diff -ruN openssh-9.4p1/aclocal.m4 openssh-9.4p1+x509-14.2.1/aclocal.m4 --- openssh-9.4p1/aclocal.m4 2023-08-10 04:11:41.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/aclocal.m4 1970-01-01 02:00:00.000000000 +0200 @@ -1,15 +0,0 @@ -# generated automatically by aclocal 1.16.5 -*- Autoconf -*- - -# Copyright (C) 1996-2021 Free Software Foundation, Inc. - -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY, to the extent permitted by law; without -# even the implied warranty of MERCHANTABILITY or FITNESS FOR A -# PARTICULAR PURPOSE. - -m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])]) -m4_include([m4/openssh.m4]) diff -ruN openssh-9.4p1/addr.c openssh-9.4p1+x509-14.2.1/addr.c --- openssh-9.4p1/addr.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/addr.c 2023-08-20 10:07:01.000000000 +0300 @@ -1,7 +1,7 @@ -/* $OpenBSD: addr.c,v 1.7 2023/03/27 03:31:05 djm Exp $ */ - +/* $OpenBSD: addr.c,v 1.6 2022/10/28 02:29:34 djm Exp $ */ /* * Copyright (c) 2004-2008 Damien Miller + * Copyright (c) 2021 Roumen Petrov. All rights reserved. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -30,9 +30,7 @@ #include "addr.h" -#define _SA(x) ((struct sockaddr *)(x)) - -int +static int addr_unicast_masklen(int af) { switch (af) { @@ -58,21 +56,19 @@ } } -int +static int addr_xaddr_to_sa(const struct xaddr *xa, struct sockaddr *sa, socklen_t *len, u_int16_t port) { - struct sockaddr_in *in4 = (struct sockaddr_in *)sa; - struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)sa; - if (xa == NULL || sa == NULL || len == NULL) return -1; switch (xa->af) { - case AF_INET: - if (*len < sizeof(*in4)) + case AF_INET: { + struct sockaddr_in *in4 = (struct sockaddr_in *)sa; + if ((size_t)*len < sizeof(*in4)) return -1; - memset(sa, '\0', sizeof(*in4)); + memset(in4, '\0', sizeof(*in4)); *len = sizeof(*in4); #ifdef SOCK_HAS_LEN in4->sin_len = sizeof(*in4); @@ -80,11 +76,12 @@ in4->sin_family = AF_INET; in4->sin_port = htons(port); memcpy(&in4->sin_addr, &xa->v4, sizeof(in4->sin_addr)); - break; - case AF_INET6: - if (*len < sizeof(*in6)) + } break; + case AF_INET6: { + struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)sa; + if ((size_t)*len < sizeof(*in6)) return -1; - memset(sa, '\0', sizeof(*in6)); + memset(in6, '\0', sizeof(*in6)); *len = sizeof(*in6); #ifdef SOCK_HAS_LEN in6->sin6_len = sizeof(*in6); @@ -95,7 +92,7 @@ #ifdef HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID in6->sin6_scope_id = xa->scope_id; #endif - break; + } break; default: return -1; } @@ -137,7 +134,11 @@ return 0; } -int +/* + * Perform bitwise negation of address + * Returns 0 on success, -1 on failure. + */ +static int addr_invert(struct xaddr *n) { int i; @@ -192,7 +193,7 @@ } } -int +static int addr_hostmask(int af, u_int l, struct xaddr *n) { if (addr_netmask(af, l, n) == -1 || addr_invert(n) == -1) @@ -227,7 +228,11 @@ } } -int +/* + * Compare addresses 'a' and 'b' + * Return 0 if addresses are identical, -1 if (a < b) or 1 if (a > b) + */ +static int addr_or(struct xaddr *dst, const struct xaddr *a, const struct xaddr *b) { int i; @@ -255,34 +260,30 @@ int i; if (a->af != b->af) - return (a->af == AF_INET6 ? 1 : -1); + return a->af == AF_INET6 ? 1 : -1; switch (a->af) { case AF_INET: - /* - * Can't just subtract here as 255.255.255.255 - 0.0.0.0 is - * too big to fit into a signed int - */ if (a->v4.s_addr == b->v4.s_addr) return 0; - return (ntohl(a->v4.s_addr) > ntohl(b->v4.s_addr) ? 1 : -1); + return ntohl(a->v4.s_addr) > ntohl(b->v4.s_addr) ? 1 : -1; case AF_INET6: - /* - * Do this a byte at a time to avoid the above issue and - * any endian problems - */ for (i = 0; i < 16; i++) if (a->addr8[i] - b->addr8[i] != 0) - return (a->addr8[i] - b->addr8[i]); + return a->addr8[i] > b->addr8[i] ? 1 : -1; if (a->scope_id == b->scope_id) - return (0); - return (a->scope_id > b->scope_id ? 1 : -1); + return 0; + return a->scope_id > b->scope_id ? 1 : -1; default: - return (-1); + return -1; } } -int +/* + * Test whether address 'a' is all zeros (i.e. 0.0.0.0 or ::) + * Returns 0 if address is all-zeros, -1 if not all zeros or on failure. + */ +static int addr_is_all0s(const struct xaddr *a) { int i; @@ -329,7 +330,7 @@ * Returns 0 if host portion of address is all-zeros, * -1 if not all zeros or on failure. */ -int +static int addr_host_is_all0s(const struct xaddr *a, u_int masklen) { struct xaddr tmp_addr, tmp_mask, tmp_result; @@ -342,20 +343,6 @@ return addr_is_all0s(&tmp_result); } -#if 0 -int -addr_host_to_all0s(struct xaddr *a, u_int masklen) -{ - struct xaddr tmp_mask; - - if (addr_netmask(a->af, masklen, &tmp_mask) == -1) - return (-1); - if (addr_and(a, a, &tmp_mask) == -1) - return (-1); - return (0); -} -#endif - int addr_host_to_all1s(struct xaddr *a, u_int masklen) { @@ -375,78 +362,55 @@ int addr_pton(const char *p, struct xaddr *n) { - struct addrinfo hints, *ai; + struct addrinfo *ai = NULL; + int ret = -1; - memset(&hints, '\0', sizeof(hints)); - hints.ai_flags = AI_NUMERICHOST; - - if (p == NULL || getaddrinfo(p, NULL, &hints, &ai) != 0) - return -1; - - if (ai == NULL) - return -1; - - if (ai->ai_addr == NULL) { - freeaddrinfo(ai); - return -1; - } - - if (n != NULL && addr_sa_to_xaddr(ai->ai_addr, ai->ai_addrlen, - n) == -1) { - freeaddrinfo(ai); - return -1; - } - - freeaddrinfo(ai); - return 0; -} - -int -addr_sa_pton(const char *h, const char *s, struct sockaddr *sa, socklen_t slen) -{ - struct addrinfo hints, *ai; + if (p == NULL) return -1; +{ struct addrinfo hints; memset(&hints, '\0', sizeof(hints)); hints.ai_flags = AI_NUMERICHOST; - if (h == NULL || getaddrinfo(h, s, &hints, &ai) != 0) + if (getaddrinfo(p, NULL, &hints, &ai) != 0) return -1; +} + if (ai == NULL) return -1; - if (ai == NULL) - return -1; + if (ai->ai_addr == NULL) goto out; - if (ai->ai_addr == NULL) { - freeaddrinfo(ai); - return -1; - } - - if (sa != NULL) { - if (slen < ai->ai_addrlen) { - freeaddrinfo(ai); - return -1; - } - memcpy(sa, &ai->ai_addr, ai->ai_addrlen); - } + if (n != NULL && + addr_sa_to_xaddr(ai->ai_addr, ai->ai_addrlen, n) == -1) + goto out; + /* success */ + ret = 0; + out: freeaddrinfo(ai); - return 0; + return ret; } +/* + * Convert address n into string 'p' + * Returns 0 on success, -1 on failure. + */ int addr_ntop(const struct xaddr *n, char *p, size_t len) { struct sockaddr_storage ss; - socklen_t slen = sizeof(ss); + struct sockaddr *sa; + socklen_t slen; - if (addr_xaddr_to_sa(n, _SA(&ss), &slen, 0) == -1) + if (n == NULL || p == NULL || len == 0) return -1; - if (p == NULL || len == 0) - return -1; - if (getnameinfo(_SA(&ss), slen, p, len, NULL, 0, - NI_NUMERICHOST) != 0) + + sa = (struct sockaddr*)&ss; + slen = sizeof(ss); + + if (addr_xaddr_to_sa(n, sa, &slen, 0) == -1) return -1; - return 0; + return getnameinfo(sa, slen, p, len, NULL, 0, NI_NUMERICHOST) != 0 + ? -1 : 0; } /* diff -ruN openssh-9.4p1/addr.h openssh-9.4p1+x509-14.2.1/addr.h --- openssh-9.4p1/addr.h 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/addr.h 2023-08-20 10:07:00.000000000 +0300 @@ -28,37 +28,25 @@ struct in_addr v4; struct in6_addr v6; u_int8_t addr8[16]; - u_int16_t addr16[8]; u_int32_t addr32[4]; } xa; /* 128-bit address */ u_int32_t scope_id; /* iface scope id for v6 */ #define v4 xa.v4 #define v6 xa.v6 #define addr8 xa.addr8 -#define addr16 xa.addr16 #define addr32 xa.addr32 }; -int addr_unicast_masklen(int af); -int addr_xaddr_to_sa(const struct xaddr *xa, struct sockaddr *sa, - socklen_t *len, u_int16_t port); int addr_sa_to_xaddr(struct sockaddr *sa, socklen_t slen, struct xaddr *xa); int addr_netmask(int af, u_int l, struct xaddr *n); -int addr_hostmask(int af, u_int l, struct xaddr *n); -int addr_invert(struct xaddr *n); int addr_pton(const char *p, struct xaddr *n); -int addr_sa_pton(const char *h, const char *s, struct sockaddr *sa, - socklen_t slen); int addr_pton_cidr(const char *p, struct xaddr *n, u_int *l); int addr_ntop(const struct xaddr *n, char *p, size_t len); int addr_and(struct xaddr *dst, const struct xaddr *a, const struct xaddr *b); -int addr_or(struct xaddr *dst, const struct xaddr *a, const struct xaddr *b); int addr_cmp(const struct xaddr *a, const struct xaddr *b); -int addr_is_all0s(const struct xaddr *n); -int addr_host_is_all0s(const struct xaddr *n, u_int masklen); -int addr_host_to_all0s(struct xaddr *a, u_int masklen); int addr_host_to_all1s(struct xaddr *a, u_int masklen); int addr_netmatch(const struct xaddr *host, const struct xaddr *net, u_int masklen); void addr_increment(struct xaddr *a); + #endif /* _ADDR_H */ diff -ruN openssh-9.4p1/addrmatch.c openssh-9.4p1+x509-14.2.1/addrmatch.c --- openssh-9.4p1/addrmatch.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/addrmatch.c 2023-08-20 10:07:01.000000000 +0300 @@ -1,5 +1,4 @@ /* $OpenBSD: addrmatch.c,v 1.17 2021/04/03 06:18:40 djm Exp $ */ - /* * Copyright (c) 2004-2008 Damien Miller * diff -ruN openssh-9.4p1/appinfo.c openssh-9.4p1+x509-14.2.1/appinfo.c --- openssh-9.4p1/appinfo.c 1970-01-01 02:00:00.000000000 +0200 +++ openssh-9.4p1+x509-14.2.1/appinfo.c 2023-08-20 10:07:01.000000000 +0300 @@ -0,0 +1,53 @@ +#ifdef __ANDROID__ +/* + * Copyright (c) 2019-2023 Roumen Petrov. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "includes.h" + +/* Android application must provide own implementation: */ +/* version 1*/ +char *get_app_etcdir(void); +char *get_app_bindir(void); +char *get_app_libexecdir(void); +/* version 2*/ +char *get2_app_etcdir(const char *cmd); +char *get2_app_bindir(const char *cmd); +char *get2_app_libexecdir(const char *cmd); + + +/*stubs*/ +/* version 1*/ +char* get_app_etcdir() { return NULL; } +char* get_app_bindir() { return NULL; } +char* get_app_libexecdir() { return NULL; } +/* version 2*/ +char *get2_app_etcdir(const char *cmd) { UNUSED(cmd); return NULL; } +char *get2_app_bindir(const char *cmd) { UNUSED(cmd); return NULL; } +char *get2_app_libexecdir(const char *cmd) { UNUSED(cmd); return NULL; } + +#else + +static void *empty_translation_unit = &empty_translation_unit; + +#endif /*def __ANDROID__*/ diff -ruN openssh-9.4p1/atomicio.c openssh-9.4p1+x509-14.2.1/atomicio.c --- openssh-9.4p1/atomicio.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/atomicio.c 2023-08-20 10:07:01.000000000 +0300 @@ -32,7 +32,7 @@ #include #ifdef HAVE_POLL_H -#include +# include #else # ifdef HAVE_SYS_POLL_H # include @@ -77,7 +77,7 @@ (void)poll(&pfd, 1, -1); continue; } - return 0; + return pos; case 0: errno = EPIPE; return pos; @@ -139,7 +139,7 @@ (void)poll(&pfd, 1, -1); continue; } - return 0; + return pos; case 0: errno = EPIPE; return pos; diff -ruN openssh-9.4p1/audit-bsm.c openssh-9.4p1+x509-14.2.1/audit-bsm.c --- openssh-9.4p1/audit-bsm.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/audit-bsm.c 2023-08-20 10:07:01.000000000 +0300 @@ -134,17 +134,17 @@ static int aug_get_machine(char *host, u_int32_t *addr, u_int32_t *type) { - struct addrinfo *ai; + struct addrinfo *ai; struct sockaddr_in *in4; struct sockaddr_in6 *in6; int ret = 0, r; if ((r = getaddrinfo(host, NULL, NULL, &ai)) != 0) { - error("BSM audit: getaddrinfo failed for %.100s: %.100s", host, + error_f("getaddrinfo failed for %.100s: %.100s", host, r == EAI_SYSTEM ? strerror(errno) : gai_strerror(r)); return -1; } - + switch (ai->ai_family) { case AF_INET: in4 = (struct sockaddr_in *)ai->ai_addr; @@ -152,14 +152,14 @@ memcpy(addr, &in4->sin_addr, sizeof(struct in_addr)); break; #ifdef AU_IPv6 - case AF_INET6: + case AF_INET6: in6 = (struct sockaddr_in6 *)ai->ai_addr; *type = AU_IPv6; memcpy(addr, &in6->sin6_addr, sizeof(struct in6_addr)); break; #endif default: - error("BSM audit: unknown address family for %.100s: %d", + error_f("unknown address family for %.100s: %d", host, ai->ai_family); ret = -1; } @@ -188,35 +188,35 @@ * in case of error and set errno to indicate the error. We don't * bother with errno here, though, since the only use of this function * below doesn't check for errors anyway. - */ + */ handle = scf_handle_create(SCF_VERSION); - if (handle == NULL) + if (handle == NULL) return -2; ret = scf_handle_bind(handle); - if (ret == -1) + if (ret == -1) return -2; property = scf_property_create(handle); - if (property == NULL) + if (property == NULL) return -2; - ret = scf_handle_decode_fmri(handle, + ret = scf_handle_decode_fmri(handle, "svc:/system/auditd:default/:properties/preselection/naflags", NULL, NULL, NULL, NULL, property, 0); - if (ret == -1) + if (ret == -1) return -2; value = scf_value_create(handle); - if (value == NULL) + if (value == NULL) return -2; ret = scf_property_get_value(property, value); - if (ret == -1) + if (ret == -1) return -2; ret = scf_value_get_astring(value, auditstring, len); - if (ret == -1) + if (ret == -1) return -2; scf_value_destroy(value); @@ -267,11 +267,11 @@ rc = (typ == 0) ? 0 : -1; sel = selected(the_authctxt->user, uid, event_no, rc); - debug3("BSM audit: typ %d rc %d \"%s\"", typ, rc, string); + debug3_f("typ %d rc %d \"%s\"", typ, rc, string); if (!sel) return; /* audit event does not match mask, do not write */ - debug3("BSM audit: writing audit new record"); + debug3_f("writing audit new record"); ad = au_open(); (void) au_write(ad, AUToSubjectFunc(uid, uid, gid, uid, gid, @@ -290,8 +290,8 @@ #endif if (rc < 0) - error("BSM audit: %s failed to write \"%s\" record: %s", - __func__, string, strerror(errno)); + error_f("failed to write \"%s\" record: %s", + string, strerror(errno)); } static void @@ -302,7 +302,7 @@ au_mask_t mask; if (the_authctxt == NULL) { - error("BSM audit: session setup internal error (NULL ctxt)"); + error_f("internal error (NULL ctxt)"); return; } @@ -323,8 +323,7 @@ rc = SetAuditFunc(&info, sizeof(info)); if (rc < 0) - error("BSM audit: %s: %s failed: %s", __func__, - SetAuditFuncText, strerror(errno)); + error_f("%s failed: %s", SetAuditFuncText, strerror(errno)); } static void @@ -355,7 +354,7 @@ if (cannot_audit(0)) return; - debug3("BSM audit: connection from %.100s port %d", host, port); + debug3_f("%.100s port %d", host, port); /* populate our terminal id structure */ #if defined(HAVE_GETAUDIT_ADDR) @@ -363,13 +362,13 @@ aug_get_machine((char *)host, &(tid->at_addr[0]), &(tid->at_type)); snprintf(buf, sizeof(buf), "%08x %08x %08x %08x", tid->at_addr[0], tid->at_addr[1], tid->at_addr[2], tid->at_addr[3]); - debug3("BSM audit: iptype %d machine ID %s", (int)tid->at_type, buf); + debug3_f("iptype %d machine ID %s", (int)tid->at_type, buf); #else /* this is used on IPv4-only machines */ tid->port = (dev_t)port; tid->machine = inet_addr(host); snprintf(buf, sizeof(buf), "%08x", tid->machine); - debug3("BSM audit: machine ID %s", buf); + debug3_f("machine ID %s", buf); #endif } @@ -398,6 +397,7 @@ static int logged_in = 0; const char *user = the_authctxt ? the_authctxt->user : "(unknown user)"; + UNUSED(ssh); if (cannot_audit(0)) return; @@ -420,8 +420,7 @@ gettext("sshd logout %s"), the_authctxt->user); bsm_audit_record(0, textbuf, AUE_logout); } else { - debug("%s: connection closed without authentication", - __func__); + debug_f("connection closed without authentication"); } break; @@ -449,7 +448,7 @@ break; default: - debug("%s: unhandled event %d", __func__, event); + debug_f("unhandled event %d", event); } } #endif /* BSM */ diff -ruN openssh-9.4p1/audit.c openssh-9.4p1+x509-14.2.1/audit.c --- openssh-9.4p1/audit.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/audit.c 2023-08-20 10:07:01.000000000 +0300 @@ -35,10 +35,12 @@ #include "hostfile.h" #include "auth.h" +const char *audit_username(void); + /* * Care must be taken when using this since it WILL NOT be initialized when * audit_connection_from() is called and MAY NOT be initialized when - * audit_event(CONNECTION_ABANDON) is called. Test for NULL before using. + * audit_event(..., CONNECTION_ABANDON) is called. Test for NULL before using. */ extern Authctxt *the_authctxt; @@ -53,8 +55,7 @@ else if (strcmp(method, "publickey") == 0 || strcmp(method, "rsa") == 0) return SSH_AUTH_FAIL_PUBKEY; - else if (strncmp(method, "keyboard-interactive", 20) == 0 || - strcmp(method, "challenge-response") == 0) + else if (strncmp(method, "keyboard-interactive", 20) == 0) return SSH_AUTH_FAIL_KBDINT; else if (strcmp(method, "hostbased") == 0 || strcmp(method, "rhosts-rsa") == 0) @@ -79,7 +80,8 @@ return (the_authctxt->user); } -const char * +# ifndef CUSTOM_SSH_AUDIT_EVENTS +static const char * audit_event_lookup(ssh_audit_event_t ev) { int i; @@ -109,7 +111,6 @@ return(event_lookup[i].name); } -# ifndef CUSTOM_SSH_AUDIT_EVENTS /* * Null implementations of audit functions. * These get used if SSH_AUDIT_EVENTS is defined but no audit module is enabled. @@ -133,6 +134,7 @@ void audit_event(struct ssh *ssh, ssh_audit_event_t event) { + UNUSED(ssh); debug("audit event euid %d user %s event %d (%s)", geteuid(), audit_username(), event, audit_event_lookup(event)); } @@ -147,7 +149,7 @@ void audit_session_open(struct logininfo *li) { - const char *t = li->line ? li->line : "(no tty)"; + const char *t = li->line[0] != '\0' ? li->line : "(no tty)"; debug("audit session open euid %d user %s tty name %s", geteuid(), audit_username(), t); @@ -163,7 +165,7 @@ void audit_session_close(struct logininfo *li) { - const char *t = li->line ? li->line : "(no tty)"; + const char *t = li->line[0] != '\0' ? li->line : "(no tty)"; debug("audit session close euid %d user %s tty name %s", geteuid(), audit_username(), t); diff -ruN openssh-9.4p1/audit.h openssh-9.4p1+x509-14.2.1/audit.h --- openssh-9.4p1/audit.h 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/audit.h 2023-08-20 10:07:00.000000000 +0300 @@ -35,7 +35,7 @@ SSH_AUTH_SUCCESS, SSH_AUTH_FAIL_NONE, SSH_AUTH_FAIL_PASSWD, - SSH_AUTH_FAIL_KBDINT, /* keyboard-interactive or challenge-response */ + SSH_AUTH_FAIL_KBDINT, /* keyboard-interactive */ SSH_AUTH_FAIL_PUBKEY, /* ssh2 pubkey or ssh1 rsa */ SSH_AUTH_FAIL_HOSTBASED, /* ssh2 hostbased or ssh1 rhostsrsa */ SSH_AUTH_FAIL_GSSAPI, diff -ruN openssh-9.4p1/audit-linux.c openssh-9.4p1+x509-14.2.1/audit-linux.c --- openssh-9.4p1/audit-linux.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/audit-linux.c 2023-08-20 10:07:01.000000000 +0300 @@ -38,7 +38,7 @@ const char *audit_username(void); -int +static int linux_audit_record_event(int uid, const char *username, const char *hostname, const char *ip, const char *ttyn, int success) { @@ -74,12 +74,14 @@ audit_connection_from(const char *host, int port) { /* not implemented */ + UNUSED(host); UNUSED(port); } void audit_run_command(const char *command) { /* not implemented */ + UNUSED(command); } void @@ -87,13 +89,14 @@ { if (linux_audit_record_event(li->uid, NULL, li->hostname, NULL, li->line, 1) == 0) - fatal("linux_audit_write_entry failed: %s", strerror(errno)); + fatal("linux_audit_record_event failed: %s", strerror(errno)); } void audit_session_close(struct logininfo *li) { /* not implemented */ + UNUSED(li); } void @@ -102,6 +105,7 @@ switch(event) { case SSH_AUTH_SUCCESS: case SSH_CONNECTION_CLOSE: + case SSH_CONNECTION_ABANDON: case SSH_NOLOGIN: case SSH_LOGIN_EXCEED_MAXTRIES: case SSH_LOGIN_ROOT_DENIED: @@ -117,7 +121,7 @@ ssh_remote_ipaddr(ssh), "sshd", 0); break; default: - debug("%s: unhandled event %d", __func__, event); + debug_f("unhandled event %d", event); break; } } diff -ruN openssh-9.4p1/a_utf8.c openssh-9.4p1+x509-14.2.1/a_utf8.c --- openssh-9.4p1/a_utf8.c 1970-01-01 02:00:00.000000000 +0200 +++ openssh-9.4p1+x509-14.2.1/a_utf8.c 2023-08-20 10:07:01.000000000 +0300 @@ -0,0 +1,192 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "evp-compat.h" + +#ifdef HAVE_UTF8_GETC + +typedef int a_utf8_empty_translation_unit; + +#else +/* UTF8 utilities */ + +/*- + * This parses a UTF8 string one character at a time. It is passed a pointer + * to the string and the length of the string. It sets 'value' to the value of + * the current character. It returns the number of characters read or a + * negative error code: + * -1 = string too short + * -2 = illegal character + * -3 = subsequent characters not of the form 10xxxxxx + * -4 = character encoded incorrectly (not minimal length). + */ + +int UTF8_getc(const unsigned char *str, int len, unsigned long *val) +{ + const unsigned char *p; + unsigned long value; + int ret; + if (len <= 0) + return 0; + p = str; + + /* Check syntax and work out the encoded value (if correct) */ + if ((*p & 0x80) == 0) { + value = *p++ & 0x7f; + ret = 1; + } else if ((*p & 0xe0) == 0xc0) { + if (len < 2) + return -1; + if ((p[1] & 0xc0) != 0x80) + return -3; + value = (*p++ & 0x1f) << 6; + value |= *p++ & 0x3f; + if (value < 0x80) + return -4; + ret = 2; + } else if ((*p & 0xf0) == 0xe0) { + if (len < 3) + return -1; + if (((p[1] & 0xc0) != 0x80) + || ((p[2] & 0xc0) != 0x80)) + return -3; + value = (*p++ & 0xf) << 12; + value |= (*p++ & 0x3f) << 6; + value |= *p++ & 0x3f; + if (value < 0x800) + return -4; + ret = 3; + } else if ((*p & 0xf8) == 0xf0) { + if (len < 4) + return -1; + if (((p[1] & 0xc0) != 0x80) + || ((p[2] & 0xc0) != 0x80) + || ((p[3] & 0xc0) != 0x80)) + return -3; + value = ((unsigned long)(*p++ & 0x7)) << 18; + value |= (*p++ & 0x3f) << 12; + value |= (*p++ & 0x3f) << 6; + value |= *p++ & 0x3f; + if (value < 0x10000) + return -4; + ret = 4; + } else if ((*p & 0xfc) == 0xf8) { + if (len < 5) + return -1; + if (((p[1] & 0xc0) != 0x80) + || ((p[2] & 0xc0) != 0x80) + || ((p[3] & 0xc0) != 0x80) + || ((p[4] & 0xc0) != 0x80)) + return -3; + value = ((unsigned long)(*p++ & 0x3)) << 24; + value |= ((unsigned long)(*p++ & 0x3f)) << 18; + value |= ((unsigned long)(*p++ & 0x3f)) << 12; + value |= (*p++ & 0x3f) << 6; + value |= *p++ & 0x3f; + if (value < 0x200000) + return -4; + ret = 5; + } else if ((*p & 0xfe) == 0xfc) { + if (len < 6) + return -1; + if (((p[1] & 0xc0) != 0x80) + || ((p[2] & 0xc0) != 0x80) + || ((p[3] & 0xc0) != 0x80) + || ((p[4] & 0xc0) != 0x80) + || ((p[5] & 0xc0) != 0x80)) + return -3; + value = ((unsigned long)(*p++ & 0x1)) << 30; + value |= ((unsigned long)(*p++ & 0x3f)) << 24; + value |= ((unsigned long)(*p++ & 0x3f)) << 18; + value |= ((unsigned long)(*p++ & 0x3f)) << 12; + value |= (*p++ & 0x3f) << 6; + value |= *p++ & 0x3f; + if (value < 0x4000000) + return -4; + ret = 6; + } else + return -2; + *val = value; + return ret; +} + +/* + * This takes a character 'value' and writes the UTF8 encoded value in 'str' + * where 'str' is a buffer containing 'len' characters. Returns the number of + * characters written or -1 if 'len' is too small. 'str' can be set to NULL + * in which case it just returns the number of characters. It will need at + * most 6 characters. + */ + +int UTF8_putc(unsigned char *str, int len, unsigned long value) +{ + if (!str) + len = 6; /* Maximum we will need */ + else if (len <= 0) + return -1; + if (value < 0x80) { + if (str) + *str = (unsigned char)value; + return 1; + } + if (value < 0x800) { + if (len < 2) + return -1; + if (str) { + *str++ = (unsigned char)(((value >> 6) & 0x1f) | 0xc0); + *str = (unsigned char)((value & 0x3f) | 0x80); + } + return 2; + } + if (value < 0x10000) { + if (len < 3) + return -1; + if (str) { + *str++ = (unsigned char)(((value >> 12) & 0xf) | 0xe0); + *str++ = (unsigned char)(((value >> 6) & 0x3f) | 0x80); + *str = (unsigned char)((value & 0x3f) | 0x80); + } + return 3; + } + if (value < 0x200000) { + if (len < 4) + return -1; + if (str) { + *str++ = (unsigned char)(((value >> 18) & 0x7) | 0xf0); + *str++ = (unsigned char)(((value >> 12) & 0x3f) | 0x80); + *str++ = (unsigned char)(((value >> 6) & 0x3f) | 0x80); + *str = (unsigned char)((value & 0x3f) | 0x80); + } + return 4; + } + if (value < 0x4000000) { + if (len < 5) + return -1; + if (str) { + *str++ = (unsigned char)(((value >> 24) & 0x3) | 0xf8); + *str++ = (unsigned char)(((value >> 18) & 0x3f) | 0x80); + *str++ = (unsigned char)(((value >> 12) & 0x3f) | 0x80); + *str++ = (unsigned char)(((value >> 6) & 0x3f) | 0x80); + *str = (unsigned char)((value & 0x3f) | 0x80); + } + return 5; + } + if (len < 6) + return -1; + if (str) { + *str++ = (unsigned char)(((value >> 30) & 0x1) | 0xfc); + *str++ = (unsigned char)(((value >> 24) & 0x3f) | 0x80); + *str++ = (unsigned char)(((value >> 18) & 0x3f) | 0x80); + *str++ = (unsigned char)(((value >> 12) & 0x3f) | 0x80); + *str++ = (unsigned char)(((value >> 6) & 0x3f) | 0x80); + *str = (unsigned char)((value & 0x3f) | 0x80); + } + return 6; +} +#endif /*ndef HAVE_UTF8_GETC*/ diff -ruN openssh-9.4p1/auth2.c openssh-9.4p1+x509-14.2.1/auth2.c --- openssh-9.4p1/auth2.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/auth2.c 2023-08-20 10:07:01.000000000 +0300 @@ -51,7 +51,6 @@ #include "auth.h" #include "dispatch.h" #include "pathnames.h" -#include "ssherr.h" #ifdef GSSAPI #include "ssh-gss.h" #endif @@ -91,7 +90,6 @@ static int input_userauth_request(int, u_int32_t, struct ssh *); /* helper */ -static Authmethod *authmethod_byname(const char *); static Authmethod *authmethod_lookup(Authctxt *, const char *); static char *authmethods_get(Authctxt *authctxt); @@ -144,7 +142,7 @@ (r = sshpkt_put_cstring(ssh, "")) != 0 || /* language, unused */ (r = sshpkt_send(ssh)) != 0) fatal_fr(r, "send packet"); - debug("%s: sent", __func__); + debug_f("sent"); } static void @@ -184,12 +182,14 @@ char *service = NULL; int r, acceptit = 0; + UNUSED(type); + UNUSED(seq); if ((r = sshpkt_get_cstring(ssh, &service, NULL)) != 0 || (r = sshpkt_get_end(ssh)) != 0) goto out; if (authctxt == NULL) - fatal("input_service_request: no authctxt"); + fatal_f("no authctxt"); if (strcmp(service, "ssh-userauth") == 0) { if (!authctxt->success) { @@ -211,7 +211,7 @@ debug("bad service request %s", service); ssh_packet_disconnect(ssh, "bad service request %s", service); } - r = 0; + out: free(service); return r; @@ -222,13 +222,18 @@ user_specific_delay(const char *user) { char b[512]; - size_t len = ssh_digest_bytes(SSH_DIGEST_SHA512); - u_char *hash = xmalloc(len); + int digest_alg; + size_t len; + u_char *hash; double delay; + digest_alg = ssh_digest_maxbytes(); + len = ssh_digest_bytes(digest_alg); + hash = xmalloc(len); + (void)snprintf(b, sizeof b, "%llu%s", (unsigned long long)options.timing_secret, user); - if (ssh_digest_memory(SSH_DIGEST_SHA512, b, strlen(b), hash, len) != 0) + if (ssh_digest_memory(digest_alg, b, strlen(b), hash, len) != 0) fatal_f("ssh_digest_memory"); /* 0-4.2 ms of delay */ delay = (double)PEEK_U32(hash) / 1000 / 1000 / 1000 / 1000; @@ -263,8 +268,10 @@ int r, authenticated = 0; double tstart = monotime_double(); + UNUSED(type); + UNUSED(seq); if (authctxt == NULL) - fatal("input_userauth_request: no authctxt"); + fatal_f("no authctxt"); if ((r = sshpkt_get_cstring(ssh, &user, NULL)) != 0 || (r = sshpkt_get_cstring(ssh, &service, NULL)) != 0 || @@ -331,14 +338,14 @@ /* try to authenticate user */ m = authmethod_lookup(authctxt, method); if (m != NULL && authctxt->failures < options.max_authtries) { - debug2("input_userauth_request: try method %s", method); - authenticated = m->userauth(ssh, method); + debug2_f("try method %s", method); + authenticated = m->userauth(ssh); } if (!authctxt->authenticated) ensure_minimum_time_since(tstart, user_specific_delay(authctxt->user)); userauth_finish(ssh, authenticated, method, NULL); - r = 0; + out: free(service); free(user); @@ -347,26 +354,19 @@ } void -userauth_finish(struct ssh *ssh, int authenticated, const char *packet_method, +userauth_finish(struct ssh *ssh, int authenticated, const char *method, const char *submethod) { Authctxt *authctxt = ssh->authctxt; - Authmethod *m = NULL; - const char *method = packet_method; char *methods; int r, partial = 0; if (authenticated) { - if (!authctxt->valid) { + if (!authctxt->valid) fatal("INTERNAL ERROR: authenticated invalid user %s", authctxt->user); - } if (authctxt->postponed) fatal("INTERNAL ERROR: authenticated and postponed"); - /* prefer primary authmethod name to possible synonym */ - if ((m = authmethod_byname(method)) == NULL) - fatal("INTERNAL ERROR: bad method %s", method); - method = m->name; } /* Special handling for root */ @@ -397,13 +397,12 @@ #ifdef USE_PAM if (options.use_pam && authenticated) { - int r, success = PRIVSEP(do_pam_account()); + int success = PRIVSEP(do_pam_account()); /* If PAM returned a message, send it to the user. */ if (sshbuf_len(loginmsg) > 0) { if ((r = sshbuf_put(loginmsg, "\0", 1)) != 0) - fatal("%s: buffer error: %s", - __func__, ssh_err(r)); + fatal_fr(r, "buffer error"); userauth_send_banner(ssh, sshbuf_ptr(loginmsg)); if ((r = ssh_packet_write_wait(ssh)) != 0) { sshpkt_fatal(ssh, r, @@ -506,42 +505,23 @@ } static Authmethod * -authmethod_byname(const char *name) +authmethod_lookup(Authctxt *authctxt, const char *name) { int i; - if (name == NULL) - fatal_f("NULL authentication method name"); - for (i = 0; authmethods[i] != NULL; i++) { - if (strcmp(name, authmethods[i]->name) == 0 || - (authmethods[i]->synonym != NULL && - strcmp(name, authmethods[i]->synonym) == 0)) - return authmethods[i]; - } - debug_f("unrecognized authentication method name: %s", name); + if (name != NULL) + for (i = 0; authmethods[i] != NULL; i++) + if (authmethods[i]->enabled != NULL && + *(authmethods[i]->enabled) != 0 && + strcmp(name, authmethods[i]->name) == 0 && + auth2_method_allowed(authctxt, + authmethods[i]->name, NULL)) + return authmethods[i]; + debug2("Unrecognized authentication method name: %s", + name ? name : "NULL"); return NULL; } -static Authmethod * -authmethod_lookup(Authctxt *authctxt, const char *name) -{ - Authmethod *method; - - if ((method = authmethod_byname(name)) == NULL) - return NULL; - - if (method->enabled == NULL || *(method->enabled) == 0) { - debug3_f("method %s not enabled", name); - return NULL; - } - if (!auth2_method_allowed(authctxt, method->name, NULL)) { - debug3_f("method %s not allowed " - "by AuthenticationMethods", name); - return NULL; - } - return method; -} - /* * Check a comma-separated list of methods for validity. Is need_enable is * non-zero, then also require that the methods are enabled. @@ -741,7 +721,7 @@ i = vasprintf(&authctxt->auth_method_info, fmt, ap); va_end(ap); - if (i == -1) + if (i < 0) fatal_f("vasprintf failed"); } diff -ruN openssh-9.4p1/auth2-chall.c openssh-9.4p1+x509-14.2.1/auth2-chall.c --- openssh-9.4p1/auth2-chall.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/auth2-chall.c 2023-08-20 10:07:01.000000000 +0300 @@ -35,13 +35,11 @@ #include "xmalloc.h" #include "ssh2.h" -#include "sshkey.h" #include "hostfile.h" #include "auth.h" #include "sshbuf.h" #include "packet.h" #include "dispatch.h" -#include "ssherr.h" #include "log.h" #include "misc.h" #include "servconf.h" @@ -124,7 +122,7 @@ } else { kbdintctxt->devices = xstrdup(devs); } - debug("kbdint_alloc: devices '%s'", kbdintctxt->devices); + debug_f("devices '%s'", kbdintctxt->devices); kbdintctxt->ctxt = NULL; kbdintctxt->device = NULL; kbdintctxt->nreq = 0; @@ -178,7 +176,7 @@ t = kbdintctxt->devices; kbdintctxt->devices = t[len] ? xstrdup(t+len+1) : NULL; free(t); - debug2("kbdint_next_device: devices %s", kbdintctxt->devices ? + debug2_f("devices %s", kbdintctxt->devices ? kbdintctxt->devices : ""); } while (kbdintctxt->devices && !kbdintctxt->device); @@ -186,14 +184,14 @@ } /* - * try challenge-response, set authctxt->postponed if we have to + * try keyboard-interactive, set authctxt->postponed if we have to * wait for the response. */ int auth2_challenge(struct ssh *ssh, char *devs) { Authctxt *authctxt = ssh->authctxt; - debug("auth2_challenge: user=%s devs=%s", + debug_f("user=%s devs=%s", authctxt->user ? authctxt->user : "", devs ? devs : ""); @@ -224,14 +222,14 @@ Authctxt *authctxt = ssh->authctxt; KbdintAuthctxt *kbdintctxt = authctxt->kbdintctxt; - debug2("auth2_challenge_start: devices %s", + debug2_f("devices %s", kbdintctxt->devices ? kbdintctxt->devices : ""); if (kbdint_next_device(authctxt, kbdintctxt) == 0) { auth2_challenge_stop(ssh); return 0; } - debug("auth2_challenge_start: trying authentication method '%s'", + debug_f("trying authentication method '%s'", kbdintctxt->device->name); if ((kbdintctxt->ctxt = kbdintctxt->device->init_ctx(authctxt)) == NULL) { @@ -293,10 +291,12 @@ KbdintAuthctxt *kbdintctxt; int authenticated = 0, res; int r; - u_int i, nresp; + u_int32_t i, nresp; const char *devicename = NULL; char **response = NULL; + UNUSED(type); + UNUSED(seq); if (authctxt == NULL) fatal_f("no authctxt"); kbdintctxt = authctxt->kbdintctxt; @@ -314,20 +314,17 @@ fatal_f("too many replies"); if (nresp > 0) { response = xcalloc(nresp, sizeof(char *)); - for (i = 0; i < nresp; i++) { + for (i = 0; i < nresp; i++) if ((r = sshpkt_get_cstring(ssh, &response[i], NULL)) != 0) fatal_fr(r, "parse response"); - } } if ((r = sshpkt_get_end(ssh)) != 0) fatal_fr(r, "parse packet"); res = kbdintctxt->device->respond(kbdintctxt->ctxt, nresp, response); - for (i = 0; i < nresp; i++) { - explicit_bzero(response[i], strlen(response[i])); - free(response[i]); - } + for (i = 0; i < nresp; i++) + freezero(response[i], strlen(response[i])); free(response); switch (res) { diff -ruN openssh-9.4p1/auth2-gss.c openssh-9.4p1+x509-14.2.1/auth2-gss.c --- openssh-9.4p1/auth2-gss.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/auth2-gss.c 2023-08-20 10:07:01.000000000 +0300 @@ -1,5 +1,4 @@ /* $OpenBSD: auth2-gss.c,v 1.34 2023/03/31 04:22:27 djm Exp $ */ - /* * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved. * @@ -40,7 +39,6 @@ #include "log.h" #include "dispatch.h" #include "sshbuf.h" -#include "ssherr.h" #include "misc.h" #include "servconf.h" #include "packet.h" @@ -62,7 +60,7 @@ * how to check local user kuserok and the like) */ static int -userauth_gssapi(struct ssh *ssh, const char *method) +userauth_gssapi(struct ssh *ssh) { Authctxt *authctxt = ssh->authctxt; gss_OID_desc goid = {0, NULL}; @@ -77,10 +75,10 @@ fatal_fr(r, "parse packet"); if (mechs == 0) { - logit_f("mechanism negotiation is not supported"); + logit("Mechanism negotiation is not supported"); return (0); } else if (mechs > SSH_GSSAPI_MAX_MECHS) { - logit_f("too many mechanisms requested %u > %u", mechs, + logit("Too many mechanisms requested %u > %u", mechs, SSH_GSSAPI_MAX_MECHS); return (0); } @@ -100,7 +98,7 @@ goid.length = len - 2; ssh_gssapi_test_oid_supported(&ms, &goid, &present); } else { - logit_f("badly formed OID received"); + logit("Badly formed OID received"); } } while (mechs > 0 && !present); @@ -153,6 +151,8 @@ size_t len; int r; + UNUSED(type); + UNUSED(plen); if (authctxt == NULL || (authctxt->methoddata == NULL && !use_privsep)) fatal("No authentication or GSSAPI context"); @@ -217,6 +217,8 @@ u_char *p; size_t len; + UNUSED(type); + UNUSED(plen); if (authctxt == NULL || (authctxt->methoddata == NULL && !use_privsep)) fatal("No authentication or GSSAPI context"); @@ -256,6 +258,8 @@ int r, authenticated; const char *displayname; + UNUSED(type); + UNUSED(plen); if (authctxt == NULL || (authctxt->methoddata == NULL && !use_privsep)) fatal("No authentication or GSSAPI context"); @@ -294,6 +298,8 @@ u_char *p; size_t len; + UNUSED(type); + UNUSED(plen); if (authctxt == NULL || (authctxt->methoddata == NULL && !use_privsep)) fatal("No authentication or GSSAPI context"); @@ -335,7 +341,6 @@ Authmethod method_gssapi = { "gssapi-with-mic", - NULL, userauth_gssapi, &options.gss_authentication }; diff -ruN openssh-9.4p1/auth2-hostbased.c openssh-9.4p1+x509-14.2.1/auth2-hostbased.c --- openssh-9.4p1/auth2-hostbased.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/auth2-hostbased.c 2023-08-20 10:07:01.000000000 +0300 @@ -1,6 +1,7 @@ /* $OpenBSD: auth2-hostbased.c,v 1.52 2023/03/05 05:34:09 dtucker Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. + * Copyright (c) 2004-2022 Roumen Petrov. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -40,7 +41,7 @@ #include "log.h" #include "misc.h" #include "servconf.h" -#include "sshkey.h" +#include "sshxkey.h" #include "hostfile.h" #include "auth.h" #include "canohost.h" @@ -55,18 +56,40 @@ /* import */ extern ServerOptions options; +/* return 1 if given hostbased algorithm is allowed */ static int -userauth_hostbased(struct ssh *ssh, const char *method) +hostbased_algorithm_allowed(const char* pkalg) +{ + if ( + (options.hostbased_algorithms != NULL) && + (match_pattern_list(pkalg, options.hostbased_algorithms, 0) != 1) + ) { + debug("disallowed hostbased algorithm: %s", pkalg); + return 0; + } + + if ( + (options.accepted_algorithms != NULL) && + (match_pattern_list(pkalg, options.accepted_algorithms, 0) != 1) + ) { + debug("non-accepted hostbased algorithm: %s", pkalg); + return 0; + } + + return 1; +} + +static int +userauth_hostbased(struct ssh *ssh) { Authctxt *authctxt = ssh->authctxt; struct sshbuf *b; struct sshkey *key = NULL; - char *pkalg, *cuser, *chost; - u_char *pkblob, *sig; + char *pkalg = NULL, *cuser = NULL, *chost = NULL; + u_char *pkblob = NULL, *sig = NULL; size_t alen, blen, slen; int r, pktype, authenticated = 0; - /* XXX use sshkey_froms() */ if ((r = sshpkt_get_cstring(ssh, &pkalg, &alen)) != 0 || (r = sshpkt_get_string(ssh, &pkblob, &blen)) != 0 || (r = sshpkt_get_cstring(ssh, &chost, NULL)) != 0 || @@ -83,12 +106,13 @@ pktype = sshkey_type_from_name(pkalg); if (pktype == KEY_UNSPEC) { /* this is perfectly legal */ - logit_f("unsupported public key algorithm: %s", - pkalg); + verbose("Unsupported public key algorithm: %s", pkalg); goto done; } - if ((r = sshkey_from_blob(pkblob, blen, &key)) != 0) { - error_fr(r, "key_from_blob"); + if (!hostbased_algorithm_allowed(pkalg)) goto done; + + if ((r = Xkey_from_blob(pkalg, pkblob, blen, &key)) != 0) { + error_fr(r, "Xkey_from_blob"); goto done; } if (key == NULL) { @@ -100,23 +124,20 @@ "(received %d, expected %d)", key->type, pktype); goto done; } - if (match_pattern_list(pkalg, options.hostbased_accepted_algos, 0) != 1) { - logit_f("signature algorithm %s not in " - "HostbasedAcceptedAlgorithms", pkalg); - goto done; - } if ((r = sshkey_check_cert_sigtype(key, options.ca_sign_algorithms)) != 0) { - logit_fr(r, "certificate signature algorithm %s", + error_r(r, "Certificate signature algorithm %s", (key->cert == NULL || key->cert->signature_type == NULL) ? "(null)" : key->cert->signature_type); goto done; } - if ((r = sshkey_check_rsa_length(key, - options.required_rsa_size)) != 0) { - logit_r(r, "refusing %s key", sshkey_type(key)); +#if 0 + /* NOTE: key size is validated on read, sign and verify */ + if ((r = sshkey_check_length(key)) != 0) { + error_r(r, "refusing %s key", sshkey_type(key)); goto done; } +#endif if (!authctxt->valid || authctxt->user == NULL) { debug2_f("disabled because of invalid user"); @@ -130,7 +151,7 @@ (r = sshbuf_put_u8(b, SSH2_MSG_USERAUTH_REQUEST)) != 0 || (r = sshbuf_put_cstring(b, authctxt->user)) != 0 || (r = sshbuf_put_cstring(b, authctxt->service)) != 0 || - (r = sshbuf_put_cstring(b, method)) != 0 || + (r = sshbuf_put_cstring(b, "hostbased")) != 0 || (r = sshbuf_put_string(b, pkalg, alen)) != 0 || (r = sshbuf_put_string(b, pkblob, blen)) != 0 || (r = sshbuf_put_cstring(b, chost)) != 0 || @@ -145,16 +166,19 @@ /* test for allowed key and correct signature */ authenticated = 0; - if (PRIVSEP(hostbased_key_allowed(ssh, authctxt->pw, cuser, - chost, key)) && - PRIVSEP(sshkey_verify(key, sig, slen, - sshbuf_ptr(b), sshbuf_len(b), pkalg, ssh->compat, NULL)) == 0) +{ ssh_verify_ctx ctx = { pkalg, key, &ssh->compat }; + + if (PRIVSEP(hostbased_xkey_allowed(ssh, authctxt->pw, &ctx, + cuser, chost)) && + PRIVSEP(Xkey_verify(&ctx, sig, slen, + sshbuf_ptr(b), sshbuf_len(b))) == 0) authenticated = 1; +} auth2_record_key(authctxt, authenticated, key); sshbuf_free(b); done: - debug2_f("authenticated %d", authenticated); + debug2_f("authenticated %d pkalg %s", authenticated, pkalg); sshkey_free(key); free(pkalg); free(pkblob); @@ -166,9 +190,10 @@ /* return 1 if given hostkey is allowed */ int -hostbased_key_allowed(struct ssh *ssh, struct passwd *pw, - const char *cuser, char *chost, struct sshkey *key) +hostbased_xkey_allowed(struct ssh *ssh, struct passwd *pw, + ssh_verify_ctx *ctx, const char *cuser, char *chost) { + struct sshkey *key = ctx->key; const char *resolvedname, *ipaddr, *lookup, *reason; HostStatus host_status; int len; @@ -253,7 +278,6 @@ Authmethod method_hostbased = { "hostbased", - NULL, userauth_hostbased, &options.hostbased_authentication }; diff -ruN openssh-9.4p1/auth2-kbdint.c openssh-9.4p1+x509-14.2.1/auth2-kbdint.c --- openssh-9.4p1/auth2-kbdint.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/auth2-kbdint.c 2023-08-20 10:07:01.000000000 +0300 @@ -1,4 +1,4 @@ -/* $OpenBSD: auth2-kbdint.c,v 1.14 2021/12/19 22:12:07 djm Exp $ */ +/* $OpenBSD: auth2-kbdint.c,v 1.13 2021/07/02 05:11:20 dtucker Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * @@ -38,13 +38,12 @@ #include "log.h" #include "misc.h" #include "servconf.h" -#include "ssherr.h" /* import */ extern ServerOptions options; static int -userauth_kbdint(struct ssh *ssh, const char *method) +userauth_kbdint(struct ssh *ssh) { int r, authenticated = 0; char *lang, *devs; @@ -66,7 +65,6 @@ Authmethod method_kbdint = { "keyboard-interactive", - NULL, userauth_kbdint, &options.kbd_interactive_authentication }; diff -ruN openssh-9.4p1/auth2-none.c openssh-9.4p1+x509-14.2.1/auth2-none.c --- openssh-9.4p1/auth2-none.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/auth2-none.c 2023-08-20 10:07:01.000000000 +0300 @@ -37,7 +37,6 @@ #include "atomicio.h" #include "xmalloc.h" -#include "sshkey.h" #include "hostfile.h" #include "auth.h" #include "packet.h" @@ -45,7 +44,6 @@ #include "misc.h" #include "servconf.h" #include "ssh2.h" -#include "ssherr.h" #ifdef GSSAPI #include "ssh-gss.h" #endif @@ -58,7 +56,7 @@ static int none_enabled = 1; static int -userauth_none(struct ssh *ssh, const char *method) +userauth_none(struct ssh *ssh) { int r; @@ -72,7 +70,6 @@ Authmethod method_none = { "none", - NULL, userauth_none, &none_enabled }; diff -ruN openssh-9.4p1/auth2-passwd.c openssh-9.4p1+x509-14.2.1/auth2-passwd.c --- openssh-9.4p1/auth2-passwd.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/auth2-passwd.c 2023-08-20 10:07:01.000000000 +0300 @@ -33,9 +33,7 @@ #include #include "packet.h" -#include "ssherr.h" #include "log.h" -#include "sshkey.h" #include "hostfile.h" #include "auth.h" #ifdef GSSAPI @@ -49,7 +47,7 @@ extern ServerOptions options; static int -userauth_passwd(struct ssh *ssh, const char *method) +userauth_passwd(struct ssh *ssh) { char *password = NULL; int authenticated = 0, r; @@ -74,7 +72,6 @@ Authmethod method_passwd = { "password", - NULL, userauth_passwd, &options.password_authentication }; diff -ruN openssh-9.4p1/auth2-pubkey.c openssh-9.4p1+x509-14.2.1/auth2-pubkey.c --- openssh-9.4p1/auth2-pubkey.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/auth2-pubkey.c 2023-08-20 10:07:01.000000000 +0300 @@ -1,7 +1,7 @@ /* $OpenBSD: auth2-pubkey.c,v 1.119 2023/07/27 22:25:17 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. - * Copyright (c) 2010 Damien Miller. All rights reserved. + * Copyright (c) 2003-2022 Roumen Petrov. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -52,7 +52,8 @@ #include "misc.h" #include "servconf.h" #include "compat.h" -#include "sshkey.h" +#include "sshxkey.h" +#include "ssh-x509.h" #include "hostfile.h" #include "auth.h" #include "pathnames.h" @@ -65,14 +66,35 @@ #include "monitor_wrap.h" #include "authfile.h" #include "match.h" -#include "ssherr.h" #include "channels.h" /* XXX for session.h */ #include "session.h" /* XXX for child_set_env(); refactor? */ -#include "sk-api.h" /* import */ extern ServerOptions options; +/* return 1 if given publickey algorithm is allowed */ +static int +pubkey_algorithm_allowed(const char* pkalg) +{ + if ( + (options.pubkey_algorithms != NULL) && + (match_pattern_list(pkalg, options.pubkey_algorithms, 0) != 1) + ) { + debug("disallowed publickey algorithm: %s", pkalg); + return 0; + } + + if ( + (options.accepted_algorithms != NULL) && + (match_pattern_list(pkalg, options.accepted_algorithms, 0) != 1) + ) { + debug("non-accepted publickey algorithm: %s", pkalg); + return 0; + } + + return 1; +} + static char * format_key(const struct sshkey *key) { @@ -85,62 +107,32 @@ } static int -userauth_pubkey(struct ssh *ssh, const char *method) +userauth_pubkey(struct ssh *ssh) { Authctxt *authctxt = ssh->authctxt; struct passwd *pw = authctxt->pw; struct sshbuf *b = NULL; - struct sshkey *key = NULL, *hostkey = NULL; + struct sshkey *key = NULL; char *pkalg = NULL, *userstyle = NULL, *key_s = NULL, *ca_s = NULL; u_char *pkblob = NULL, *sig = NULL, have_sig; size_t blen, slen; - int hostbound, r, pktype; - int req_presence = 0, req_verify = 0, authenticated = 0; + int r, pktype; + int authenticated = 0; struct sshauthopt *authopts = NULL; - struct sshkey_sig_details *sig_details = NULL; - - hostbound = strcmp(method, "publickey-hostbound-v00@openssh.com") == 0; if ((r = sshpkt_get_u8(ssh, &have_sig)) != 0 || (r = sshpkt_get_cstring(ssh, &pkalg, NULL)) != 0 || (r = sshpkt_get_string(ssh, &pkblob, &blen)) != 0) - fatal_fr(r, "parse %s packet", method); - - /* hostbound auth includes the hostkey offered at initial KEX */ - if (hostbound) { - if ((r = sshpkt_getb_froms(ssh, &b)) != 0 || - (r = sshkey_fromb(b, &hostkey)) != 0) - fatal_fr(r, "parse %s hostkey", method); - if (ssh->kex->initial_hostkey == NULL) - fatal_f("internal error: initial hostkey not recorded"); - if (!sshkey_equal(hostkey, ssh->kex->initial_hostkey)) - fatal_f("%s packet contained wrong host key", method); - sshbuf_free(b); - b = NULL; - } - - if (log_level_get() >= SYSLOG_LEVEL_DEBUG2) { - char *keystring; - struct sshbuf *pkbuf; - - if ((pkbuf = sshbuf_from(pkblob, blen)) == NULL) - fatal_f("sshbuf_from failed"); - if ((keystring = sshbuf_dtob64_string(pkbuf, 0)) == NULL) - fatal_f("sshbuf_dtob64 failed"); - debug2_f("%s user %s %s public key %s %s", - authctxt->valid ? "valid" : "invalid", authctxt->user, - have_sig ? "attempting" : "querying", pkalg, keystring); - sshbuf_free(pkbuf); - free(keystring); - } - + fatal_fr(r, "parse packet"); pktype = sshkey_type_from_name(pkalg); if (pktype == KEY_UNSPEC) { /* this is perfectly legal */ - verbose_f("unsupported public key algorithm: %s", pkalg); + verbose("Unsupported public key algorithm: %s", pkalg); goto done; } - if ((r = sshkey_from_blob(pkblob, blen, &key)) != 0) { + if (!pubkey_algorithm_allowed(pkalg)) goto done; + + if ((r = Xkey_from_blob(pkalg, pkblob, blen, &key)) != 0) { error_fr(r, "parse key"); goto done; } @@ -157,37 +149,36 @@ logit("refusing previously-used %s key", sshkey_type(key)); goto done; } - if (match_pattern_list(pkalg, options.pubkey_accepted_algos, 0) != 1) { - logit_f("signature algorithm %s not in " - "PubkeyAcceptedAlgorithms", pkalg); - goto done; - } if ((r = sshkey_check_cert_sigtype(key, options.ca_sign_algorithms)) != 0) { - logit_fr(r, "certificate signature algorithm %s", + error_r(r, "Certificate signature algorithm %s", (key->cert == NULL || key->cert->signature_type == NULL) ? "(null)" : key->cert->signature_type); goto done; } - if ((r = sshkey_check_rsa_length(key, - options.required_rsa_size)) != 0) { - logit_r(r, "refusing %s key", sshkey_type(key)); +#if 0 + /* NOTE: key size is validated on read, sign and verify */ + if ((r = sshkey_check_length(key)) != 0) { + error_r(r, "refusing %s key", sshkey_type(key)); goto done; } +#endif + +{ ssh_verify_ctx ctx = { pkalg, key, &ssh->compat }; + key_s = format_key(key); if (sshkey_is_cert(key)) ca_s = format_key(key->cert->signature_key); if (have_sig) { - debug3_f("%s have %s signature for %s%s%s", - method, pkalg, key_s, + debug3_f("have signature for %s %s%s%s", pkalg, key_s, ca_s == NULL ? "" : " CA ", ca_s == NULL ? "" : ca_s); if ((r = sshpkt_get_string(ssh, &sig, &slen)) != 0 || (r = sshpkt_get_end(ssh)) != 0) fatal_fr(r, "parse signature packet"); if ((b = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); - if (ssh->compat & SSH_OLD_SESSIONID) { + if (ssh_compat_fellows(ssh, SSH_OLD_SESSIONID)) { if ((r = sshbuf_putb(b, ssh->kex->session_id)) != 0) fatal_fr(r, "put old session id"); } else { @@ -206,64 +197,24 @@ if ((r = sshbuf_put_u8(b, SSH2_MSG_USERAUTH_REQUEST)) != 0 || (r = sshbuf_put_cstring(b, userstyle)) != 0 || (r = sshbuf_put_cstring(b, authctxt->service)) != 0 || - (r = sshbuf_put_cstring(b, method)) != 0 || + (r = sshbuf_put_cstring(b, "publickey")) != 0 || (r = sshbuf_put_u8(b, have_sig)) != 0 || (r = sshbuf_put_cstring(b, pkalg)) != 0 || (r = sshbuf_put_string(b, pkblob, blen)) != 0) - fatal_fr(r, "reconstruct %s packet", method); - if (hostbound && - (r = sshkey_puts(ssh->kex->initial_hostkey, b)) != 0) - fatal_fr(r, "reconstruct %s packet", method); + fatal_fr(r, "reconstruct packet"); #ifdef DEBUG_PK sshbuf_dump(b, stderr); #endif /* test for correct signature */ authenticated = 0; - if (PRIVSEP(user_key_allowed(ssh, pw, key, 1, &authopts)) && - PRIVSEP(sshkey_verify(key, sig, slen, - sshbuf_ptr(b), sshbuf_len(b), - (ssh->compat & SSH_BUG_SIGTYPE) == 0 ? pkalg : NULL, - ssh->compat, &sig_details)) == 0) { + if (PRIVSEP(user_xkey_allowed(ssh, pw, &ctx, 1, &authopts)) && + PRIVSEP(Xkey_verify(&ctx, sig, slen, + sshbuf_ptr(b), sshbuf_len(b))) == 0) { authenticated = 1; } - if (authenticated == 1 && sig_details != NULL) { - auth2_record_info(authctxt, "signature count = %u", - sig_details->sk_counter); - debug_f("sk_counter = %u, sk_flags = 0x%02x", - sig_details->sk_counter, sig_details->sk_flags); - req_presence = (options.pubkey_auth_options & - PUBKEYAUTH_TOUCH_REQUIRED) || - !authopts->no_require_user_presence; - if (req_presence && (sig_details->sk_flags & - SSH_SK_USER_PRESENCE_REQD) == 0) { - error("public key %s signature for %s%s from " - "%.128s port %d rejected: user presence " - "(authenticator touch) requirement " - "not met ", key_s, - authctxt->valid ? "" : "invalid user ", - authctxt->user, ssh_remote_ipaddr(ssh), - ssh_remote_port(ssh)); - authenticated = 0; - goto done; - } - req_verify = (options.pubkey_auth_options & - PUBKEYAUTH_VERIFY_REQUIRED) || - authopts->require_verify; - if (req_verify && (sig_details->sk_flags & - SSH_SK_USER_VERIFICATION_REQD) == 0) { - error("public key %s signature for %s%s from " - "%.128s port %d rejected: user " - "verification requirement not met ", key_s, - authctxt->valid ? "" : "invalid user ", - authctxt->user, ssh_remote_ipaddr(ssh), - ssh_remote_port(ssh)); - authenticated = 0; - goto done; - } - } auth2_record_key(authctxt, authenticated, key); } else { - debug_f("%s test pkalg %s pkblob %s%s%s", method, pkalg, key_s, + debug_f("test pkalg %s pkblob %s%s%s", pkalg, key_s, ca_s == NULL ? "" : " CA ", ca_s == NULL ? "" : ca_s); if ((r = sshpkt_get_end(ssh)) != 0) @@ -281,7 +232,7 @@ * if a user is not allowed to login. is this an * issue? -markus */ - if (PRIVSEP(user_key_allowed(ssh, pw, key, 0, NULL))) { + if (PRIVSEP(user_xkey_allowed(ssh, pw, &ctx, 0, NULL))) { if ((r = sshpkt_start(ssh, SSH2_MSG_USERAUTH_PK_OK)) != 0 || (r = sshpkt_put_cstring(ssh, pkalg)) != 0 || @@ -292,6 +243,7 @@ authctxt->postponed = 1; } } +} done: if (authenticated == 1 && auth_activate_options(ssh, authopts) != 0) { debug_f("key options inconsistent with existing"); @@ -299,17 +251,15 @@ } debug2_f("authenticated %d pkalg %s", authenticated, pkalg); - sshbuf_free(b); sshauthopt_free(authopts); sshkey_free(key); - sshkey_free(hostkey); + sshbuf_free(b); free(userstyle); free(pkalg); free(pkblob); free(key_s); free(ca_s); free(sig); - sshkey_sig_details_free(sig_details); return authenticated; } @@ -461,9 +411,7 @@ if (f != NULL) fclose(f); ssh_signal(SIGCHLD, osigchld); - for (i = 0; i < ac; i++) - free(av[i]); - free(av); + argv_free(av, ac); if (uid_swapped) restore_uid(); free(command); @@ -499,7 +447,7 @@ if ((r = sshkey_in_file(key->cert->signature_key, options.trusted_user_ca_keys, 1, 0)) != 0) { - debug2_fr(r, "CA %s %s is not listed in %s", + debug2_r(r, "CA %s %s is not listed in %s", sshkey_type(key->cert->signature_key), ca_fp, options.trusted_user_ca_keys); goto out; @@ -597,7 +545,7 @@ /* Temporarily use the user's uid. */ temporarily_use_uid(pw); - debug("trying public key file %s", file); + debug("trying authorized keys file %s", file); if ((f = auth_openkeyfile(file, pw, options.strict_modes)) != NULL) { found_key = auth_check_authkeys_file(pw, f, file, key, remote_ip, remote_host, authoptsp); @@ -733,9 +681,7 @@ if (f != NULL) fclose(f); ssh_signal(SIGCHLD, osigchld); - for (i = 0; i < ac; i++) - free(av[i]); - free(av); + argv_free(av, ac); if (uid_swapped) restore_uid(); free(command); @@ -749,32 +695,38 @@ * Check whether key authenticates and authorises the user. */ int -user_key_allowed(struct ssh *ssh, struct passwd *pw, struct sshkey *key, +user_xkey_allowed(struct ssh *ssh, struct passwd *pw, ssh_verify_ctx *ctx, int auth_attempt, struct sshauthopt **authoptsp) { - u_int success = 0, i; - char *file, *conn_id; + struct sshkey *key = ctx->key; + u_int success, i; + char *file, *conn_id = NULL; struct sshauthopt *opts = NULL; const char *rdomain, *remote_ip, *remote_host; + UNUSED(auth_attempt); if (authoptsp != NULL) *authoptsp = NULL; + if (options.x509flags.validate_first && + sshkey_is_x509(key) && + (xkey_validate_cert(key) < 0)) + return 0; if (auth_key_is_revoked(key)) return 0; if (sshkey_is_cert(key) && auth_key_is_revoked(key->cert->signature_key)) return 0; - if ((rdomain = ssh_packet_rdomain_in(ssh)) == NULL) - rdomain = ""; + rdomain = ssh_packet_rdomain_in(ssh); + if (rdomain == NULL) rdomain = ""; remote_ip = ssh_remote_ipaddr(ssh); remote_host = auth_get_canonical_hostname(ssh, options.use_dns); xasprintf(&conn_id, "%s %d %s %d", ssh_local_ipaddr(ssh), ssh_local_port(ssh), remote_ip, ssh_remote_port(ssh)); - for (i = 0; !success && i < options.num_authkeys_files; i++) { + for (i = 0; i < options.num_authkeys_files; i++) { if (strcasecmp(options.authorized_keys_files[i], "none") == 0) continue; file = expand_authorized_keys( @@ -782,28 +734,26 @@ success = user_key_allowed2(pw, key, file, remote_ip, remote_host, &opts); free(file); - if (!success) { - sshauthopt_free(opts); - opts = NULL; - } + if (success) goto out; + sshauthopt_free(opts); + opts = NULL; } - if (success) - goto out; - if ((success = user_cert_trusted_ca(pw, key, remote_ip, remote_host, - conn_id, rdomain, &opts)) != 0) - goto out; + success = user_cert_trusted_ca(pw, key, remote_ip, remote_host, conn_id, rdomain, &opts); + if (success) goto out; sshauthopt_free(opts); opts = NULL; - if ((success = user_key_command_allowed2(pw, key, remote_ip, - remote_host, conn_id, rdomain, &opts)) != 0) - goto out; - sshauthopt_free(opts); - opts = NULL; + success = user_key_command_allowed2(pw, key, remote_ip, remote_host, conn_id, rdomain, &opts); out: free(conn_id); + if (success && + !options.x509flags.validate_first && + sshkey_is_x509(key) + ) + success = (xkey_validate_cert(key) == 0); + if (success && authoptsp != NULL) { *authoptsp = opts; opts = NULL; @@ -814,7 +764,6 @@ Authmethod method_pubkey = { "publickey", - "publickey-hostbound-v00@openssh.com", userauth_pubkey, &options.pubkey_authentication }; diff -ruN openssh-9.4p1/auth2-pubkeyfile.c openssh-9.4p1+x509-14.2.1/auth2-pubkeyfile.c --- openssh-9.4p1/auth2-pubkeyfile.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/auth2-pubkeyfile.c 2023-08-20 10:07:01.000000000 +0300 @@ -1,7 +1,8 @@ -/* $OpenBSD: auth2-pubkeyfile.c,v 1.4 2023/03/05 05:34:09 dtucker Exp $ */ +/* $OpenBSD: auth2-pubkeyfile.c,v 1.3 2022/07/01 03:52:57 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * Copyright (c) 2010 Damien Miller. All rights reserved. + * Copyright (c) 2003-2022 Roumen Petrov. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -39,17 +40,19 @@ #include #include -#include "ssh.h" #include "log.h" #include "misc.h" -#include "sshkey.h" -#include "digest.h" +#include "ssh-x509.h" +#include "x509store.h" #include "hostfile.h" #include "auth.h" #include "auth-options.h" #include "authfile.h" +#include "servconf.h" #include "match.h" -#include "ssherr.h" + +/* import */ +extern ServerOptions options; int auth_authorise_keyopts(struct passwd *pw, struct sshauthopt *opts, @@ -168,7 +171,7 @@ * authoptsp is principal is authorised, -1 otherwise. "loc" is used as a * log preamble for file/line information. */ -int +static int auth_check_principals_line(char *cp, const struct sshkey_cert *cert, const char *loc, struct sshauthopt **authoptsp) { @@ -255,17 +258,59 @@ return found_principal; } +static int +key_match(const struct sshkey *key, const struct sshkey *found) { + /* key without X.509 identity - see check_authkey_line */ + if (sshkey_is_x509(found)) return 0; + + return sshkey_equal(key, found); +} + +static int +x509_match(const struct sshkey *key, const struct sshkey *found) { + /* key always is a X.509 identity - see check_authkey_line */ + if (found == NULL) + return 0; + + if (sshkey_is_x509(found)) { + if (!sshkey_equal_public(key, found)) + return 0; + + debug3_f("found matching certificate"); + /* If self-issued is not enabled only verification + process can allow received certificate. */ + if (!ssh_x509flags.key_allow_selfissued) return 1; + + { /* The public key or X.509 certificate found in + authorized keys file can allow self-issued. */ + X509 *x = SSH_X509_get_cert(key->x509_data); + if (!ssh_X509_is_selfissued(x)) return 1; + } + + /* If self-issued can be authorized (and allowed) + by public key-material */ + } + + /* Note a X.509 certificate can be allowed by public key. + * Also manage case for self-issued. + * Code is same as sshkey_equal_public but without + * compare by distinguished name. + */ + return sshkey_equal_public_pkey(key, found); +} + /* * Check a single line of an authorized_keys-format file. Returns 0 if key * matches, -1 otherwise. Will return key/cert options via *authoptsp * on success. "loc" is used as file/line location in log messages. */ -int +static int auth_check_authkey_line(struct passwd *pw, struct sshkey *key, char *cp, const char *remote_ip, const char *remote_host, const char *loc, struct sshauthopt **authoptsp) { - int want_keytype = sshkey_is_cert(key) ? KEY_UNSPEC : key->type; + int want_keytype = sshkey_is_cert(key) || sshkey_is_x509(key) + ? KEY_UNSPEC : key->type; struct sshkey *found = NULL; struct sshauthopt *keyopts = NULL, *certopts = NULL, *finalopts = NULL; char *key_options = NULL, *fp = NULL; @@ -309,16 +354,31 @@ if (!sshkey_equal(found, key->cert->signature_key) || !keyopts->cert_authority) goto out; + } else if (sshkey_is_x509(key)) { + /* Variable key always contain public key or + * certificate. In case of X.509 certificate + * x509 attribute of Key structure "found" + * may contain only "Distinguished Name" ! + */ + if (!x509_match(key, found)) + goto out; } else { /* Plain key: check it against key found in file */ - if (!sshkey_equal(found, key) || keyopts->cert_authority) + if (!key_match(key, found) || keyopts->cert_authority) goto out; } /* We have a candidate key, perform authorisation checks */ - if ((fp = sshkey_fingerprint(found, - SSH_FP_HASH_DEFAULT, SSH_FP_DEFAULT)) == NULL) - fatal_f("fingerprint failed"); + fp = sshkey_is_x509(found) + ? x509key_subject(found) + : sshkey_fingerprint(found, options.fingerprint_hash, SSH_FP_DEFAULT); + if (fp == NULL) { + if (sshkey_is_x509(found)) + error_f("extract of X.509 distinguished name failed"); + else + error_f("fingerprint failed"); + goto out; + } debug("%s: matching %s found: %s %s", loc, sshkey_is_cert(key) ? "CA" : "key", sshkey_type(found), fp); @@ -328,6 +388,14 @@ reason = "Refused by key options"; goto fail_reason; } + + if (sshkey_is_x509(key)) { + verbose("Authorized by %s : %s", sshkey_type(found), fp); + finalopts = keyopts; + keyopts = NULL; + goto success; + } + /* That's all we need for plain keys. */ if (!sshkey_is_cert(key)) { verbose("Accepted key %s %s found at %s", @@ -484,7 +552,6 @@ return f; } - FILE * auth_openkeyfile(const char *file, struct passwd *pw, int strict_modes) { @@ -497,4 +564,3 @@ return auth_openfile(file, pw, strict_modes, 0, "authorized principals"); } - diff -ruN openssh-9.4p1/auth-bsdauth.c openssh-9.4p1+x509-14.2.1/auth-bsdauth.c --- openssh-9.4p1/auth-bsdauth.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/auth-bsdauth.c 2023-08-20 10:07:01.000000000 +0300 @@ -31,8 +31,6 @@ #ifdef BSD_AUTH #include "xmalloc.h" -#include "sshkey.h" -#include "sshbuf.h" #include "hostfile.h" #include "auth.h" #include "log.h" @@ -60,7 +58,7 @@ *echo_on = NULL; if (authctxt->as != NULL) { - debug2("bsdauth_query: try reuse session"); + debug2_f("try reuse session"); challenge = auth_getitem(authctxt->as, AUTHV_CHALLENGE); if (challenge == NULL) { auth_close(authctxt->as); @@ -69,14 +67,14 @@ } if (challenge == NULL) { - debug2("bsdauth_query: new bsd auth session"); - debug3("bsdauth_query: style %s", + debug2_f("new bsd auth session"); + debug3_f("style %s", authctxt->style ? authctxt->style : ""); authctxt->as = auth_userchallenge(authctxt->user, authctxt->style, "auth-ssh", &challenge); if (authctxt->as == NULL) challenge = NULL; - debug2("bsdauth_query: <%s>", challenge ? challenge : "empty"); + debug2_f("<%s>", challenge ? challenge : "empty"); } if (challenge == NULL) @@ -102,14 +100,14 @@ return -1; if (authctxt->as == NULL) - error("bsdauth_respond: no bsd auth session"); + error_f("no bsd auth session"); if (numresponses != 1) return -1; authok = auth_userresponse(authctxt->as, responses[0], 0); authctxt->as = NULL; - debug3("bsdauth_respond: <%s> = <%d>", responses[0], authok); + debug3_f("<%s> = <%d>", responses[0], authok); return (authok == 0) ? -1 : 0; } diff -ruN openssh-9.4p1/auth.c openssh-9.4p1+x509-14.2.1/auth.c --- openssh-9.4p1/auth.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/auth.c 2023-08-20 10:07:01.000000000 +0300 @@ -1,6 +1,7 @@ /* $OpenBSD: auth.c,v 1.160 2023/03/05 05:34:09 dtucker Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. + * Copyright (c) 2016-2021 Roumen Petrov. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -76,6 +77,24 @@ #include "ssherr.h" #include "channels.h" +#ifdef HAVE_LOGIN_CAP +/* compatibility */ + +/* FreeBSD has login_getpwclass() that does some special magic for UID=0 */ +#ifndef HAVE_LOGIN_GETPWCLASS +static inline login_cap_t* +login_getpwclass(const struct passwd *pwd) { +#ifdef HAVE_STRUCT_PASSWD_PW_CLASS + return login_getclass(pwd != NULL ? pwd->pw_class : NULL); +#else + UNUSED(pwd); + return NULL; +#endif +} +#endif /*ndef HAVE_LOGIN_GETPWCLASS**/ + +#endif /*def HAVE_LOGIN_CAP*/ + /* import */ extern ServerOptions options; extern struct include_list includes; @@ -105,7 +124,7 @@ int r; /* Shouldn't be called if pw is NULL, but better safe than sorry... */ - if (!pw || !pw->pw_name) + if (pw == NULL || pw->pw_name == NULL) return 0; if (!options.use_pam && platform_locked_account(pw)) { @@ -241,7 +260,7 @@ options.fingerprint_hash, SSH_FP_DEFAULT); cafp = sshkey_fingerprint(key->cert->signature_key, options.fingerprint_hash, SSH_FP_DEFAULT); - xasprintf(&ret, "%s %s ID %s (serial %llu) CA %s %s%s%s", + xasprintf(&ret, "%s %s ID \"%s\" (serial %llu) CA %s %s%s%s", sshkey_type(key), fp == NULL ? "(null)" : fp, key->cert->key_id, (unsigned long long)key->cert->serial, @@ -312,8 +331,7 @@ /* Log failed login attempt */ # ifdef CUSTOM_FAILED_LOGIN if (strcmp(method, "password") == 0 || - strncmp(method, "keyboard-interactive", 20) == 0 || - strcmp(method, "challenge-response") == 0) + strncmp(method, "keyboard-interactive", 20) == 0) record_failed_login(ssh, authctxt->user, auth_get_canonical_hostname(ssh, options.use_dns), "ssh"); # endif @@ -400,7 +418,7 @@ i = snprintf(ret, sizeof(ret), "%s/%s", pw->pw_dir, file); if (i < 0 || (size_t)i >= sizeof(ret)) - fatal("expand_authorized_keys: path too long"); + fatal_f("path too long"); free(file); return (xstrdup(ret)); } @@ -429,7 +447,7 @@ if (userfile != NULL) { user_hostfile = tilde_expand_filename(userfile, pw->pw_uid); if (options.strict_modes && - (stat(user_hostfile, &st) == 0) && + (stat(user_hostfile, &st) != -1) && ((st.st_uid != 0 && st.st_uid != pw->pw_uid) || (st.st_mode & 022) != 0)) { logit("Authentication refused for %.100s: " @@ -470,15 +488,12 @@ #endif struct passwd *pw; struct connection_info *ci; - u_int i; ci = get_connection_info(ssh, 1, options.use_dns); ci->user = user; parse_server_match_config(&options, &includes, ci); log_change_level(options.log_level); - log_verbose_reset(); - for (i = 0; i < options.num_log_verbose; i++) - log_verbose_add(options.log_verbose[i]); + log_verbose_init(options.log_verbose, options.num_log_verbose); process_permitopen(ssh, &options); #if defined(_AIX) && defined(HAVE_SETAUTHDB) @@ -570,13 +585,14 @@ va_list args; int r; + if (auth_debug == NULL) + return; + va_start(args, fmt); vsnprintf(buf, sizeof(buf), fmt, args); va_end(args); - debug3("%s", buf); - if (auth_debug != NULL) - if ((r = sshbuf_put_cstring(auth_debug, buf)) != 0) - fatal_fr(r, "sshbuf_put_cstring"); + if ((r = sshbuf_put_cstring(auth_debug, buf)) != 0) + fatal_fr(r, "sshbuf_put_cstring"); } void @@ -765,18 +781,16 @@ snprintf(buf, sizeof(buf), "%d", opts->force_tun_device); /* Try to keep this alphabetically sorted */ - snprintf(msg, sizeof(msg), "key options:%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", + snprintf(msg, sizeof(msg), "key options:%s%s%s%s%s%s%s%s%s%s%s%s%s", opts->permit_agent_forwarding_flag ? " agent-forwarding" : "", opts->force_command == NULL ? "" : " command", do_env ? " environment" : "", opts->valid_before == 0 ? "" : "expires", - opts->no_require_user_presence ? " no-touch-required" : "", do_permitopen ? " permitopen" : "", do_permitlisten ? " permitlisten" : "", opts->permit_port_forwarding_flag ? " port-forwarding" : "", opts->cert_principals == NULL ? "" : " principals", opts->permit_pty_flag ? " pty" : "", - opts->require_verify ? " uv" : "", opts->force_tun_device == -1 ? "" : " tun=", opts->force_tun_device == -1 ? "" : buf, opts->permit_user_rc ? " user-rc" : "", @@ -828,6 +842,7 @@ struct sshauthopt *old = auth_opts; const char *emsg = NULL; + UNUSED(ssh); debug_f("setting new authentication options"); if ((auth_opts = sshauthopt_merge(old, opts, &emsg)) == NULL) { error("Inconsistent authentication options: %s", emsg); diff -ruN openssh-9.4p1/authfd.c openssh-9.4p1+x509-14.2.1/authfd.c --- openssh-9.4p1/authfd.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/authfd.c 2023-08-20 10:07:01.000000000 +0300 @@ -1,4 +1,4 @@ -/* $OpenBSD: authfd.c,v 1.133 2023/03/09 21:06:24 jcs Exp $ */ +/* $OpenBSD: authfd.c,v 1.130 2022/04/27 11:08:55 dtucker Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -13,6 +13,7 @@ * * SSH2 implementation, * Copyright (c) 2000 Markus Friedl. All rights reserved. + * Copyright (c) 2002-2019 Roumen Petrov. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -51,10 +52,10 @@ #include "xmalloc.h" #include "ssh.h" -#include "sshbuf.h" -#include "sshkey.h" +#include "sshxkey.h" #include "authfd.h" #include "cipher.h" +#include "compat.h" #include "log.h" #include "atomicio.h" #include "misc.h" @@ -70,7 +71,7 @@ (x == SSH2_AGENT_FAILURE)) /* Convert success/failure response from agent to a err.h status */ -static int +static inline int decode_reply(u_char type) { if (agent_failed(type)) @@ -188,11 +189,9 @@ if ((reply = sshbuf_new()) == NULL) return SSH_ERR_ALLOC_FAIL; if ((r = ssh_request_reply(sock, request, reply)) != 0 || - (r = sshbuf_get_u8(reply, &type)) != 0 || - (r = decode_reply(type)) != 0) + (r = sshbuf_get_u8(reply, &type)) != 0) goto out; - /* success */ - r = 0; + r = decode_reply(type); out: sshbuf_free(reply); return r; @@ -221,11 +220,9 @@ if ((msg = sshbuf_new()) == NULL) return SSH_ERR_ALLOC_FAIL; if ((r = sshbuf_put_u8(msg, type)) != 0 || - (r = sshbuf_put_cstring(msg, password)) != 0 || - (r = ssh_request_reply_decode(sock, msg)) != 0) + (r = sshbuf_put_cstring(msg, password)) != 0) goto out; - /* success */ - r = 0; + r = ssh_request_reply_decode(sock, msg); out: sshbuf_free(msg); return r; @@ -243,7 +240,7 @@ if ((r = sshbuf_get_string_direct(ids, &blob, &blen)) != 0 || (r = sshbuf_get_cstring(ids, &comment, NULL)) != 0) goto out; - if ((r = sshkey_from_blob(blob, blen, keyp)) != 0) + if ((r = Akey_from_blob(blob, blen, keyp)) != 0) goto out; if (commentp != NULL) { *commentp = comment; @@ -319,6 +316,7 @@ } else goto out; } + debug3_f("comment[%d]: '%s'", i, idl->comments[i]); i++; } idl->nkeys = num; @@ -351,32 +349,6 @@ } /* - * Check if the ssh agent has a given key. - * Returns 0 if found, or a negative SSH_ERR_* error code on failure. - */ -int -ssh_agent_has_key(int sock, const struct sshkey *key) -{ - int r, ret = SSH_ERR_KEY_NOT_FOUND; - size_t i; - struct ssh_identitylist *idlist = NULL; - - if ((r = ssh_fetch_identitylist(sock, &idlist)) != 0) { - return r; - } - - for (i = 0; i < idlist->nkeys; i++) { - if (sshkey_equal_public(idlist->keys[i], key)) { - ret = 0; - break; - } - } - - ssh_free_identitylist(idlist); - return ret; -} - -/* * Sends a challenge (typically from a server via ssh(1)) to the agent, * and waits for a response from the agent. * Returns true (non-zero) if the agent gave the correct answer, zero @@ -388,22 +360,26 @@ static u_int agent_encode_alg(const struct sshkey *key, const char *alg) { - if (alg != NULL && sshkey_type_plain(key->type) == KEY_RSA) { - if (strcmp(alg, "rsa-sha2-256") == 0 || - strcmp(alg, "rsa-sha2-256-cert-v01@openssh.com") == 0) - return SSH_AGENT_RSA_SHA2_256; - if (strcmp(alg, "rsa-sha2-512") == 0 || - strcmp(alg, "rsa-sha2-512-cert-v01@openssh.com") == 0) - return SSH_AGENT_RSA_SHA2_512; - } + if (alg == NULL) return 0; + if (key->type != KEY_RSA) return 0; +#ifdef HAVE_EVP_SHA256 + if (strcmp(alg, "rsa-sha2-256") == 0) + return SSH_AGENT_RSA_SHA2_256; + if (strcmp(alg, "rsa-sha2-512") == 0) + return SSH_AGENT_RSA_SHA2_512; + if (strcmp(alg, "rsa-sha2-256-cert-v01@openssh.com") == 0) + return SSH_AGENT_RSA_SHA2_256; + if (strcmp(alg, "rsa-sha2-512-cert-v01@openssh.com") == 0) + return SSH_AGENT_RSA_SHA2_512; +#endif /*def HAVE_EVP_SHA256*/ return 0; } /* ask agent to sign data, returns err.h code on error, 0 on success */ int -ssh_agent_sign(int sock, const struct sshkey *key, +Xssh_agent_sign(int sock, ssh_sign_ctx *ctx, u_char **sigp, size_t *lenp, - const u_char *data, size_t datalen, const char *alg, u_int compat) + const u_char *data, size_t datalen) { struct sshbuf *msg; u_char *sig = NULL, type = 0; @@ -416,11 +392,13 @@ if (datalen > SSH_KEY_MAX_SIGN_DATA_SIZE) return SSH_ERR_INVALID_ARGUMENT; + if (check_compat_extra(ctx->compat, SSHX_RFC6187_ASN1_OPAQUE_ECDSA_SIGNATURE)) + flags |= SSH_AGENT_RFC6187_OPAQUE_ECDSA_SIGNATURE; if ((msg = sshbuf_new()) == NULL) return SSH_ERR_ALLOC_FAIL; - flags |= agent_encode_alg(key, alg); + flags |= agent_encode_alg(ctx->key, ctx->alg); if ((r = sshbuf_put_u8(msg, SSH2_AGENTC_SIGN_REQUEST)) != 0 || - (r = sshkey_puts(key, msg)) != 0 || + (r = Xkey_puts(ctx->alg, ctx->key, msg)) != 0 || (r = sshbuf_put_string(msg, data, datalen)) != 0 || (r = sshbuf_put_u32(msg, flags)) != 0) goto out; @@ -438,7 +416,7 @@ if ((r = sshbuf_get_string(msg, &sig, &len)) != 0) goto out; /* Check what we actually got back from the agent. */ - if ((r = sshkey_check_sigtype(sig, len, alg)) != 0) + if ((r = Xkey_check_sigalg(ctx, sig, len)) != 0) goto out; /* success */ *sigp = sig; @@ -454,63 +432,12 @@ /* Encode key for a message to the agent. */ -static int -encode_dest_constraint_hop(struct sshbuf *m, - const struct dest_constraint_hop *dch) -{ - struct sshbuf *b; - u_int i; - int r; - - if ((b = sshbuf_new()) == NULL) - return SSH_ERR_ALLOC_FAIL; - if ((r = sshbuf_put_cstring(b, dch->user)) != 0 || - (r = sshbuf_put_cstring(b, dch->hostname)) != 0 || - (r = sshbuf_put_string(b, NULL, 0)) != 0) /* reserved */ - goto out; - for (i = 0; i < dch->nkeys; i++) { - if ((r = sshkey_puts(dch->keys[i], b)) != 0 || - (r = sshbuf_put_u8(b, dch->key_is_ca[i] != 0)) != 0) - goto out; - } - if ((r = sshbuf_put_stringb(m, b)) != 0) - goto out; - /* success */ - r = 0; - out: - sshbuf_free(b); - return r; -} - -static int -encode_dest_constraint(struct sshbuf *m, const struct dest_constraint *dc) -{ - struct sshbuf *b; - int r; - - if ((b = sshbuf_new()) == NULL) - return SSH_ERR_ALLOC_FAIL; - if ((r = encode_dest_constraint_hop(b, &dc->from)) != 0 || - (r = encode_dest_constraint_hop(b, &dc->to)) != 0 || - (r = sshbuf_put_string(b, NULL, 0)) != 0) /* reserved */ - goto out; - if ((r = sshbuf_put_stringb(m, b)) != 0) - goto out; - /* success */ - r = 0; - out: - sshbuf_free(b); - return r; -} static int encode_constraints(struct sshbuf *m, u_int life, u_int confirm, u_int maxsign, - const char *provider, struct dest_constraint **dest_constraints, - size_t ndest_constraints) + const char *provider) { int r; - struct sshbuf *b = NULL; - size_t i; if (life != 0) { if ((r = sshbuf_put_u8(m, SSH_AGENT_CONSTRAIN_LIFETIME)) != 0 || @@ -527,33 +454,13 @@ goto out; } if (provider != NULL) { - if ((r = sshbuf_put_u8(m, - SSH_AGENT_CONSTRAIN_EXTENSION)) != 0 || - (r = sshbuf_put_cstring(m, - "sk-provider@openssh.com")) != 0 || + if ((r = sshbuf_put_u8(m, SSH_AGENT_CONSTRAIN_EXTENSION)) != 0 || + (r = sshbuf_put_cstring(m, "sk-provider@openssh.com")) != 0 || (r = sshbuf_put_cstring(m, provider)) != 0) goto out; } - if (dest_constraints != NULL && ndest_constraints > 0) { - if ((b = sshbuf_new()) == NULL) { - r = SSH_ERR_ALLOC_FAIL; - goto out; - } - for (i = 0; i < ndest_constraints; i++) { - if ((r = encode_dest_constraint(b, - dest_constraints[i])) != 0) - goto out; - } - if ((r = sshbuf_put_u8(m, - SSH_AGENT_CONSTRAIN_EXTENSION)) != 0 || - (r = sshbuf_put_cstring(m, - "restrict-destination-v00@openssh.com")) != 0 || - (r = sshbuf_put_stringb(m, b)) != 0) - goto out; - } r = 0; out: - sshbuf_free(b); return r; } @@ -564,12 +471,10 @@ int ssh_add_identity_constrained(int sock, struct sshkey *key, const char *comment, u_int life, u_int confirm, u_int maxsign, - const char *provider, struct dest_constraint **dest_constraints, - size_t ndest_constraints) + const char *provider) { struct sshbuf *msg; - int r, constrained = (life || confirm || maxsign || - provider || dest_constraints); + int r, constrained = (life || confirm || maxsign || provider); u_char type; if ((msg = sshbuf_new()) == NULL) @@ -583,13 +488,9 @@ case KEY_DSA_CERT: case KEY_ECDSA: case KEY_ECDSA_CERT: - case KEY_ECDSA_SK: - case KEY_ECDSA_SK_CERT: #endif case KEY_ED25519: case KEY_ED25519_CERT: - case KEY_ED25519_SK: - case KEY_ED25519_SK_CERT: case KEY_XMSS: case KEY_XMSS_CERT: type = constrained ? @@ -607,12 +508,9 @@ } if (constrained && (r = encode_constraints(msg, life, confirm, maxsign, - provider, dest_constraints, ndest_constraints)) != 0) - goto out; - if ((r = ssh_request_reply_decode(sock, msg)) != 0) + provider)) != 0) goto out; - /* success */ - r = 0; + r = ssh_request_reply_decode(sock, msg); out: sshbuf_free(msg); return r; @@ -634,7 +532,7 @@ return SSH_ERR_ALLOC_FAIL; if (key->type != KEY_UNSPEC) { - if ((r = sshkey_to_blob(key, &blob, &blen)) != 0) + if ((r = Akey_to_blob(key, &blob, &blen)) != 0) goto out; if ((r = sshbuf_put_u8(msg, SSH2_AGENTC_REMOVE_IDENTITY)) != 0 || @@ -644,10 +542,7 @@ r = SSH_ERR_INVALID_ARGUMENT; goto out; } - if ((r = ssh_request_reply_decode(sock, msg)) != 0) - goto out; - /* success */ - r = 0; + r = ssh_request_reply_decode(sock, msg); out: if (blob != NULL) freezero(blob, blen); @@ -661,11 +556,10 @@ */ int ssh_update_card(int sock, int add, const char *reader_id, const char *pin, - u_int life, u_int confirm, - struct dest_constraint **dest_constraints, size_t ndest_constraints) + u_int life, u_int confirm) { struct sshbuf *msg; - int r, constrained = (life || confirm || dest_constraints); + int r, constrained = (life || confirm); u_char type; if (add) { @@ -682,13 +576,9 @@ (r = sshbuf_put_cstring(msg, pin)) != 0) goto out; if (constrained && - (r = encode_constraints(msg, life, confirm, 0, NULL, - dest_constraints, ndest_constraints)) != 0) - goto out; - if ((r = ssh_request_reply_decode(sock, msg)) != 0) + (r = encode_constraints(msg, life, confirm, 0, NULL)) != 0) goto out; - /* success */ - r = 0; + r = ssh_request_reply_decode(sock, msg); out: sshbuf_free(msg); return r; @@ -715,39 +605,7 @@ return SSH_ERR_ALLOC_FAIL; if ((r = sshbuf_put_u8(msg, type)) != 0) goto out; - if ((r = ssh_request_reply_decode(sock, msg)) != 0) - goto out; - /* success */ - r = 0; - out: - sshbuf_free(msg); - return r; -} - -/* Binds a session ID to a hostkey via the initial KEX signature. */ -int -ssh_agent_bind_hostkey(int sock, const struct sshkey *key, - const struct sshbuf *session_id, const struct sshbuf *signature, - int forwarding) -{ - struct sshbuf *msg; - int r; - - if (key == NULL || session_id == NULL || signature == NULL) - return SSH_ERR_INVALID_ARGUMENT; - if ((msg = sshbuf_new()) == NULL) - return SSH_ERR_ALLOC_FAIL; - if ((r = sshbuf_put_u8(msg, SSH_AGENTC_EXTENSION)) != 0 || - (r = sshbuf_put_cstring(msg, "session-bind@openssh.com")) != 0 || - (r = sshkey_puts(key, msg)) != 0 || - (r = sshbuf_put_stringb(msg, session_id)) != 0 || - (r = sshbuf_put_stringb(msg, signature)) != 0 || - (r = sshbuf_put_u8(msg, forwarding ? 1 : 0)) != 0) - goto out; - if ((r = ssh_request_reply_decode(sock, msg)) != 0) - goto out; - /* success */ - r = 0; + r = ssh_request_reply_decode(sock, msg); out: sshbuf_free(msg); return r; diff -ruN openssh-9.4p1/authfd.h openssh-9.4p1+x509-14.2.1/authfd.h --- openssh-9.4p1/authfd.h 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/authfd.h 2023-08-20 10:07:00.000000000 +0300 @@ -1,4 +1,4 @@ -/* $OpenBSD: authfd.h,v 1.51 2021/12/19 22:10:24 djm Exp $ */ +/* $OpenBSD: authfd.h,v 1.49 2020/06/26 05:03:36 djm Exp $ */ /* * Author: Tatu Ylonen @@ -11,14 +11,33 @@ * software must be clearly marked as such, and if the derived work is * incompatible with the protocol description in the RFC file, it must be * called by a name other than "ssh" or "Secure Shell". + * + * Copyright (c) 2002-2019 Roumen Petrov. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef AUTHFD_H #define AUTHFD_H -struct sshbuf; -struct sshkey; - /* List of identities returned by ssh_fetch_identitylist() */ struct ssh_identitylist { size_t nkeys; @@ -26,20 +45,6 @@ char **comments; }; -/* Key destination restrictions */ -struct dest_constraint_hop { - char *user; /* wildcards allowed */ - char *hostname; /* used to matching cert principals and for display */ - int is_ca; - u_int nkeys; /* number of entries in *both* 'keys' and 'key_is_ca' */ - struct sshkey **keys; - int *key_is_ca; -}; -struct dest_constraint { - struct dest_constraint_hop from; - struct dest_constraint_hop to; -}; - int ssh_get_authentication_socket(int *fdp); int ssh_get_authentication_socket_path(const char *authsocket, int *fdp); void ssh_close_authentication_socket(int sock); @@ -48,24 +53,15 @@ int ssh_fetch_identitylist(int sock, struct ssh_identitylist **idlp); void ssh_free_identitylist(struct ssh_identitylist *idl); int ssh_add_identity_constrained(int sock, struct sshkey *key, - const char *comment, u_int life, u_int confirm, u_int maxsign, - const char *provider, struct dest_constraint **dest_constraints, - size_t ndest_constraints); -int ssh_agent_has_key(int sock, const struct sshkey *key); + const char *comment, u_int life, u_int confirm, u_int maxsign, + const char *provider); int ssh_remove_identity(int sock, const struct sshkey *key); int ssh_update_card(int sock, int add, const char *reader_id, - const char *pin, u_int life, u_int confirm, - struct dest_constraint **dest_constraints, - size_t ndest_constraints); + const char *pin, u_int life, u_int confirm); int ssh_remove_all_identities(int sock, int version); -int ssh_agent_sign(int sock, const struct sshkey *key, - u_char **sigp, size_t *lenp, - const u_char *data, size_t datalen, const char *alg, u_int compat); - -int ssh_agent_bind_hostkey(int sock, const struct sshkey *key, - const struct sshbuf *session_id, const struct sshbuf *signature, - int forwarding); +int Xssh_agent_sign(int sock, ssh_sign_ctx *ctx, + u_char **sigp, size_t *lenp, const u_char *data, size_t datalen); /* Messages for the authentication agent connection. */ #define SSH_AGENTC_REQUEST_RSA_IDENTITIES 1 @@ -100,9 +96,6 @@ #define SSH2_AGENTC_ADD_ID_CONSTRAINED 25 #define SSH_AGENTC_ADD_SMARTCARD_KEY_CONSTRAINED 26 -/* generic extension mechanism */ -#define SSH_AGENTC_EXTENSION 27 - #define SSH_AGENT_CONSTRAIN_LIFETIME 1 #define SSH_AGENT_CONSTRAIN_CONFIRM 2 #define SSH_AGENT_CONSTRAIN_MAXSIGN 3 @@ -118,4 +111,6 @@ #define SSH_AGENT_RSA_SHA2_256 0x02 #define SSH_AGENT_RSA_SHA2_512 0x04 +#define SSH_AGENT_RFC6187_OPAQUE_ECDSA_SIGNATURE 0x00010000U + #endif /* AUTHFD_H */ diff -ruN openssh-9.4p1/authfile.c openssh-9.4p1+x509-14.2.1/authfile.c --- openssh-9.4p1/authfile.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/authfile.c 2023-08-20 10:07:01.000000000 +0300 @@ -1,6 +1,7 @@ -/* $OpenBSD: authfile.c,v 1.144 2023/03/14 07:26:25 dtucker Exp $ */ +/* $OpenBSD: authfile.c,v 1.143 2022/06/21 14:52:13 tobhe Exp $ */ /* * Copyright (c) 2000, 2013 Markus Friedl. All rights reserved. + * Copyright (c) 2002-2021 Roumen Petrov. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -44,8 +45,9 @@ #include "authfile.h" #include "misc.h" #include "atomicio.h" -#include "sshkey.h" -#include "sshbuf.h" +#include "sshxkey.h" +#include "ssh-x509.h" +#include "key-eng.h" #include "ssherr.h" #include "krl.h" @@ -114,42 +116,58 @@ return 0; } -int -sshkey_load_private_type(int type, const char *filename, const char *passphrase, - struct sshkey **keyp, char **commentp) + +static int +sshkey_load_private_file(const char *filename, + const char *passphrase, struct sshkey **keyp, char **commentp) { int fd, r; - if (keyp != NULL) - *keyp = NULL; - if (commentp != NULL) - *commentp = NULL; + if (keyp != NULL) *keyp = NULL; + if (commentp != NULL) *commentp = NULL; if ((fd = open(filename, O_RDONLY)) == -1) return SSH_ERR_SYSTEM_ERROR; r = sshkey_perm_ok(fd, filename); - if (r != 0) - goto out; + if (r != 0) goto out; + + r = sshkey_load_private_fd(fd, passphrase, keyp, commentp); + if (r != 0) goto out; - r = sshkey_load_private_type_fd(fd, type, passphrase, keyp, commentp); - if (r == 0 && keyp && *keyp) + if (keyp && *keyp) r = sshkey_set_filename(*keyp, filename); - out: + +out: close(fd); return r; } int -sshkey_load_private(const char *filename, const char *passphrase, +sshkey_load_private(const char *name, const char *passphrase, struct sshkey **keyp, char **commentp) { - return sshkey_load_private_type(KEY_UNSPEC, filename, passphrase, + if (name == NULL) + return SSH_ERR_INVALID_ARGUMENT; + debug3_f("name='%s'", name); + +#ifdef USE_OPENSSL_STORE2 + if (strncmp(name, "store:", 6) == 0) + return store_load_private(name + 6, + passphrase, keyp, commentp); +#endif +#ifdef USE_OPENSSL_ENGINE + if (strncmp(name, "engine:", 7) == 0) + return engine_load_private(name + 7, + passphrase, keyp, commentp); +#endif + + return sshkey_load_private_file(name, passphrase, keyp, commentp); } int -sshkey_load_private_type_fd(int fd, int type, const char *passphrase, +sshkey_load_private_fd(int fd, const char *passphrase, struct sshkey **keyp, char **commentp) { struct sshbuf *buffer = NULL; @@ -158,7 +176,7 @@ if (keyp != NULL) *keyp = NULL; if ((r = sshbuf_load_fd(fd, &buffer)) != 0 || - (r = sshkey_parse_private_fileblob_type(buffer, type, + (r = sshkey_parse_private_fileblob(buffer, passphrase, keyp, commentp)) != 0) goto out; @@ -169,7 +187,6 @@ return r; } -/* Load a pubkey from the unencrypted envelope of a new-format private key */ static int sshkey_load_pubkey_from_private(const char *filename, struct sshkey **pubkeyp) { @@ -182,18 +199,20 @@ if ((fd = open(filename, O_RDONLY)) == -1) return SSH_ERR_SYSTEM_ERROR; + if ((r = sshbuf_load_fd(fd, &buffer)) != 0 || - (r = sshkey_parse_pubkey_from_private_fileblob_type(buffer, - KEY_UNSPEC, &pubkey)) != 0) - goto out; - if ((r = sshkey_set_filename(pubkey, filename)) != 0) + (r = sshkey_parse_pubkey_from_private_fileblob(buffer, + &pubkey)) != 0 || + (r = sshkey_set_filename(pubkey, filename)) != 0) goto out; + /* success */ if (pubkeyp != NULL) { *pubkeyp = pubkey; pubkey = NULL; } r = 0; + out: close(fd); sshbuf_free(buffer); @@ -202,7 +221,7 @@ } static int -sshkey_try_load_public(struct sshkey **kp, const char *filename, +sshkey_try_load_public(const char *filename, struct sshkey **keyp, char **commentp) { FILE *f; @@ -211,11 +230,27 @@ int r; struct sshkey *k = NULL; - if (kp == NULL) - return SSH_ERR_INVALID_ARGUMENT; - *kp = NULL; + if (keyp != NULL) + *keyp = NULL; if (commentp != NULL) *commentp = NULL; + +/* NOTE: For external keys simulate "missing" file. + * This suppress extra messages due to faulty load control in ssh.c + */ +#ifdef USE_OPENSSL_STORE2 + if (strncmp(filename, "store:", 6) == 0) { + errno = ENOENT; + return SSH_ERR_SYSTEM_ERROR; + } +#endif +#ifdef USE_OPENSSL_ENGINE + if (strncmp(filename, "engine:", 7) == 0) { + errno = ENOENT; + return SSH_ERR_SYSTEM_ERROR; + } +#endif + if ((f = fopen(filename, "r")) == NULL) return SSH_ERR_SYSTEM_ERROR; if ((k = sshkey_new(KEY_UNSPEC)) == NULL) { @@ -238,7 +273,8 @@ for (; *cp && (*cp == ' ' || *cp == '\t'); cp++) ; if (*cp) { - if ((r = sshkey_read(k, &cp)) == 0) { + char *pkalg = NULL; + if ((r = sshkey_read_pkalg(k, &cp, &pkalg)) == 0) { cp[strcspn(cp, "\r\n")] = '\0'; if (commentp) { *commentp = strdup(*cp ? @@ -246,15 +282,21 @@ if (*commentp == NULL) r = SSH_ERR_ALLOC_FAIL; } - /* success */ - *kp = k; free(line); fclose(f); + if (pkalg) { + /* load extra certificates for RFC6187 keys */ + x509key_load_certs(pkalg, k, filename); + free(pkalg); + } + /* success */ + if (keyp != NULL) + *keyp = k; return r; } } } - free(k); + sshkey_free(k); free(line); fclose(f); return SSH_ERR_INVALID_FORMAT; @@ -264,105 +306,61 @@ int sshkey_load_public(const char *filename, struct sshkey **keyp, char **commentp) { - char *pubfile = NULL; - int r, oerrno; + int r; - if (keyp != NULL) - *keyp = NULL; - if (commentp != NULL) - *commentp = NULL; + debug3_f("filename=%s", (filename ? filename : "?!?")); +#ifdef USE_OPENSSL_STORE2 + if (strncmp(filename, "store:", 6) == 0) { + return store_try_load_public(filename + 6, keyp, commentp); + } +#endif +#ifdef USE_OPENSSL_ENGINE + if (strncmp(filename, "engine:", 7) == 0) { + return engine_try_load_public(filename + 7, keyp, commentp); + } +#endif - if ((r = sshkey_try_load_public(keyp, filename, commentp)) == 0) - goto out; + r = sshkey_try_load_public(filename, keyp, commentp); + if (r == 0) return 0; /* try .pub suffix */ - if (asprintf(&pubfile, "%s.pub", filename) == -1) +{ char *pubfile = NULL; + if (asprintf(&pubfile, "%s.pub", filename) < 0) return SSH_ERR_ALLOC_FAIL; - if ((r = sshkey_try_load_public(keyp, pubfile, commentp)) == 0) - goto out; + debug3_f("pubfile=%s", pubfile); + + r = sshkey_try_load_public(pubfile, keyp, commentp); + + free(pubfile); +} + if (r == 0) return 0; /* finally, try to extract public key from private key file */ - if ((r = sshkey_load_pubkey_from_private(filename, keyp)) == 0) - goto out; + r = sshkey_load_pubkey_from_private(filename, keyp); + if (r == 0) return 0; - /* Pretend we couldn't find the key */ - r = SSH_ERR_SYSTEM_ERROR; + /* pretend missing files */ errno = ENOENT; - - out: - oerrno = errno; - free(pubfile); - errno = oerrno; - return r; + return SSH_ERR_SYSTEM_ERROR; } /* Load the certificate associated with the named private key */ int sshkey_load_cert(const char *filename, struct sshkey **keyp) { - struct sshkey *pub = NULL; char *file = NULL; - int r = SSH_ERR_INTERNAL_ERROR; - - if (keyp != NULL) - *keyp = NULL; - - if (asprintf(&file, "%s-cert.pub", filename) == -1) - return SSH_ERR_ALLOC_FAIL; - - r = sshkey_try_load_public(keyp, file, NULL); - free(file); - sshkey_free(pub); - return r; -} - -/* Load private key and certificate */ -int -sshkey_load_private_cert(int type, const char *filename, const char *passphrase, - struct sshkey **keyp) -{ - struct sshkey *key = NULL, *cert = NULL; int r; + debug3_f("filename=%s", (filename ? filename : "?!?")); if (keyp != NULL) *keyp = NULL; - switch (type) { -#ifdef WITH_OPENSSL - case KEY_RSA: - case KEY_DSA: - case KEY_ECDSA: -#endif /* WITH_OPENSSL */ - case KEY_ED25519: - case KEY_XMSS: - case KEY_UNSPEC: - break; - default: - return SSH_ERR_KEY_TYPE_UNKNOWN; - } - - if ((r = sshkey_load_private_type(type, filename, - passphrase, &key, NULL)) != 0 || - (r = sshkey_load_cert(filename, &cert)) != 0) - goto out; + if (asprintf(&file, "%s-cert.pub", filename) < 0) + return SSH_ERR_ALLOC_FAIL; - /* Make sure the private key matches the certificate */ - if (sshkey_equal_public(key, cert) == 0) { - r = SSH_ERR_KEY_CERT_MISMATCH; - goto out; - } + r = sshkey_try_load_public(file, keyp, NULL); - if ((r = sshkey_to_certified(key)) != 0 || - (r = sshkey_cert_copy(cert, key)) != 0) - goto out; - r = 0; - if (keyp != NULL) { - *keyp = key; - key = NULL; - } - out: - sshkey_free(key); - sshkey_free(cert); + free(file); return r; } @@ -495,34 +493,43 @@ sshkey_save_public(const struct sshkey *key, const char *path, const char *comment) { - int fd, oerrno; + int fd; FILE *f = NULL; int r = SSH_ERR_INTERNAL_ERROR; - if ((fd = open(path, O_WRONLY|O_CREAT|O_TRUNC, 0644)) == -1) + if ((fd = open(path, O_WRONLY|O_CREAT|O_TRUNC, 0644)) == -1) { + debug3_f("open: %s", strerror(errno)); return SSH_ERR_SYSTEM_ERROR; + } if ((f = fdopen(fd, "w")) == NULL) { + debug3_f("fdopen: %s", strerror(errno)); r = SSH_ERR_SYSTEM_ERROR; - close(fd); goto fail; } + if ((r = sshkey_write(key, f)) != 0) goto fail; fprintf(f, " %s\n", comment); + if (ferror(f)) { + debug3("write key failed: %s", strerror(errno)); r = SSH_ERR_SYSTEM_ERROR; goto fail; } if (fclose(f) != 0) { r = SSH_ERR_SYSTEM_ERROR; f = NULL; - fail: - if (f != NULL) { - oerrno = errno; - fclose(f); - errno = oerrno; - } - return r; + goto fail; } + return 0; +fail: +{ int oerrno = errno; + if (f != NULL) + fclose(f); + else + close(fd); + errno = oerrno; +} + return r; } diff -ruN openssh-9.4p1/authfile.h openssh-9.4p1+x509-14.2.1/authfile.h --- openssh-9.4p1/authfile.h 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/authfile.h 2023-08-20 10:07:00.000000000 +0300 @@ -38,11 +38,7 @@ int sshkey_load_cert(const char *, struct sshkey **); int sshkey_load_public(const char *, struct sshkey **, char **); int sshkey_load_private(const char *, const char *, struct sshkey **, char **); -int sshkey_load_private_cert(int, const char *, const char *, - struct sshkey **); -int sshkey_load_private_type(int, const char *, const char *, - struct sshkey **, char **); -int sshkey_load_private_type_fd(int fd, int type, const char *passphrase, +int sshkey_load_private_fd(int fd, const char *passphrase, struct sshkey **keyp, char **commentp); int sshkey_perm_ok(int, const char *); int sshkey_in_file(struct sshkey *, const char *, int, int); diff -ruN openssh-9.4p1/auth.h openssh-9.4p1+x509-14.2.1/auth.h --- openssh-9.4p1/auth.h 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/auth.h 2023-08-20 10:07:00.000000000 +0300 @@ -1,8 +1,9 @@ /* $OpenBSD: auth.h,v 1.106 2022/06/15 16:08:25 djm Exp $ */ - /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * + * Copyright (c) 2014-2022 Roumen Petrov. All rights reserved. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -106,8 +107,7 @@ struct Authmethod { char *name; - char *synonym; - int (*userauth)(struct ssh *, const char *); + int (*userauth)(struct ssh *); int *enabled; }; @@ -133,10 +133,11 @@ int auth_password(struct ssh *, const char *); -int hostbased_key_allowed(struct ssh *, struct passwd *, - const char *, char *, struct sshkey *); -int user_key_allowed(struct ssh *ssh, struct passwd *, struct sshkey *, - int, struct sshauthopt **); +int hostbased_xkey_allowed(struct ssh *, struct passwd *, ssh_verify_ctx *, + const char *, char *); +int user_xkey_allowed(struct ssh *, struct passwd *, ssh_verify_ctx *, int, + struct sshauthopt **); + int auth2_key_already_used(Authctxt *, const struct sshkey *); /* @@ -202,13 +203,14 @@ const char *, const char *); /* hostkey handling */ -struct sshkey *get_hostkey_by_index(int); -struct sshkey *get_hostkey_public_by_index(int, struct ssh *); -struct sshkey *get_hostkey_public_by_type(int, int, struct ssh *); -struct sshkey *get_hostkey_private_by_type(int, int, struct ssh *); +struct sshkey *get_hostkey_by_index(u_int); +struct sshkey *get_hostkey_public_by_index(u_int, struct ssh *); +struct sshkey *get_hostkey_public_by_alg(const char*, struct ssh *); +struct sshkey *get_hostkey_private_by_alg(const char*, struct ssh *); int get_hostkey_index(struct sshkey *, int, struct ssh *); -int sshd_hostkey_sign(struct ssh *, struct sshkey *, struct sshkey *, - u_char **, size_t *, const u_char *, size_t, const char *); + +int Xsshd_hostkey_sign(struct ssh *ssh, ssh_sign_ctx *ctx, struct sshkey *pubkey, + u_char **signature, size_t *slen, const u_char *data, size_t dlen); /* Key / cert options linkage to auth layer */ const struct sshauthopt *auth_options(struct ssh *); @@ -227,12 +229,8 @@ /* auth2-pubkeyfile.c */ int auth_authorise_keyopts(struct passwd *, struct sshauthopt *, int, const char *, const char *, const char *); -int auth_check_principals_line(char *, const struct sshkey_cert *, - const char *, struct sshauthopt **); int auth_process_principals(FILE *, const char *, const struct sshkey_cert *, struct sshauthopt **); -int auth_check_authkey_line(struct passwd *, struct sshkey *, - char *, const char *, const char *, const char *, struct sshauthopt **); int auth_check_authkeys_file(struct passwd *, FILE *, char *, struct sshkey *, const char *, const char *, struct sshauthopt **); FILE *auth_openkeyfile(const char *, struct passwd *, int); diff -ruN openssh-9.4p1/auth-krb5.c openssh-9.4p1+x509-14.2.1/auth-krb5.c --- openssh-9.4p1/auth-krb5.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/auth-krb5.c 2023-08-20 10:07:01.000000000 +0300 @@ -38,8 +38,6 @@ #include "ssh.h" #include "packet.h" #include "log.h" -#include "sshbuf.h" -#include "sshkey.h" #include "misc.h" #include "servconf.h" #include "uidswap.h" @@ -193,7 +191,7 @@ out: restore_uid(); - + free(platform_client); if (problem) { @@ -245,8 +243,12 @@ char ccname[40]; mode_t old_umask; +{ const char *tmpdir = getenv("TMPDIR"); + if (tmpdir == NULL) tmpdir = "/tmp"; + ret = snprintf(ccname, sizeof(ccname), - "FILE:/tmp/krb5cc_%d_XXXXXXXXXX", geteuid()); + "FILE:%s/krb5cc_%d_XXXXXXXXXX", tmpdir, geteuid()); +} if (ret < 0 || (size_t)ret >= sizeof(ccname)) return ENOMEM; diff -ruN openssh-9.4p1/auth-options.c openssh-9.4p1+x509-14.2.1/auth-options.c --- openssh-9.4p1/auth-options.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/auth-options.c 2023-08-20 10:07:01.000000000 +0300 @@ -1,4 +1,4 @@ -/* $OpenBSD: auth-options.c,v 1.101 2023/07/14 07:44:21 dtucker Exp $ */ +/* $OpenBSD: auth-options.c,v 1.100 2023/07/14 05:31:44 djm Exp $ */ /* * Copyright (c) 2018 Damien Miller * @@ -24,9 +24,6 @@ #include #include #include -#ifdef HAVE_STDINT_H -# include -#endif #include #include #include @@ -51,11 +48,11 @@ *dstp = NULL; *ndstp = 0; - if (nsrc == 0) return 0; - if (nsrc >= SIZE_MAX / sizeof(*src) || - (dst = calloc(nsrc, sizeof(*src))) == NULL) + if (nsrc > SIZE_MAX / sizeof(*src)) + return -1; + if ((dst = calloc(nsrc, sizeof(*src))) == NULL) return -1; for (i = 0; i < nsrc; i++) { if ((dst[i] = strdup(src[i])) == NULL) { @@ -99,10 +96,7 @@ name, sshbuf_len(data)); found = 0; if ((which & OPTIONS_EXTENSIONS) != 0) { - if (strcmp(name, "no-touch-required") == 0) { - opts->no_require_user_presence = 1; - found = 1; - } else if (strcmp(name, "permit-X11-forwarding") == 0) { + if (strcmp(name, "permit-X11-forwarding") == 0) { opts->permit_x11_forwarding_flag = 1; found = 1; } else if (strcmp(name, @@ -122,10 +116,7 @@ } } if (!found && (which & OPTIONS_CRITICAL) != 0) { - if (strcmp(name, "verify-required") == 0) { - opts->require_verify = 1; - found = 1; - } else if (strcmp(name, "force-command") == 0) { + if (strcmp(name, "force-command") == 0) { if ((r = sshbuf_get_cstring(data, &command, NULL)) != 0) { error_r(r, "Unable to parse \"%s\" " @@ -140,7 +131,8 @@ } opts->force_command = command; found = 1; - } else if (strcmp(name, "source-address") == 0) { + } + if (strcmp(name, "source-address") == 0) { if ((r = sshbuf_get_cstring(data, &allowed, NULL)) != 0) { error_r(r, "Unable to parse \"%s\" " @@ -157,6 +149,7 @@ if (addr_match_cidr_list(NULL, allowed) == -1) { error("Certificate source-address " "contents invalid"); + free(allowed); goto out; } opts->required_from_host_cert = allowed; @@ -271,7 +264,7 @@ * Allow a bare port number in permitlisten to indicate a * listen_host wildcard. */ - if (asprintf(&tmp, "*:%s", opt) == -1) { + if (asprintf(&tmp, "*:%s", opt) < 0) { free(opt); *errstrp = "memory allocation failed"; return -1; @@ -323,12 +316,11 @@ struct sshauthopt * sshauthopt_parse(const char *opts, const char **errstrp) { - char **oarray, *opt, *cp, *tmp; + char *opt; int r; struct sshauthopt *ret = NULL; const char *errstr = "unknown error"; uint64_t valid_before; - size_t i, l; if (errstrp != NULL) *errstrp = NULL; @@ -355,10 +347,6 @@ ret->permit_agent_forwarding_flag = r == 1; } else if ((r = opt_flag("x11-forwarding", 1, &opts)) != -1) { ret->permit_x11_forwarding_flag = r == 1; - } else if ((r = opt_flag("touch-required", 1, &opts)) != -1) { - ret->no_require_user_presence = r != 1; /* NB. flip */ - } else if ((r = opt_flag("verify-required", 1, &opts)) != -1) { - ret->require_verify = r == 1; } else if ((r = opt_flag("pty", 1, &opts)) != -1) { ret->permit_pty_flag = r == 1; } else if ((r = opt_flag("user-rc", 1, &opts)) != -1) { @@ -409,46 +397,48 @@ if ((opt = opt_dequote(&opts, &errstr)) == NULL) goto fail; /* env name must be alphanumeric and followed by '=' */ - if ((tmp = strchr(opt, '=')) == NULL) { - free(opt); - errstr = "invalid environment string"; - goto fail; - } + { char *cp, *tmp; if ((cp = strdup(opt)) == NULL) { free(opt); goto alloc_fail; } - l = (size_t)(tmp - opt); - cp[l] = '\0'; /* truncate at '=' */ + if ((tmp = strchr(cp, '=')) == NULL) { + free(cp); + free(opt); + errstr = "invalid environment string"; + goto fail; + } + *tmp = '\0'; /* truncate at '=' */ if (!valid_env_name(cp)) { free(cp); free(opt); errstr = "invalid environment string"; goto fail; } + { size_t i, l = strlen(cp); /* Check for duplicates; XXX O(n*log(n)) */ for (i = 0; i < ret->nenv; i++) { if (strncmp(ret->env[i], cp, l) == 0 && - ret->env[i][l] == '=') - break; - } - free(cp); - /* First match wins */ - if (i >= ret->nenv) { - /* Append it. */ - oarray = ret->env; - if ((ret->env = recallocarray(ret->env, - ret->nenv, ret->nenv + 1, - sizeof(*ret->env))) == NULL) { + ret->env[i][l] == '=') { + /* First match wins */ + free(cp); free(opt); - /* put it back for cleanup */ - ret->env = oarray; - goto alloc_fail; + goto done; } - ret->env[ret->nenv++] = opt; - opt = NULL; /* transferred */ } - free(opt); + } + free(cp); + } + /* Append it. */ + { char **oarray = ret->env; + if ((ret->env = recallocarray(ret->env, ret->nenv, + ret->nenv + 1, sizeof(*ret->env))) == NULL) { + free(opt); + ret->env = oarray; /* put it back for cleanup */ + goto alloc_fail; + } + ret->env[ret->nenv++] = opt; + } } else if (opt_match(&opts, "permitopen")) { if (handle_permit(&opts, 0, &ret->permitopen, &ret->npermitopen, &errstr) != 0) @@ -485,6 +475,7 @@ } } +done: /* success */ if (errstrp != NULL) *errstrp = NULL; @@ -596,16 +587,12 @@ } #define OPTFLAG_AND(x) ret->x = (primary->x == 1) && (additional->x == 1) -#define OPTFLAG_OR(x) ret->x = (primary->x == 1) || (additional->x == 1) /* Permissive flags are logical-AND (i.e. must be set in both) */ OPTFLAG_AND(permit_port_forwarding_flag); OPTFLAG_AND(permit_agent_forwarding_flag); OPTFLAG_AND(permit_x11_forwarding_flag); OPTFLAG_AND(permit_pty_flag); OPTFLAG_AND(permit_user_rc); - OPTFLAG_AND(no_require_user_presence); - /* Restrictive flags are logical-OR (i.e. must be set in either) */ - OPTFLAG_OR(require_verify); #undef OPTFLAG_AND /* Earliest expiry time should win */ @@ -675,8 +662,6 @@ OPTSCALAR(cert_authority); OPTSCALAR(force_tun_device); OPTSCALAR(valid_before); - OPTSCALAR(no_require_user_presence); - OPTSCALAR(require_verify); #undef OPTSCALAR #define OPTSTRING(x) \ do { \ @@ -707,14 +692,14 @@ { struct sshbuf *b; size_t i; - int r = SSH_ERR_INTERNAL_ERROR; + int r; if (n > INT_MAX) - return SSH_ERR_INTERNAL_ERROR; + return SSH_ERR_INVALID_ARGUMENT; - if ((b = sshbuf_new()) == NULL) { + if ((b = sshbuf_new()) == NULL) return SSH_ERR_ALLOC_FAIL; - } + for (i = 0; i < n; i++) { if ((r = sshbuf_put_cstring(b, a[i])) != 0) goto out; @@ -722,6 +707,7 @@ if ((r = sshbuf_put_u32(m, n)) != 0 || (r = sshbuf_put_stringb(m, b)) != 0) goto out; + /* success */ r = 0; out: @@ -800,7 +786,7 @@ { int r = SSH_ERR_INTERNAL_ERROR; - /* Flag options */ + /* Flag and simple integer options */ if ((r = sshbuf_put_u8(m, opts->permit_port_forwarding_flag)) != 0 || (r = sshbuf_put_u8(m, opts->permit_agent_forwarding_flag)) != 0 || (r = sshbuf_put_u8(m, opts->permit_x11_forwarding_flag)) != 0 || @@ -808,12 +794,7 @@ (r = sshbuf_put_u8(m, opts->permit_user_rc)) != 0 || (r = sshbuf_put_u8(m, opts->restricted)) != 0 || (r = sshbuf_put_u8(m, opts->cert_authority)) != 0 || - (r = sshbuf_put_u8(m, opts->no_require_user_presence)) != 0 || - (r = sshbuf_put_u8(m, opts->require_verify)) != 0) - return r; - - /* Simple integer options */ - if ((r = sshbuf_put_u64(m, opts->valid_before)) != 0) + (r = sshbuf_put_u64(m, opts->valid_before)) != 0) return r; /* tunnel number can be negative to indicate "unset" */ @@ -857,7 +838,6 @@ if ((opts = calloc(1, sizeof(*opts))) == NULL) return SSH_ERR_ALLOC_FAIL; - /* Flag options */ #define OPT_FLAG(x) \ do { \ if ((r = sshbuf_get_u8(m, &f)) != 0) \ @@ -871,11 +851,8 @@ OPT_FLAG(permit_user_rc); OPT_FLAG(restricted); OPT_FLAG(cert_authority); - OPT_FLAG(no_require_user_presence); - OPT_FLAG(require_verify); #undef OPT_FLAG - /* Simple integer options */ if ((r = sshbuf_get_u64(m, &opts->valid_before)) != 0) goto out; diff -ruN openssh-9.4p1/auth-options.h openssh-9.4p1+x509-14.2.1/auth-options.h --- openssh-9.4p1/auth-options.h 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/auth-options.h 2023-08-20 10:07:00.000000000 +0300 @@ -71,11 +71,6 @@ */ char *required_from_host_cert; char *required_from_host_keys; - - /* Key requires user presence asserted */ - int no_require_user_presence; - /* Key requires user verification (e.g. PIN) */ - int require_verify; }; struct sshauthopt *sshauthopt_new(void); diff -ruN openssh-9.4p1/auth-pam.c openssh-9.4p1+x509-14.2.1/auth-pam.c --- openssh-9.4p1/auth-pam.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/auth-pam.c 2023-08-20 10:07:01.000000000 +0300 @@ -88,7 +88,6 @@ #include "xmalloc.h" #include "sshbuf.h" -#include "ssherr.h" #include "hostfile.h" #include "auth.h" #include "auth-pam.h" @@ -127,17 +126,13 @@ * pthreads, which unconditionally define pthread_t via sys/types.h * (e.g. Linux) */ -typedef pthread_t sp_pthread_t; +typedef pthread_t ssh_pthread_t; #else -typedef pid_t sp_pthread_t; -#define pthread_exit fake_pthread_exit -#define pthread_create fake_pthread_create -#define pthread_cancel fake_pthread_cancel -#define pthread_join fake_pthread_join +typedef pid_t ssh_pthread_t; #endif struct pam_ctxt { - sp_pthread_t pam_thread; + ssh_pthread_t pam_thread; int pam_psock; int pam_csock; int pam_done; @@ -150,6 +145,10 @@ /* * Simulate threads with processes. */ +#define pthread_exit ssh_pthread_exit +#define pthread_create ssh_pthread_create +#define pthread_cancel ssh_pthread_cancel +#define pthread_join ssh_pthread_join static int sshpam_thread_status = -1; static sshsig_t sshpam_oldsig; @@ -157,12 +156,13 @@ static void sshpam_sigchld_handler(int sig) { + UNUSED(sig); ssh_signal(SIGCHLD, SIG_DFL); if (cleanup_ctxt == NULL) return; /* handler called after PAM cleanup, shouldn't happen */ if (waitpid(cleanup_ctxt->pam_thread, &sshpam_thread_status, WNOHANG) <= 0) { - /* PAM thread has not exitted, privsep slave must have */ + /* PAM thread has not exitted, privsep child must have */ kill(cleanup_ctxt->pam_thread, SIGTERM); while (waitpid(cleanup_ctxt->pam_thread, &sshpam_thread_status, 0) == -1) { @@ -180,21 +180,21 @@ sigdie("PAM: authentication thread exited uncleanly"); } -/* ARGSUSED */ static void pthread_exit(void *value) { + UNUSED(value); _exit(0); } -/* ARGSUSED */ static int -pthread_create(sp_pthread_t *thread, const void *attr, +pthread_create(ssh_pthread_t *thread, const void *attr, void *(*thread_start)(void *), void *arg) { pid_t pid; struct pam_ctxt *ctx = arg; + UNUSED(attr); sshpam_thread_status = -1; switch ((pid = fork())) { case -1: @@ -215,25 +215,25 @@ } static int -pthread_cancel(sp_pthread_t thread) +pthread_cancel(ssh_pthread_t thread) { ssh_signal(SIGCHLD, sshpam_oldsig); return (kill(thread, SIGTERM)); } -/* ARGSUSED */ static int -pthread_join(sp_pthread_t thread, void **value) +pthread_join(ssh_pthread_t thread, void **value) { int status; + UNUSED(value); if (sshpam_thread_status != -1) return (sshpam_thread_status); ssh_signal(SIGCHLD, sshpam_oldsig); while (waitpid(thread, &status, 0) == -1) { if (errno == EINTR) continue; - fatal("%s: waitpid: %s", __func__, strerror(errno)); + fatal_f("waitpid: %s", strerror(errno)); } return (status); } @@ -291,10 +291,10 @@ if (sshpam_authctxt == NULL) fatal("PAM: sshpam_authctxt not initialized"); if (setreuid(sshpam_authctxt->pw->pw_uid, -1) == -1) - fatal("%s: setreuid failed: %s", __func__, strerror(errno)); + fatal_f("setreuid failed: %s", strerror(errno)); result = pam_chauthtok(pamh, flags); if (setreuid(0, -1) == -1) - fatal("%s: setreuid failed: %s", __func__, strerror(errno)); + fatal_f("setreuid failed: %s", strerror(errno)); return result; } # define pam_chauthtok(a,b) (sshpam_chauthtok_ruid((a), (b))) @@ -306,9 +306,9 @@ extern struct sshauthopt *auth_opts; static int saved_port, saved_agent, saved_x11; - debug3("%s %d", __func__, reqd); + debug3_f("reqd: %d", reqd); if (sshpam_authctxt == NULL) - fatal("%s: PAM authctxt not initialized", __func__); + fatal_f("PAM authctxt not initialized"); sshpam_authctxt->force_pwchange = reqd; if (reqd) { saved_port = auth_opts->permit_port_forwarding_flag; @@ -332,40 +332,43 @@ import_environments(struct sshbuf *b) { char *env; - u_int n, i, num_env; + u_int num_env; + u_int32_t n, i; int r; - debug3("PAM: %s entering", __func__); + debug3_f("PAM entering"); #ifndef UNSUPPORTED_POSIX_THREADS_HACK /* Import variables set by do_pam_account */ if ((r = sshbuf_get_u32(b, &n)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); - if (n > INT_MAX) - fatal("%s: invalid PAM account status %u", __func__, n); + fatal_fr(r, "buffer error"); + if (n > INT32_MAX) + fatal_f("invalid PAM account status %u", (unsigned)n); sshpam_account_status = (int)n; + if ((r = sshbuf_get_u32(b, &n)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "buffer error"); sshpam_password_change_required(n != 0); /* Import environment from subprocess */ - if ((r = sshbuf_get_u32(b, &num_env)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); - if (num_env > 1024) { + if ((r = sshbuf_get_u32(b, &n)) != 0) + fatal_fr(r, "buffer error"); + num_env = n; + if (num_env > 1024) fatal_f("received %u environment variables, expected <= 1024", num_env); - } sshpam_env = xcalloc(num_env + 1, sizeof(*sshpam_env)); debug3("PAM: num env strings %u", num_env); for(i = 0; i < num_env; i++) { if ((r = sshbuf_get_cstring(b, &(sshpam_env[i]), NULL)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "buffer error"); } sshpam_env[num_env] = NULL; /* Import PAM environment from subprocess */ - if ((r = sshbuf_get_u32(b, &num_env)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + if ((r = sshbuf_get_u32(b, &n)) != 0) + fatal_fr(r, "buffer error"); + num_env = n; if (num_env > 1024) { fatal_f("received %u PAM env variables, expected <= 1024", num_env); @@ -373,7 +376,7 @@ debug("PAM: num PAM env strings %u", num_env); for (i = 0; i < num_env; i++) { if ((r = sshbuf_get_cstring(b, &env, NULL)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "buffer error"); /* Errors are not fatal here */ if ((r = pam_putenv(sshpam_handle, env)) != PAM_SUCCESS) { error("PAM: pam_putenv: %s", @@ -401,7 +404,7 @@ int r, i; u_char status; - debug3("PAM: %s entering, %d messages", __func__, n); + debug3_f("PAM entering, %d messages", n); *resp = NULL; if (data == NULL) { @@ -414,10 +417,8 @@ if ((reply = calloc(n, sizeof(*reply))) == NULL) return PAM_CONV_ERR; - if ((buffer = sshbuf_new()) == NULL) { - free(reply); - return PAM_CONV_ERR; - } + if ((buffer = sshbuf_new()) == NULL) + fatal_f("sshbuf_new failed"); for (i = 0; i < n; ++i) { switch (PAM_MSG_MEMBER(msg, i, msg_style)) { @@ -425,8 +426,7 @@ case PAM_PROMPT_ECHO_ON: if ((r = sshbuf_put_cstring(buffer, PAM_MSG_MEMBER(msg, i, msg))) != 0) - fatal("%s: buffer error: %s", - __func__, ssh_err(r)); + fatal_fr(r, "buffer error"); if (ssh_msg_send(ctxt->pam_csock, PAM_MSG_MEMBER(msg, i, msg_style), buffer) == -1) goto fail; @@ -434,21 +434,18 @@ if (ssh_msg_recv(ctxt->pam_csock, buffer) == -1) goto fail; if ((r = sshbuf_get_u8(buffer, &status)) != 0) - fatal("%s: buffer error: %s", - __func__, ssh_err(r)); + fatal_fr(r, "buffer error"); if (status != PAM_AUTHTOK) goto fail; if ((r = sshbuf_get_cstring(buffer, &reply[i].resp, NULL)) != 0) - fatal("%s: buffer error: %s", - __func__, ssh_err(r)); + fatal_fr(r, "buffer error"); break; case PAM_ERROR_MSG: case PAM_TEXT_INFO: if ((r = sshbuf_put_cstring(buffer, PAM_MSG_MEMBER(msg, i, msg))) != 0) - fatal("%s: buffer error: %s", - __func__, ssh_err(r)); + fatal_fr(r, "buffer error"); if (ssh_msg_send(ctxt->pam_csock, PAM_MSG_MEMBER(msg, i, msg_style), buffer) == -1) goto fail; @@ -511,10 +508,10 @@ sshpam_conv.appdata_ptr = ctxt; if (sshpam_authctxt == NULL) - fatal("%s: PAM authctxt not initialized", __func__); + fatal_f("PAM authctxt not initialized"); if ((buffer = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new failed", __func__); + fatal_f("sshbuf_new failed"); sshpam_err = pam_set_item(sshpam_handle, PAM_CONV, (const void *)&sshpam_conv); @@ -539,38 +536,38 @@ } if ((r = sshbuf_put_cstring(buffer, "OK")) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "buffer error"); #ifndef UNSUPPORTED_POSIX_THREADS_HACK /* Export variables set by do_pam_account */ if ((r = sshbuf_put_u32(buffer, sshpam_account_status)) != 0 || (r = sshbuf_put_u32(buffer, sshpam_authctxt->force_pwchange)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "buffer error"); /* Export any environment strings set in child */ for (i = 0; environ[i] != NULL; i++) { /* Count */ - if (i > INT_MAX) - fatal("%s: too many environment strings", __func__); + if (i > INT32_MAX) + fatal_f("too many environment strings"); } if ((r = sshbuf_put_u32(buffer, i)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "buffer error"); for (i = 0; environ[i] != NULL; i++) { if ((r = sshbuf_put_cstring(buffer, environ[i])) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "buffer error"); } /* Export any environment strings set by PAM in child */ env_from_pam = pam_getenvlist(sshpam_handle); for (i = 0; env_from_pam != NULL && env_from_pam[i] != NULL; i++) { /* Count */ - if (i > INT_MAX) - fatal("%s: too many PAM environment strings", __func__); + if (i > INT32_MAX) + fatal_f("too many PAM environment strings"); } if ((r = sshbuf_put_u32(buffer, i)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "buffer error"); for (i = 0; env_from_pam != NULL && env_from_pam[i] != NULL; i++) { if ((r = sshbuf_put_cstring(buffer, env_from_pam[i])) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "buffer error"); } #endif /* UNSUPPORTED_POSIX_THREADS_HACK */ @@ -582,7 +579,7 @@ auth_fail: if ((r = sshbuf_put_cstring(buffer, pam_strerror(sshpam_handle, sshpam_err))) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "buffer error"); /* XXX - can't do much about an error here */ if (sshpam_err == PAM_ACCT_EXPIRED) ssh_msg_send(ctxt->pam_csock, PAM_ACCT_EXPIRED, buffer); @@ -601,7 +598,7 @@ { struct pam_ctxt *ctxt = cleanup_ctxt; - debug3("PAM: %s entering", __func__); + debug3_f("PAM entering"); if (ctxt != NULL && ctxt->pam_thread != 0) { pthread_cancel(ctxt->pam_thread); pthread_join(ctxt->pam_thread, NULL); @@ -616,7 +613,10 @@ sshpam_null_conv(int n, sshpam_const struct pam_message **msg, struct pam_response **resp, void *data) { - debug3("PAM: %s entering, %d messages", __func__, n); + UNUSED(msg); + UNUSED(resp); + UNUSED(data); + debug3_f("PAM entering, %d messages", n); return (PAM_CONV_ERR); } @@ -629,7 +629,8 @@ struct pam_response *reply; int r, i; - debug3("PAM: %s called with %d messages", __func__, n); + UNUSED(data); + debug3_f("PAM called with %d messages", n); *resp = NULL; if (n <= 0 || n > PAM_MAX_NUM_MSG) @@ -644,8 +645,7 @@ case PAM_TEXT_INFO: if ((r = sshbuf_putf(loginmsg, "%s\n", PAM_MSG_MEMBER(msg, i, msg))) != 0) - fatal("%s: buffer error: %s", - __func__, ssh_err(r)); + fatal_fr(r, "buffer error"); reply[i].resp_retcode = PAM_SUCCESS; break; default: @@ -692,7 +692,6 @@ { const char *pam_user, *user = authctxt->user; const char **ptr_pam_user = &pam_user; - int r; #if defined(PAM_SUN_CODEBASE) && defined(PAM_MAX_RESP_SIZE) /* Protect buggy PAM implementations from excessively long usernames */ @@ -702,8 +701,7 @@ #endif if (sshpam_handle == NULL) { if (ssh == NULL) { - fatal("%s: called initially with no " - "packet context", __func__); + fatal_f("called initially with no packet context"); } } if (sshpam_handle != NULL) { /* We already have a PAM context; check if the user matches */ @@ -752,9 +750,12 @@ xasprintf(&conninfo, "SSH_CONNECTION=%.50s %d %.50s %d", ssh_remote_ipaddr(ssh), ssh_remote_port(ssh), sshpam_laddr, ssh_local_port(ssh)); - if ((r = pam_putenv(sshpam_handle, conninfo)) != PAM_SUCCESS) - logit("pam_putenv: %s", pam_strerror(sshpam_handle, r)); - free(conninfo); + if ((sshpam_err = pam_putenv(sshpam_handle, conninfo)) != PAM_SUCCESS) + logit("pam_putenv: %s", pam_strerror(sshpam_handle, sshpam_err)); + free(conninfo); /* TODO, NOTE + - import_environments() does not free "environment" string + - do_pam_putenv free "compound" string + */ } #ifdef PAM_TTY_KLUDGE @@ -774,8 +775,10 @@ return (0); } +#define export_authinfo() sshpam_put_authinfo(__FILE__, __func__, __LINE__) + static void -expose_authinfo(const char *caller) +sshpam_put_authinfo(const char *file, const char *func, int line) { char *auth_info; @@ -788,9 +791,10 @@ auth_info = xstrdup(""); else if ((auth_info = sshbuf_dup_string( sshpam_authctxt->session_info)) == NULL) - fatal("%s: sshbuf_dup_string failed", __func__); + fatal_f("sshbuf_dup_string failed"); - debug2("%s: auth information in SSH_AUTH_INFO_0", caller); + sshlog_f(file, func, line, SYSLOG_LEVEL_DEBUG2, + "auth information in SSH_AUTH_INFO_0"); do_pam_putenv("SSH_AUTH_INFO_0", auth_info); free(auth_info); } @@ -801,7 +805,7 @@ struct pam_ctxt *ctxt; int result, socks[2]; - debug3("PAM: %s entering", __func__); + debug3_f("PAM entering"); /* * Refuse to start if we don't have PAM enabled or do_pam_account * has previously failed. @@ -815,7 +819,7 @@ return (NULL); } - expose_authinfo(__func__); + export_authinfo(); ctxt = xcalloc(1, sizeof *ctxt); /* Start the authentication thread */ @@ -848,12 +852,12 @@ size_t plen; u_char type; char *msg; - size_t len, mlen, nmesg = 0; + size_t len, mlen, nmsg = 0; int r; - debug3("PAM: %s entering", __func__); + debug3_f("PAM entering"); if ((buffer = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new failed", __func__); + fatal_f("sshbuf_new failed"); *name = xstrdup(""); *info = xstrdup(""); *prompts = xmalloc(sizeof(char *)); @@ -861,11 +865,11 @@ plen = 0; *echo_on = xmalloc(sizeof(u_int)); while (ssh_msg_recv(ctxt->pam_psock, buffer) == 0) { - if (++nmesg > PAM_MAX_NUM_MSG) + if (++nmsg > PAM_MAX_NUM_MSG) fatal_f("too many query messages"); if ((r = sshbuf_get_u8(buffer, &type)) != 0 || (r = sshbuf_get_cstring(buffer, &msg, &mlen)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "buffer error"); switch (type) { case PAM_PROMPT_ECHO_ON: case PAM_PROMPT_ECHO_OFF: @@ -916,8 +920,7 @@ debug("PAM: %s", **prompts); if ((r = sshbuf_put(loginmsg, **prompts, strlen(**prompts))) != 0) - fatal("%s: buffer error: %s", - __func__, ssh_err(r)); + fatal_fr(r, "buffer error"); free(**prompts); **prompts = NULL; } @@ -966,7 +969,7 @@ size_t i, l = wire_password != NULL ? strlen(wire_password) : 0; if (l >= INT_MAX) - fatal("%s: password length too long: %zu", __func__, l); + fatal_f("password length too long: %zu", l); ret = malloc(l + 1); if (ret == NULL) @@ -986,7 +989,7 @@ char *fake; int r; - debug2("PAM: %s entering, %u responses", __func__, num); + debug2_f("PAM entering, %u responses", num); switch (ctxt->pam_done) { case 1: sshpam_authenticated = 1; @@ -1001,16 +1004,16 @@ return (-1); } if ((buffer = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new failed", __func__); + fatal_f("sshbuf_new failed"); if (sshpam_authctxt->valid && (sshpam_authctxt->pw->pw_uid != 0 || options.permit_root_login == PERMIT_YES)) { if ((r = sshbuf_put_cstring(buffer, *resp)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "buffer error"); } else { fake = fake_password(*resp); if ((r = sshbuf_put_cstring(buffer, fake)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "buffer error"); free(fake); } if (ssh_msg_send(ctxt->pam_psock, PAM_AUTHTOK, buffer) == -1) { @@ -1026,7 +1029,7 @@ { struct pam_ctxt *ctxt = ctxtp; - debug3("PAM: %s entering", __func__); + debug3_f("PAM entering"); sshpam_thread_cleanup(); free(ctxt); /* @@ -1078,14 +1081,14 @@ u_int do_pam_account(void) { - debug("%s: called", __func__); + debug_f("called"); if (sshpam_account_status != -1) return (sshpam_account_status); - expose_authinfo(__func__); + export_authinfo(); sshpam_err = pam_acct_mgmt(sshpam_handle, 0); - debug3("PAM: %s pam_acct_mgmt = %d (%s)", __func__, sshpam_err, + debug3_f("PAM pam_acct_mgmt = %d (%s)", sshpam_err, pam_strerror(sshpam_handle, sshpam_err)); if (sshpam_err != PAM_SUCCESS && sshpam_err != PAM_NEW_AUTHTOK_REQD) { @@ -1135,7 +1138,8 @@ struct pam_response *reply; int i; - debug3("PAM: %s called with %d messages", __func__, n); + UNUSED(data); + debug3_f("PAM called with %d messages", n); *resp = NULL; @@ -1209,7 +1213,7 @@ { debug3("PAM: opening session"); - expose_authinfo(__func__); + export_authinfo(); sshpam_err = pam_set_item(sshpam_handle, PAM_CONV, (const void *)&store_conv); @@ -1294,7 +1298,8 @@ int r, i; size_t len; - debug3("PAM: %s called with %d messages", __func__, n); + UNUSED(data); + debug3_f("PAM called with %d messages", n); *resp = NULL; @@ -1319,8 +1324,7 @@ if (len > 0) { if ((r = sshbuf_putf(loginmsg, "%s\n", PAM_MSG_MEMBER(msg, i, msg))) != 0) - fatal("%s: buffer error: %s", - __func__, ssh_err(r)); + fatal_fr(r, "buffer error"); } if ((reply[i].resp = strdup("")) == NULL) goto fail; @@ -1354,8 +1358,8 @@ char *fake = NULL; if (!options.use_pam || sshpam_handle == NULL) - fatal("PAM: %s called when PAM disabled or failed to " - "initialise.", __func__); + fatal_f("PAM: called when PAM disabled or failed to " + "initialise."); sshpam_password = password; sshpam_authctxt = authctxt; @@ -1372,7 +1376,7 @@ sshpam_err = pam_set_item(sshpam_handle, PAM_CONV, (const void *)&passwd_conv); if (sshpam_err != PAM_SUCCESS) - fatal("PAM: %s: failed to set PAM_CONV: %s", __func__, + fatal_f("PAM: failed to set PAM_CONV: %s", pam_strerror(sshpam_handle, sshpam_err)); sshpam_err = pam_authenticate(sshpam_handle, flags); diff -ruN openssh-9.4p1/auth-passwd.c openssh-9.4p1+x509-14.2.1/auth-passwd.c --- openssh-9.4p1/auth-passwd.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/auth-passwd.c 2023-08-20 10:07:01.000000000 +0300 @@ -47,7 +47,6 @@ #include "packet.h" #include "sshbuf.h" -#include "ssherr.h" #include "log.h" #include "misc.h" #include "servconf.h" diff -ruN openssh-9.4p1/auth-rhosts.c openssh-9.4p1+x509-14.2.1/auth-rhosts.c --- openssh-9.4p1/auth-rhosts.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/auth-rhosts.c 2023-08-20 10:07:01.000000000 +0300 @@ -1,11 +1,11 @@ -/* $OpenBSD: auth-rhosts.c,v 1.57 2022/12/09 00:17:40 dtucker Exp $ */ +/* $OpenBSD: auth-rhosts.c,v 1.56 2022/02/23 21:21:49 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland * All rights reserved * Rhosts authentication. This file contains code to check whether to admit * the login based on rhosts authentication. This file also processes - * /etc/hosts.equiv. + * hosts.equiv(5) files. * * As far as I am concerned, the code I have written for this software * can be used freely for any purpose. Any derived versions of this @@ -19,7 +19,6 @@ #include #include -#include #include #ifdef HAVE_NETGROUP_H # include @@ -37,8 +36,6 @@ #include "log.h" #include "misc.h" #include "xmalloc.h" -#include "sshbuf.h" -#include "sshkey.h" #include "servconf.h" #include "canohost.h" #include "hostfile.h" @@ -49,8 +46,9 @@ extern int use_privsep; /* - * This function processes an rhosts-style file (.rhosts, .shosts, or - * /etc/hosts.equiv). This returns true if authentication can be granted + * This function processes an rhosts-style file (.rhosts, .shosts, + * /etc/hosts.equiv or /etc/shosts.equiv). + * This returns true if authentication can be granted * based on the file, and returns zero otherwise. */ @@ -184,19 +182,18 @@ } /* - * Tries to authenticate the user using the .shosts or .rhosts file. Returns - * true if authentication succeeds. If ignore_rhosts is true, only - * /etc/hosts.equiv will be considered (.rhosts and .shosts are ignored). + * Tries to authenticate the user using the hosts.equiv(5) files. Returns + * true if authentication succeeds. Always consider files /etc/hosts.equiv + * and /etc/shosts.equiv. Files .rhosts and .shosts are ignored depending from + * IgnoreRhosts option. */ int auth_rhosts2(struct passwd *pw, const char *client_user, const char *hostname, const char *ipaddr) { - char *path = NULL; struct stat st; static const char * const rhosts_files[] = {".shosts", ".rhosts", NULL}; u_int rhosts_file_index; - int r; debug2_f("clientuser %s hostname %s ipaddr %s", client_user, hostname, ipaddr); @@ -211,13 +208,14 @@ */ for (rhosts_file_index = 0; rhosts_files[rhosts_file_index]; rhosts_file_index++) { + char *path = NULL; + int r; /* Check users .rhosts or .shosts. */ xasprintf(&path, "%s/%s", pw->pw_dir, rhosts_files[rhosts_file_index]); r = stat(path, &st); free(path); - if (r >= 0) - break; + if (r != -1) break; } /* Switch back to privileged uid. */ restore_uid(); @@ -226,7 +224,7 @@ * Deny if The user has no .shosts or .rhosts file and there * are no system-wide files. */ - if (!rhosts_files[rhosts_file_index] && + if (rhosts_files[rhosts_file_index] == NULL && stat(_PATH_RHOSTS_EQUIV, &st) == -1 && stat(_PATH_SSH_HOSTS_EQUIV, &st) == -1) { debug3_f("no hosts access files exist"); @@ -243,13 +241,13 @@ if (check_rhosts_file(_PATH_RHOSTS_EQUIV, hostname, ipaddr, client_user, pw->pw_name)) { auth_debug_add("Accepted for %.100s [%.100s] by " - "/etc/hosts.equiv.", hostname, ipaddr); + "%s.", hostname, ipaddr, _PATH_RHOSTS_EQUIV); return 1; } if (check_rhosts_file(_PATH_SSH_HOSTS_EQUIV, hostname, ipaddr, client_user, pw->pw_name)) { auth_debug_add("Accepted for %.100s [%.100s] by " - "%.100s.", hostname, ipaddr, _PATH_SSH_HOSTS_EQUIV); + "%s.", hostname, ipaddr, _PATH_SSH_HOSTS_EQUIV); return 1; } } @@ -280,11 +278,11 @@ /* Check all .rhosts files (currently .shosts and .rhosts). */ for (rhosts_file_index = 0; rhosts_files[rhosts_file_index]; rhosts_file_index++) { + char *path = NULL; /* Check users .rhosts or .shosts. */ xasprintf(&path, "%s/%s", pw->pw_dir, rhosts_files[rhosts_file_index]); if (stat(path, &st) == -1) { - debug3_f("stat %s: %s", path, strerror(errno)); free(path); continue; } @@ -309,7 +307,7 @@ * and .shosts files. */ if (options.ignore_rhosts == IGNORE_RHOSTS_YES || - (options.ignore_rhosts == IGNORE_RHOSTS_SHOSTS && + (options.ignore_rhosts == IGNORE_RHOSTS_ONLY && strcmp(rhosts_files[rhosts_file_index], ".shosts") != 0)) { auth_debug_add("Server has been configured to " "ignore %.100s.", rhosts_files[rhosts_file_index]); diff -ruN openssh-9.4p1/auth-shadow.c openssh-9.4p1+x509-14.2.1/auth-shadow.c --- openssh-9.4p1/auth-shadow.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/auth-shadow.c 2023-08-20 10:07:01.000000000 +0300 @@ -33,7 +33,6 @@ #include "hostfile.h" #include "auth.h" #include "sshbuf.h" -#include "ssherr.h" #include "log.h" #ifdef DAY @@ -61,7 +60,7 @@ today = time(NULL) / DAY; daysleft = spw->sp_expire - today; - debug3("%s: today %lld sp_expire %lld days left %lld", __func__, + debug3_f("today %lld sp_expire %lld days left %lld", (long long)today, (long long)spw->sp_expire, daysleft); if (spw->sp_expire == -1) { @@ -71,10 +70,10 @@ return 1; } else if (daysleft <= spw->sp_warn) { debug3("account will expire in %lld days", daysleft); - if ((r = sshbuf_putf(loginmsg, + if ((r = sshbuf_putf(loginmsg, "Your account will expire in %lld day%s.\n", daysleft, daysleft == 1 ? "" : "s")) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "buffer error"); } return 0; @@ -90,7 +89,8 @@ struct spwd *spw = NULL; const char *user = ctxt->pw->pw_name; time_t today; - int r, daysleft, disabled = 0; + long long daysleft; + int r, disabled = 0; if ((spw = getspnam((char *)user)) == NULL) { error("Could not get shadow information for %.100s", user); @@ -129,11 +129,11 @@ logit("User %.100s password has expired (password aged)", user); return 1; } else if (daysleft <= spw->sp_warn) { - debug3("password will expire in %d days", daysleft); - if ((r = sshbuf_putf(loginmsg, - "Your password will expire in %d day%s.\n", daysleft, + debug3("password will expire in %lld days", daysleft); + if ((r = sshbuf_putf(loginmsg, + "Your password will expire in %lld day%s.\n", daysleft, daysleft == 1 ? "" : "s")) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "buffer error"); } return 0; diff -ruN openssh-9.4p1/blocks.c openssh-9.4p1+x509-14.2.1/blocks.c --- openssh-9.4p1/blocks.c 1970-01-01 02:00:00.000000000 +0200 +++ openssh-9.4p1+x509-14.2.1/blocks.c 2023-08-20 10:07:01.000000000 +0300 @@ -0,0 +1,251 @@ +/* $OpenBSD: blocks.c,v 1.3 2013/12/09 11:03:45 markus Exp $ */ + +/* + * Public Domain, Author: Daniel J. Bernstein + * Copied from nacl-20110221/crypto_hashblocks/sha512/ref/blocks.c + */ + +#include "includes.h" + +#include "crypto_api.h" + +typedef unsigned long long uint64; + +int crypto_hashblocks_sha512(unsigned char *, const unsigned char *, + unsigned long long); + +static uint64 load_bigendian(const unsigned char *x) +{ + return + (uint64) (x[7]) \ + | (((uint64) (x[6])) << 8) \ + | (((uint64) (x[5])) << 16) \ + | (((uint64) (x[4])) << 24) \ + | (((uint64) (x[3])) << 32) \ + | (((uint64) (x[2])) << 40) \ + | (((uint64) (x[1])) << 48) \ + | (((uint64) (x[0])) << 56) + ; +} + +static void store_bigendian(unsigned char *x,uint64 u) +{ + x[7] = u; u >>= 8; + x[6] = u; u >>= 8; + x[5] = u; u >>= 8; + x[4] = u; u >>= 8; + x[3] = u; u >>= 8; + x[2] = u; u >>= 8; + x[1] = u; u >>= 8; + x[0] = u; +} + +#define SHR(x,c) ((x) >> (c)) +#define ROTR(x,c) (((x) >> (c)) | ((x) << (64 - (c)))) + +#define Ch(x,y,z) ((x & y) ^ (~x & z)) +#define Maj(x,y,z) ((x & y) ^ (x & z) ^ (y & z)) +#define Sigma0(x) (ROTR(x,28) ^ ROTR(x,34) ^ ROTR(x,39)) +#define Sigma1(x) (ROTR(x,14) ^ ROTR(x,18) ^ ROTR(x,41)) +#define sigma0(x) (ROTR(x, 1) ^ ROTR(x, 8) ^ SHR(x,7)) +#define sigma1(x) (ROTR(x,19) ^ ROTR(x,61) ^ SHR(x,6)) + +#define M(w0,w14,w9,w1) w0 = sigma1(w14) + w9 + sigma0(w1) + w0; + +#define EXPAND \ + M(w0 ,w14,w9 ,w1 ) \ + M(w1 ,w15,w10,w2 ) \ + M(w2 ,w0 ,w11,w3 ) \ + M(w3 ,w1 ,w12,w4 ) \ + M(w4 ,w2 ,w13,w5 ) \ + M(w5 ,w3 ,w14,w6 ) \ + M(w6 ,w4 ,w15,w7 ) \ + M(w7 ,w5 ,w0 ,w8 ) \ + M(w8 ,w6 ,w1 ,w9 ) \ + M(w9 ,w7 ,w2 ,w10) \ + M(w10,w8 ,w3 ,w11) \ + M(w11,w9 ,w4 ,w12) \ + M(w12,w10,w5 ,w13) \ + M(w13,w11,w6 ,w14) \ + M(w14,w12,w7 ,w15) \ + M(w15,w13,w8 ,w0 ) + +#define F(w,k) \ + T1 = h + Sigma1(e) + Ch(e,f,g) + k + w; \ + T2 = Sigma0(a) + Maj(a,b,c); \ + h = g; \ + g = f; \ + f = e; \ + e = d + T1; \ + d = c; \ + c = b; \ + b = a; \ + a = T1 + T2; + +int crypto_hashblocks_sha512(unsigned char *statebytes,const unsigned char *in,unsigned long long inlen) +{ + uint64 state[8]; + uint64 a; + uint64 b; + uint64 c; + uint64 d; + uint64 e; + uint64 f; + uint64 g; + uint64 h; + uint64 T1; + uint64 T2; + + a = load_bigendian(statebytes + 0); state[0] = a; + b = load_bigendian(statebytes + 8); state[1] = b; + c = load_bigendian(statebytes + 16); state[2] = c; + d = load_bigendian(statebytes + 24); state[3] = d; + e = load_bigendian(statebytes + 32); state[4] = e; + f = load_bigendian(statebytes + 40); state[5] = f; + g = load_bigendian(statebytes + 48); state[6] = g; + h = load_bigendian(statebytes + 56); state[7] = h; + + while (inlen >= 128) { + uint64 w0 = load_bigendian(in + 0); + uint64 w1 = load_bigendian(in + 8); + uint64 w2 = load_bigendian(in + 16); + uint64 w3 = load_bigendian(in + 24); + uint64 w4 = load_bigendian(in + 32); + uint64 w5 = load_bigendian(in + 40); + uint64 w6 = load_bigendian(in + 48); + uint64 w7 = load_bigendian(in + 56); + uint64 w8 = load_bigendian(in + 64); + uint64 w9 = load_bigendian(in + 72); + uint64 w10 = load_bigendian(in + 80); + uint64 w11 = load_bigendian(in + 88); + uint64 w12 = load_bigendian(in + 96); + uint64 w13 = load_bigendian(in + 104); + uint64 w14 = load_bigendian(in + 112); + uint64 w15 = load_bigendian(in + 120); + + F(w0 ,0x428a2f98d728ae22ULL) + F(w1 ,0x7137449123ef65cdULL) + F(w2 ,0xb5c0fbcfec4d3b2fULL) + F(w3 ,0xe9b5dba58189dbbcULL) + F(w4 ,0x3956c25bf348b538ULL) + F(w5 ,0x59f111f1b605d019ULL) + F(w6 ,0x923f82a4af194f9bULL) + F(w7 ,0xab1c5ed5da6d8118ULL) + F(w8 ,0xd807aa98a3030242ULL) + F(w9 ,0x12835b0145706fbeULL) + F(w10,0x243185be4ee4b28cULL) + F(w11,0x550c7dc3d5ffb4e2ULL) + F(w12,0x72be5d74f27b896fULL) + F(w13,0x80deb1fe3b1696b1ULL) + F(w14,0x9bdc06a725c71235ULL) + F(w15,0xc19bf174cf692694ULL) + + EXPAND + + F(w0 ,0xe49b69c19ef14ad2ULL) + F(w1 ,0xefbe4786384f25e3ULL) + F(w2 ,0x0fc19dc68b8cd5b5ULL) + F(w3 ,0x240ca1cc77ac9c65ULL) + F(w4 ,0x2de92c6f592b0275ULL) + F(w5 ,0x4a7484aa6ea6e483ULL) + F(w6 ,0x5cb0a9dcbd41fbd4ULL) + F(w7 ,0x76f988da831153b5ULL) + F(w8 ,0x983e5152ee66dfabULL) + F(w9 ,0xa831c66d2db43210ULL) + F(w10,0xb00327c898fb213fULL) + F(w11,0xbf597fc7beef0ee4ULL) + F(w12,0xc6e00bf33da88fc2ULL) + F(w13,0xd5a79147930aa725ULL) + F(w14,0x06ca6351e003826fULL) + F(w15,0x142929670a0e6e70ULL) + + EXPAND + + F(w0 ,0x27b70a8546d22ffcULL) + F(w1 ,0x2e1b21385c26c926ULL) + F(w2 ,0x4d2c6dfc5ac42aedULL) + F(w3 ,0x53380d139d95b3dfULL) + F(w4 ,0x650a73548baf63deULL) + F(w5 ,0x766a0abb3c77b2a8ULL) + F(w6 ,0x81c2c92e47edaee6ULL) + F(w7 ,0x92722c851482353bULL) + F(w8 ,0xa2bfe8a14cf10364ULL) + F(w9 ,0xa81a664bbc423001ULL) + F(w10,0xc24b8b70d0f89791ULL) + F(w11,0xc76c51a30654be30ULL) + F(w12,0xd192e819d6ef5218ULL) + F(w13,0xd69906245565a910ULL) + F(w14,0xf40e35855771202aULL) + F(w15,0x106aa07032bbd1b8ULL) + + EXPAND + + F(w0 ,0x19a4c116b8d2d0c8ULL) + F(w1 ,0x1e376c085141ab53ULL) + F(w2 ,0x2748774cdf8eeb99ULL) + F(w3 ,0x34b0bcb5e19b48a8ULL) + F(w4 ,0x391c0cb3c5c95a63ULL) + F(w5 ,0x4ed8aa4ae3418acbULL) + F(w6 ,0x5b9cca4f7763e373ULL) + F(w7 ,0x682e6ff3d6b2b8a3ULL) + F(w8 ,0x748f82ee5defb2fcULL) + F(w9 ,0x78a5636f43172f60ULL) + F(w10,0x84c87814a1f0ab72ULL) + F(w11,0x8cc702081a6439ecULL) + F(w12,0x90befffa23631e28ULL) + F(w13,0xa4506cebde82bde9ULL) + F(w14,0xbef9a3f7b2c67915ULL) + F(w15,0xc67178f2e372532bULL) + + EXPAND + + F(w0 ,0xca273eceea26619cULL) + F(w1 ,0xd186b8c721c0c207ULL) + F(w2 ,0xeada7dd6cde0eb1eULL) + F(w3 ,0xf57d4f7fee6ed178ULL) + F(w4 ,0x06f067aa72176fbaULL) + F(w5 ,0x0a637dc5a2c898a6ULL) + F(w6 ,0x113f9804bef90daeULL) + F(w7 ,0x1b710b35131c471bULL) + F(w8 ,0x28db77f523047d84ULL) + F(w9 ,0x32caab7b40c72493ULL) + F(w10,0x3c9ebe0a15c9bebcULL) + F(w11,0x431d67c49c100d4cULL) + F(w12,0x4cc5d4becb3e42b6ULL) + F(w13,0x597f299cfc657e2aULL) + F(w14,0x5fcb6fab3ad6faecULL) + F(w15,0x6c44198c4a475817ULL) + + a += state[0]; + b += state[1]; + c += state[2]; + d += state[3]; + e += state[4]; + f += state[5]; + g += state[6]; + h += state[7]; + + state[0] = a; + state[1] = b; + state[2] = c; + state[3] = d; + state[4] = e; + state[5] = f; + state[6] = g; + state[7] = h; + + in += 128; + inlen -= 128; + } + + store_bigendian(statebytes + 0,state[0]); + store_bigendian(statebytes + 8,state[1]); + store_bigendian(statebytes + 16,state[2]); + store_bigendian(statebytes + 24,state[3]); + store_bigendian(statebytes + 32,state[4]); + store_bigendian(statebytes + 40,state[5]); + store_bigendian(statebytes + 48,state[6]); + store_bigendian(statebytes + 56,state[7]); + + return inlen; +} diff -ruN openssh-9.4p1/canohost.c openssh-9.4p1+x509-14.2.1/canohost.c --- openssh-9.4p1/canohost.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/canohost.c 2023-08-20 10:07:01.000000000 +0300 @@ -80,10 +80,10 @@ memset(&addr, 0, sizeof(addr)); if (remote) { - if (getpeername(sock, (struct sockaddr *)&addr, &addrlen) != 0) + if (getpeername(sock, (struct sockaddr *)&addr, &addrlen) == -1) return NULL; } else { - if (getsockname(sock, (struct sockaddr *)&addr, &addrlen) != 0) + if (getsockname(sock, (struct sockaddr *)&addr, &addrlen) == -1) return NULL; } @@ -144,7 +144,7 @@ /* Handle the case where we were passed a pipe */ if (gethostname(myname, sizeof(myname)) == -1) { - verbose_f("gethostname: %s", strerror(errno)); + debug_f("gethostname: %s", strerror(errno)); host = xstrdup("UNKNOWN"); } else { host = xstrdup(myname); @@ -165,6 +165,7 @@ if (sock < 0) return -1; + /* Get IP address of client. */ fromlen = sizeof(from); memset(&from, 0, sizeof(from)); diff -ruN openssh-9.4p1/chacha.c openssh-9.4p1+x509-14.2.1/chacha.c --- openssh-9.4p1/chacha.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/chacha.c 2023-08-20 10:07:01.000000000 +0300 @@ -1,4 +1,3 @@ -/* $OpenBSD: chacha.c,v 1.2 2023/07/17 05:26:38 djm Exp $ */ /* chacha-merged.c version 20080118 D. J. Bernstein @@ -9,6 +8,8 @@ #include "chacha.h" +/* $OpenBSD: chacha.c,v 1.1 2013/11/21 00:45:44 djm Exp $ */ + typedef unsigned char u8; typedef unsigned int u32; diff -ruN openssh-9.4p1/ChangeLog openssh-9.4p1+x509-14.2.1/ChangeLog --- openssh-9.4p1/ChangeLog 2023-08-10 04:11:15.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/ChangeLog 1970-01-01 02:00:00.000000000 +0200 @@ -1,10174 +0,0 @@ -commit daa5b2d869ee5a16f3ef9035aa0ad3c70cf4028e -Author: Damien Miller -Date: Thu Aug 10 11:10:22 2023 +1000 - - depend - -commit 41bfb63f5101fbacde9d8d2ada863f9ee16df194 -Author: Damien Miller -Date: Thu Aug 10 11:05:42 2023 +1000 - - update versions in RPM specs - -commit e598b92b1eecedac21667edf1fe92078eaf8f2b1 -Author: Damien Miller -Date: Thu Aug 10 11:05:14 2023 +1000 - - update version in README - -commit e797e5ffa74377c8696e3b0559a258d836479239 -Author: djm@openbsd.org -Date: Thu Aug 10 01:01:07 2023 +0000 - - upstream: openssh-9.4 - - OpenBSD-Commit-ID: 71fc1e01a4c4ea061b252bd399cda7be757e6e35 - -commit 3961ed02dc578517a9d2535128cff5c3a5460d28 -Author: Damien Miller -Date: Thu Aug 10 09:08:49 2023 +1000 - - wrap poll.h include in HAVE_POLL_H - -commit e535fbe2af893046c28adfcd787c1fdbae36a24a -Author: dtucker@openbsd.org -Date: Fri Aug 4 06:32:40 2023 +0000 - - upstream: Apply ConnectTimeout to multiplexing local socket - - connections. If the multiplex socket exists but the connection times out, - ssh will fall back to a direct connection the same way it would if the socket - did not exist at all. ok djm@ - - OpenBSD-Commit-ID: 2fbe1a36d4a24b98531b2d298a6557c8285dc1b4 - -commit 9d92e7b24848fcc605945f7c2e3460c7c31832ce -Author: Darren Tucker -Date: Thu Aug 3 19:35:33 2023 +1000 - - Fix RNG seeding for OpenSSL w/out self seeding. - - When sshd is built with an OpenSSL that does not self-seed, it would - fail in the preauth privsep process while handling a new connection. - Sanity checked by djm@ - -commit f70010d9b0b3e7e95de8aa0b961e1d74362cfb5d -Author: djm@openbsd.org -Date: Wed Aug 2 23:04:38 2023 +0000 - - upstream: CheckHostIP has defaulted to 'no' for a while; make the - - commented- out config option match. From Ed Maste - - OpenBSD-Commit-ID: e66e934c45a9077cb1d51fc4f8d3df4505db58d9 - -commit c88a8788f9865d02b986d00405b9f0be65ad0b5a -Author: dtucker@openbsd.org -Date: Tue Aug 1 08:15:04 2023 +0000 - - upstream: remove unnecessary if statement. - - github PR#422 from eyalasulin999, ok djm@ - - OpenBSD-Commit-ID: 2b6b0dde4407e039f58f86c8d2ff584a8205ea55 - -commit 77b8b865cd5a8c79a47605c0c5b2bacf4692c4d5 -Author: jmc@openbsd.org -Date: Fri Jul 28 05:42:36 2023 +0000 - - upstream: %C is a callable macro in mdoc(7) - - so, as we do for %D, escape it; - - OpenBSD-Commit-ID: 538cfcddbbb59dc3a8739604319491dcb8e0c0c9 - -commit e0f91aa9c2fbfc951e9ced7e1305455fc614d3f2 -Author: djm@openbsd.org -Date: Fri Jul 28 05:33:15 2023 +0000 - - upstream: don't need to start a command here; use ssh -N instead. - - Fixes failure on cygwin spotted by Darren - - OpenBSD-Regress-ID: ff678a8cc69160a3b862733d935ec4a383f93cfb - -commit f446a44f30bc680e0d026a4204844b02646c1c2d -Author: djm@openbsd.org -Date: Wed May 17 05:52:01 2023 +0000 - - upstream: add LTESTS_FROM variable to allow skipping of tests up to - - a specific point. e.g. "make LTESTS_FROM=t-sftp" will only run the sftp.sh - test and subsequent ones. ok dtucker@ - - OpenBSD-Regress-ID: 07f653de731def074b29293db946042706fcead3 - -commit 8eb8899d612440a9b608bee7f916081d3d0b7812 -Author: djm@openbsd.org -Date: Fri May 12 06:37:42 2023 +0000 - - upstream: test ChrootDirectory in Match block - - OpenBSD-Regress-ID: a6150262f39065939f025e546af2a346ffe674c1 - -commit e43f43d3f19516222e9a143468ea0dc1b3ab67b6 -Author: djm@openbsd.org -Date: Fri May 12 06:36:27 2023 +0000 - - upstream: better error messages - - OpenBSD-Regress-ID: 55e4186604e80259496d841e690ea2090981bc7a - -commit 6958f00acf3b9e0b3730f7287e69996bcf3ceda4 -Author: djm@openbsd.org -Date: Thu Jul 27 22:26:49 2023 +0000 - - upstream: don't incorrectly truncate logged strings retrieved from - - PKCS#11 modules; based on GHPR406 by Jakub Jelen; ok markus - - OpenBSD-Commit-ID: 7ed1082f23a13b38c373008f856fd301d50012f9 - -commit d1ffde6b55170cd4b9a72bfd9a3f17508e6cf714 -Author: djm@openbsd.org -Date: Thu Jul 27 22:25:17 2023 +0000 - - upstream: make sshd_config AuthorizedPrincipalsCommand and - - AuthorizedKeysCommand accept the %D (routing domain) and a new %C (connection - address/port 4-tuple) as expansion sequences; ok markus - - OpenBSD-Commit-ID: ee9a48bf1a74c4ace71b69de69cfdaa2a7388565 - -commit 999a2886ca1844a7a74b905e5f2c8c701f9838cd -Author: djm@openbsd.org -Date: Thu Jul 27 22:23:05 2023 +0000 - - upstream: increase default KDF work-factor for OpenSSH format - - private keys from 16 to 24; { feedback ok } x { deraadt markus } - - OpenBSD-Commit-ID: a3afb1383f8ff0a49613d449f02395d9e8d4a9ec - -commit 0fa803a1dd1c7b546c166000e23a869cf6c4ec10 -Author: Darren Tucker -Date: Thu Jul 27 02:25:09 2023 +1000 - - Prefer OpenSSL's SHA256 in sk-dummy.so - - Previously sk-dummy.so used libc's (or compat's) SHA256 since it may be - built without OpenSSL. In many cases, however, including both libc's - and OpenSSL's headers together caused conflicting definitions. - - We tried working around this (on OpenSSL <1.1 you could define - OPENSSL_NO_SHA, NetBSD had USE_LIBC_SHA2, various #define hacks) with - varying levels of success. Since OpenSSL >=1.1 removed OPENSSL_NO_SHA - and including most OpenSSL headers would bring sha.h in, even if it - wasn't used directly this was a constant hassle. - - Admit defeat and use OpenSSL's SHA256 unless we aren't using OpenSSL at - all. ok djm@ - -commit 36cdb5dbf55c99c0faad06066f56a7c341258c1f -Author: Darren Tucker -Date: Thu Jul 27 10:29:44 2023 +1000 - - Retire dfly58 test VM. Add dfly64. - -commit 2d34205dab08ede9b0676efa57647fc49e6decbe -Author: djm@openbsd.org -Date: Wed Jul 26 23:06:00 2023 +0000 - - upstream: make ssh -f (fork after authentication) work properly in - - multiplexed cases (inc. ControlPersist). bz3589 bz3589 Based on patches by - Peter Chubb; ok dtucker@ - - OpenBSD-Commit-ID: a7a2976a54b93e6767dc846b85647e6ec26969ac - -commit 076aeda86a7ee9be8fd2f0181ec7b9729a6ceb37 -Author: naddy@openbsd.org -Date: Sun Jul 23 20:04:45 2023 +0000 - - upstream: man page typos; ok jmc@ - - OpenBSD-Commit-ID: e6ddfef94b0eb867ad88abe07cedc8ed581c07f0 - -commit 135e7d5fe31f700e6dfc61ce914970c5ee7175ba -Author: jmc@openbsd.org -Date: Thu Jul 20 05:43:39 2023 +0000 - - upstream: tweak the allow-remote-pkcs11 text; - - OpenBSD-Commit-ID: bc965460a89edf76865b7279b45cf9cbdebd558a - -commit 5f83342b61d1f76c141de608ed2bd293990416bd -Author: Darren Tucker -Date: Tue Jul 25 13:00:22 2023 +1000 - - Handle a couple more OpenSSL no-ecc cases. - - ok djm@ - -commit edc2ef4e418e514c99701451fae4428ec04ce538 -Author: Damien Miller -Date: Thu Jul 20 12:53:44 2023 +1000 - - depend - -commit 51fda734e0d3c2df256fc03e8b060c4305be6e59 -Author: Damien Miller -Date: Thu Jul 20 12:53:21 2023 +1000 - - Bring back OPENSSL_HAS_ECC to ssh-pkcs11-client - -commit 099cdf59ce1e72f55d421c8445bf6321b3004755 -Author: djm@openbsd.org -Date: Wed Jul 19 14:03:45 2023 +0000 - - upstream: Separate ssh-pkcs11-helpers for each p11 module - - Make ssh-pkcs11-client start an independent helper for each provider, - providing better isolation between modules and reliability if a single - module misbehaves. - - This also implements reference counting of PKCS#11-hosted keys, - allowing ssh-pkcs11-helper subprocesses to be automatically reaped - when no remaining keys reference them. This fixes some bugs we have - that make PKCS11 keys unusable after they have been deleted, e.g. - https://bugzilla.mindrot.org/show_bug.cgi?id=3125 - - ok markus@ - - OpenBSD-Commit-ID: 0ce188b14fe271ab0568f4500070d96c5657244e - -commit 29ef8a04866ca14688d5b7fed7b8b9deab851f77 -Author: djm@openbsd.org -Date: Wed Jul 19 14:02:27 2023 +0000 - - upstream: Ensure FIDO/PKCS11 libraries contain expected symbols - - This checks via nlist(3) that candidate provider libraries contain one - of the symbols that we will require prior to dlopen(), which can cause - a number of side effects, including execution of constructors. - - Feedback deraadt; ok markus - - OpenBSD-Commit-ID: 1508a5fbd74e329e69a55b56c453c292029aefbe - -commit 1f2731f5d7a8f8a8385c6031667ed29072c0d92a -Author: djm@openbsd.org -Date: Wed Jul 19 13:56:33 2023 +0000 - - upstream: Disallow remote addition of FIDO/PKCS11 provider - - libraries to ssh-agent by default. - - The old behaviour of allowing remote clients from loading providers - can be restored using `ssh-agent -O allow-remote-pkcs11`. - - Detection of local/remote clients requires a ssh(1) that supports - the `session-bind@openssh.com` extension. Forwarding access to a - ssh-agent socket using non-OpenSSH tools may circumvent this control. - - ok markus@ - - OpenBSD-Commit-ID: 4c2bdf79b214ae7e60cc8c39a45501344fa7bd7c - -commit 892506b13654301f69f9545f48213fc210e5c5cc -Author: djm@openbsd.org -Date: Wed Jul 19 13:55:53 2023 +0000 - - upstream: terminate process if requested to load a PKCS#11 provider - - that isn't a PKCS#11 provider; from / ok markus@ - - OpenBSD-Commit-ID: 39532cf18b115881bb4cfaee32084497aadfa05c - -commit f3f56df8ec476b2de6cbdbdfdb77a2a61087829d -Author: Damien Miller -Date: Wed Jul 19 12:07:18 2023 +1000 - - agent_fuzz doesn't want stdint.h conditionalised - -commit 750911fd31d307a767cc86e3bfa90bbbb77b1a25 -Author: Damien Miller -Date: Tue Jul 18 15:41:12 2023 +1000 - - conditionalise stdint.h inclusion on HAVE_STDINT_H - - fixes build on AIX5 at least - -commit ff047504fa6e008c4092f8929881816b8993bea0 -Author: Damien Miller -Date: Tue Jul 18 15:30:45 2023 +1000 - - conditionalise match localnetwork on ifaddrs.h - - Fixes build breakage on platforms that lack getifaddrs() - -commit b87b03282e466ca2927954ce93f5dbf0bfdc68f6 -Author: djm@openbsd.org -Date: Mon Jul 17 06:16:33 2023 +0000 - - upstream: missing match localnetwork negation check - - OpenBSD-Commit-ID: 9a08ed8dae27d3f38cf280f1b28d4e0ff41a737a - -commit 6d6e185ba29ef4274164b77eab4dc763907f8821 -Author: jmc@openbsd.org -Date: Mon Jul 17 05:41:53 2023 +0000 - - upstream: - add -P to usage() - sync the arg name to -J in usage() - - with that in ssh.1 - reformat usage() to match what "man ssh" does on 80width - - OpenBSD-Commit-ID: 5235dd7aa42e5bf90ae54579d519f92fc107036e - -commit f1a9898283a0638667b587ee4a950afd61ab51b0 -Author: jmc@openbsd.org -Date: Mon Jul 17 05:38:10 2023 +0000 - - upstream: -P before -p in SYNOPSIS; - - OpenBSD-Commit-ID: 535f5257c779e26c6a662a038d241b017f8cab7c - -commit eef4d7e873568e1c84c36bb4034e2c3378250a61 -Author: jsg@openbsd.org -Date: Mon Jul 17 05:36:14 2023 +0000 - - upstream: configuation -> configuration - - OpenBSD-Commit-ID: 4776ced33b780f1db0b2902faec99312f26a726b - -commit dc1dbe94cf6532bd546a3373ad436404f8850e5f -Author: djm@openbsd.org -Date: Mon Jul 17 05:26:38 2023 +0000 - - upstream: move other RCSIDs to before their respective license blocks - - too no code change - - OpenBSD-Commit-ID: ef5bf46b57726e4260a63b032b0b5ac3b4fe9cd4 - -commit ebe11044681caff78834ca6b78311ad19c1860b8 -Author: djm@openbsd.org -Date: Mon Jul 17 05:22:30 2023 +0000 - - upstream: Move RCSID to before license block and away from #includes, - - where it caused merge conflict in -portable for each commit :( - - OpenBSD-Commit-ID: 756ebac963df3245258b962e88150ebab9d5fc20 - -commit 05c08e5f628de3ecf6f7ea20947735bcfa3201e0 -Author: djm@openbsd.org -Date: Mon Jul 17 05:20:15 2023 +0000 - - upstream: return SSH_ERR_KRL_BAD_MAGIC when a KRL doesn't contain a - - valid magic number and not SSH_ERR_MESSAGE_INCOMPLETE; the former is needed - to fall back to text revocation lists in some cases; fixes t-cert-hostkey. - - OpenBSD-Commit-ID: 5c670a6c0f027e99b7774ef29f18ba088549c7e1 - -commit c6fad2c3d19b74f0bd0af1ef040fc74f3a1d9ebb -Author: Damien Miller -Date: Mon Jul 17 14:56:14 2023 +1000 - - avoid AF_LINK on platforms that don't define it - -commit 919bc3d3b712c920de1ae6be5ac6561c98886d7e -Author: djm@openbsd.org -Date: Mon Jul 17 04:08:31 2023 +0000 - - upstream: Add support for configuration tags to ssh(1). - - This adds a ssh_config(5) "Tag" directive and corresponding - "Match tag" predicate that may be used to select blocks of - configuration similar to the pf.conf(5) keywords of the same - name. - - ok markus - - OpenBSD-Commit-ID: dc08358e70e702b59ac3e591827e5a96141b06a3 - -commit 3071d85a47061c1bdaf11a0ac233b501ecba862c -Author: djm@openbsd.org -Date: Mon Jul 17 04:04:36 2023 +0000 - - upstream: add a "match localnetwork" predicate. - - This allows matching on the addresses of available network interfaces - and may be used to vary the effective client configuration based on - network location (e.g. to use a ProxyJump when not on a particular - network). - - ok markus@ - - OpenBSD-Commit-ID: cffb6ff9a3803abfc52b5cad0aa190c5e424c139 - -commit beec17bb311365b75a0a5941418d4b96df7d7888 -Author: djm@openbsd.org -Date: Mon Jul 17 04:01:10 2023 +0000 - - upstream: remove vestigal support for KRL signatures - - When the KRL format was originally defined, it included support for - signing of KRL objects. However, the code to sign KRLs and verify KRL - signatues was never completed in OpenSSH. - - Now, some years later, we have SSHSIG support in ssh-keygen that is - more general, well tested and actually works. So this removes the - semi-finished KRL signing/verification support from OpenSSH and - refactors the remaining code to realise the benefit - primarily, we - no longer need to perform multiple parsing passes over KRL objects. - - ok markus@ - - OpenBSD-Commit-ID: 517437bab3d8180f695c775410c052340e038804 - -commit 449566f64c21b4578d5c0c431badd0328adc53ed -Author: djm@openbsd.org -Date: Mon Jul 17 03:57:21 2023 +0000 - - upstream: Support for KRL extensions. - - This defines wire formats for optional KRL extensions and implements - parsing of the new submessages. No actual extensions are supported at - this point. - - ok markus - - OpenBSD-Commit-ID: ae2fcde9a22a9ba7f765bd4f36b3f5901d8c3fa7 - -commit 18ea857770e84825a3a6238bb37f54864487b59f -Author: dtucker@openbsd.org -Date: Fri Jul 14 07:44:21 2023 +0000 - - upstream: Include stdint.h for SIZE_MAX. Fixes OPENSSL=no build. - - OpenBSD-Commit-ID: e7c31034a5434f2ead3579b13a7892960651e6b0 - -commit 20b768fcd13effe0f2d3619661b6c8592c773553 -Author: Darren Tucker -Date: Fri Jul 14 17:07:32 2023 +1000 - - Fix typo in declaration of nmesg. - -commit 4b94d09542e36ebde2eb9ad89bc68431609932de -Author: Damien Miller -Date: Fri Jul 14 15:34:47 2023 +1000 - - portable-specific int overflow defence-in-depth - - These too are unreachable, but we want the code to be safe regardless of - context. Reported by Yair Mizrahi @ JFrog - -commit 2ee48adb9fc8692e8d6ac679dcc9f35e89ad68f0 -Author: djm@openbsd.org -Date: Fri Jul 14 05:31:44 2023 +0000 - - upstream: add defence-in-depth checks for some unreachable integer - - overflows reported by Yair Mizrahi @ JFrog; feedback/ok millert@ - - OpenBSD-Commit-ID: 52af085f4e7ef9f9d8423d8c1840a6a88bda90bd - -commit 4b43bc358ae6f6b19a973679246dc5172f6ac41b -Author: djm@openbsd.org -Date: Mon Jul 10 04:51:26 2023 +0000 - - upstream: misplaced debug message - - OpenBSD-Commit-ID: d0f12af0a5067a756aa707bc39a83fa6f58bf7e5 - -commit 8c7203bcee4c4f98a22487b4631fe068b992099b -Author: Damien Miller -Date: Wed Jul 12 11:41:19 2023 +1000 - - replace deprecate selinux matchpathcon function - - This function is apparently deprecated. Documentation on what is the - supposed replacement is is non-existent, so this follows the approach - glibc used https://sourceware.org/git/?p=glibc.git;a=patch;h=f278835f59 - - ok dtucker@ - -commit 7e8800f5d701efffa39ccb63ca1e095ea777c31a -Author: dtucker@openbsd.org -Date: Thu Jul 6 22:17:59 2023 +0000 - - upstream: minleft and maxsign are u_int so cast appropriately. Prompted - - by github PR#410, ok deraadt. - - OpenBSD-Commit-ID: 0514cd51db3ec60239966622a0d3495b15406ddd - -commit 94842bfe9b09fc93189c6ed0dc9bbebc1d44a426 -Author: dlg@openbsd.org -Date: Tue Jul 4 03:59:21 2023 +0000 - - upstream: add support for unix domain sockets to ssh -W - - ok djm@ dtucker@ - - OpenBSD-Commit-ID: 3e6d47567b895c7c28855c7bd614e106c987a6d8 - -commit a95fc5eed09a0238fb127b6c50e8498432b79dae -Author: David Seifert -Date: Fri May 12 14:06:01 2023 +0200 - - gss-serv.c: `MAXHOSTNAMELEN` -> `HOST_NAME_MAX` - - `MAXHOSTNAMELEN` is not defined in POSIX, which breaks on musl: - https://pubs.opengroup.org/onlinepubs/9699919799/functions/gethostname.html - - Bug: https://bugs.gentoo.org/834044 - -commit 8a6cd08850f576e7527c52a1b086cae82fab290e -Author: Darren Tucker -Date: Fri Jun 23 09:49:02 2023 +1000 - - Update runner OS version for hardenedmalloc test. - - Hardenedmalloc dropped support for "legacy glibc" versions in their - 64dad0a69 so use a newer Ubuntu version for the runner for that test. - -commit cfca6f17e64baed6822bb927ed9f372ce64d9c5b -Author: Damien Miller -Date: Thu Jun 22 15:04:03 2023 +1000 - - handle sysconf(SC_OPEN_MAX) returning > INT_MAX; - - bz3581; ok dtucker - -commit c1c2ca1365b3f7b626683690bd2c68265f6d8ffd -Author: djm@openbsd.org -Date: Wed Jun 21 05:10:26 2023 +0000 - - upstream: better validate CASignatureAlgorithms in ssh_config and - - sshd_config. - - Previously this directive would accept certificate algorithm names, but - these were unusable in practice as OpenSSH does not support CA chains. - - part of bz3577; ok dtucker@ - - OpenBSD-Commit-ID: a992d410c8a78ec982701bc3f91043dbdb359912 - -commit 4e73cd0f4ab3e5b576c56cac9732da62c8fc0565 -Author: djm@openbsd.org -Date: Wed Jun 21 05:08:32 2023 +0000 - - upstream: make `ssh -Q CASignatureAlgorithms` only list signature - - algorithms that are valid for CA signing. Previous behaviour was to list all - signing algorithms, including certificate algorithms (OpenSSH certificates do - not support CA chains). part of bz3577; ok dtucker@ - - OpenBSD-Commit-ID: 99c2b072dbac0f44fd1f2269e3ff6c1b5d7d3e59 - -commit a69062f1695ac9c3c3dea29d3044c72aaa6af0ea -Author: djm@openbsd.org -Date: Wed Jun 21 05:06:04 2023 +0000 - - upstream: handle rlimits > INT_MAX (rlim_t is u64); ok dtucker - - bz3581 - - OpenBSD-Commit-ID: 31cf59c041becc0e5ccb0a77106f812c4cd1cd74 - -commit 8d33f2aa6bb895a7f85a47189913639086347b75 -Author: djm@openbsd.org -Date: Tue Jun 20 23:59:33 2023 +0000 - - upstream: prepare for support for connecting to unix domain sockets - - using ssh -W by explicitly decoding PORT_STREAMLOCAL (a negative number) from - the u32 that's passed over the multiplexing socket; previously code would - just cast, which is UB. - - OpenBSD-Commit-ID: e5ac5f40d354096c51e8c118a5c1b2d2b7a31384 - -commit b4ac435b4e67f8eb5932d8f59eb5b3cf7dc38df0 -Author: djm@openbsd.org -Date: Tue Jun 20 00:05:09 2023 +0000 - - upstream: reset comment=NULL for each key in do_fingerprint(); - - fixes "no comment" not showing on when running `ssh-keygen -l` on multiple - keys where one has a comment and other following keys do not. Patch from - Markus Kuhn via GHPR407, bz3580 - - OpenBSD-Commit-ID: 3cce84456fdcd67dc6b84e369f92c6686d111d9b - -commit b53a809a549dcd4fbde554c6aa283e597b15ea33 -Author: millert@openbsd.org -Date: Mon Jun 5 13:24:36 2023 +0000 - - upstream: Store timeouts as int, not u_int as they are limited to - - INT_MAX. Fixes sign compare warnings systems with 32-bit time_t due to type - promotion. OK djm@ - - OpenBSD-Commit-ID: 48081e9ad35705c5f1705711704a4c2ff94e87b7 - -commit 2709809fd616a0991dc18e3a58dea10fb383c3f0 -Author: Philip Hands -Date: Wed May 24 19:41:14 2023 +0200 - - fixup! if -s & -p specified, mention 'sftp -P' on - - success - - SSH-Copy-ID-Upstream: 32686e7c65b4fa2846e474d3315102dfa0f043b0 - -commit 204e0bf05161b7641500d7ab266c21217412379f -Author: Darren Tucker -Date: Tue Aug 3 21:25:48 2021 +1000 - - Make ssh-copy-id(1) consistent with OpenSSH. - - This makes the ssh-copy-id man page more consistent with the rest of the - OpenSSH man pages: - - new sentence, new line - - no sentences >80 - - N.B. -> NB - - zap unused .Pp - - zap trailing whitespace - - Report from Debian via mindrot bz#3331, diff from jmc at openbsd.org. - - SSH-Copy-ID-Upstream: d8974cfb6242316460ed22a1ccc662800a50c5d3 - -commit 9de79df66d1430d290fab670bb4b18612875e518 -Author: Philip Hands -Date: Wed May 24 11:45:43 2023 +0200 - - if -s & -p specified, mention 'sftp -P' on success - - This was inspired by this: - https://github.com/openssh/openssh-portable/pull/321 - but I thought that it was better to not do the sed patching. - - BTW the reason one can get away with using $SSH_OPTS throughout, despite - the lowercase -p in there, even if sftp is in use, is that the sftp call - is using the already-established ssh master connection, so the port was - passed to the earlier ssh. - - SSH-Copy-ID-Upstream: 1c124d9bfafdbe28a00b683367ebf5750ce12eb2 - -commit 801cda54c00e0f4e7d89345a90874c8d05dc233a -Author: Philip Hands -Date: Tue May 23 23:07:11 2023 +0200 - - drop whitespace - - SSH-Copy-ID-Upstream: e604fae1cdee35c18055d35dcec530cf12ef00ad - -commit 288482f53613f3e74544eb92deeb24f7c7f1f371 -Author: Philip Hands -Date: Tue May 23 20:52:13 2023 +0200 - - make -x also apply to the target script - - SSH-Copy-ID-Upstream: 3c4214704f427bd0654adf9b0fc079253db21cf4 - -commit b79e7b88ed44f0e4339f0ff35c96c78a92175a8d -Author: Philip Hands -Date: Tue May 23 16:46:42 2023 +0200 - - add -t option to specify the target path - - Allow the default target path (.ssh/authorized_files) to be over-riden - - This was inspired by this MR from Panagiotis Cheilaris - - https://gitlab.com/phil_hands/ssh-copy-id/-/merge_requests/8 - - SSH-Copy-ID-Upstream: a942a0e076874adb6d8b2f0fb76d6c7918190fcd - -commit 914f4ad138714c471ba72fb6d5496b6235320edd -Author: Carlos Rodríguez Gili -Date: Tue Apr 20 19:23:57 2021 +0200 - - Fix test error for /bin/sh on Solaris 10 and older - - On Solaris 10 and older targets /bin/sh is not POSIX-compliant. - Test -z `...` fails with error 'sh: test: argument expected'. - Using quotes around backticks fixes this and doesn't break - POSIX compatibility. - - SSH-Copy-ID-Upstream: 98394072a3f985b2650c1e8eab2fef84e38cc065 - -commit bd382dca316c721aed1e45edcf4c4e0f6374afb0 -Author: Jakub Jelen -Date: Tue Mar 2 21:34:05 2021 +0000 - - Remove outdated comment - - The commit b068122 removed the code dropping the trailing colon, but the comment stayed leaving the code confusing for future readers - - SSH-Copy-ID-Upstream: 930d39f238117cd53810240ec989d0356aa1c1f6 - -commit bdcaf7939029433635d63aade8f9ac762aca2bbe -Author: Darren Tucker -Date: Wed May 10 18:50:46 2023 +1000 - - Special case OpenWrt instead of Dropbear. - - OpenWrt overrides the location of authorized_keys for root. Currently we - assume that all Dropbear installations behave this way, which is not the - case. Check for OpenWrt and root user before using that location instead - of assuming that for all Dropbear servers. Prompted by Github PR#250. - - SSH-Copy-ID-Upstream: 0e1f5d443a9967483c33945793107ae3f3e4af2d - -commit cf84498f67abe93f813a296167b406a0db7b288e -Author: Philip Hands -Date: Thu May 18 18:20:55 2023 +0200 - - ssh-copy-id: add -x option (for debugging) - - This option causes the ssh-copy-id to run with set -x - - SSH-Copy-ID-Upstream: a0ee367ea8c0a29c8b4515245e408d2d349e7844 - -commit b4a1efdcb88f03394c08e7f68ed4e11676830002 -Author: Philip Hands -Date: Thu May 18 17:14:41 2023 +0200 - - update copyright notices - - SSH-Copy-ID-Upstream: c284ed33b361814ea48ff68cbd01ca525b2bf117 - -commit fcd78e31cdd45a7e69ccfe6d8a3b1037dc1de290 -Author: djm@openbsd.org -Date: Wed May 24 23:01:06 2023 +0000 - - upstream: fix AuthorizedPrincipalsCommand when AuthorizedKeysCommand - - appears previously in configuration. Reported by John Meyers in bz3574 ok - dtucker@ - - OpenBSD-Commit-ID: 1c92e4517284386703936e1d3abaa36cfacf1951 - -commit 5ec5504f1d328d5bfa64280cd617c3efec4f78f3 -Author: dtucker@openbsd.org -Date: Wed May 10 10:04:20 2023 +0000 - - upstream: Remove unused prototypes for ssh1 RSA functions. - - From lengyijun via github PR#396. - - OpenBSD-Commit-ID: 379a5afa8b7a0f3cba0c8a9bcceb4e5e33a5c1ef - -commit fbf362b3891ae4b36052d1b39f37fc618b41c476 -Author: Darren Tucker -Date: Tue May 9 19:26:56 2023 +1000 - - main(void) to prevent unused variable warning. - -commit baf854c8bb0a6d0af5c696c801e631a48dabbaba -Author: Darren Tucker -Date: Tue May 9 19:25:45 2023 +1000 - - Remove warning pragma since clang doesn't like it. - -commit 5fbb7a1349fbbb48ccb1b8cafff2c1854370d87d -Author: Darren Tucker -Date: Tue May 9 17:13:33 2023 +1000 - - Suppress warning for snprintf truncation test. - -commit 47742c513e4e045ecc985c6483fc5c8b050acda2 -Author: Darren Tucker -Date: Tue May 9 17:12:50 2023 +1000 - - Update OpenSSL compat test for 3.x. - -commit 86ad25d455a2313126125540e61e0f9314283f88 -Author: Darren Tucker -Date: Mon May 8 20:23:08 2023 +1000 - - Add macos13 PAM test target. - -commit 77cca2c4b13bc6e5f389565583b6202b0d1bccc2 -Author: Darren Tucker -Date: Mon May 8 20:14:46 2023 +1000 - - Skip agent-peereid test on macos13. - - sudo -S nobody doesn't work on the github runners (probably a - permission issue) so skip that test. - -commit b356b8e91678ea295bcf44df5248c3fbf499fdcf -Author: Darren Tucker -Date: Mon May 8 20:14:28 2023 +1000 - - Include config.guess in debug output. - -commit b7afd8a4ecaca8afd3179b55e9db79c0ff210237 -Author: Darren Tucker -Date: Mon May 8 20:12:59 2023 +1000 - - Handle OpenSSL >=3 ABI compatibility. - - Beyond OpenSSL 3.0, the ABI compatibility guarantees are wider (only - major must match instead of major and minor in earlier versions). - bz#3548, ok djm@ - -commit 0e9e2663eb2c6e9c3e10d15d70418312ae67e542 -Author: dtucker@openbsd.org -Date: Mon May 1 08:57:29 2023 +0000 - - upstream: Import regenerated moduli. - - OpenBSD-Commit-ID: 3d5f811cfcaed8cc4a97e1db49ac61bdf118113c - -commit d9687f49682e1e93383fc15ab2018850b2ef38c3 -Author: Darren Tucker -Date: Mon May 1 11:45:14 2023 +1000 - - Add macos-13 test target. - - Also flatten OS list for clarity. - -commit aacfd6767497b8fa6d41ecdd3f8e265d1e9ef1f6 -Author: djm@openbsd.org -Date: Sun Apr 30 22:54:22 2023 +0000 - - upstream: adjust ftruncate() logic to handle servers that reorder - - requests. - - sftp/scp will ftruncate the destination file after a transfer completes, - to deal with the case where a longer destination file already existed. - We tracked the highest contiguous block transferred to deal with this - case, but our naive tracking doesn't deal with servers that reorder - requests - a misfeature strictly permitted by the protocol but seldom - implemented. - - Adjust the logic to ftruncate() at the highest absolute block received - when the transfer is successful. feedback deraadt@ ok markus@ - - prompted by https://github.com/openssh/openssh-portable/commit/9b733#commitcomment-110679778 - - OpenBSD-Commit-ID: 4af7fac75958ad8507b4fea58706f3ff0cfddb1b - -commit c8eb3941758615c8284a48fff47872db926da63c -Author: djm@openbsd.org -Date: Wed Apr 26 01:36:03 2023 +0000 - - upstream: Check for ProxyJump=none in CanonicalizeHostname logic. - - Previously ssh would incorrectly refuse to canonicalise the hostname - if ProxyJump was explicitly set to "none" when CanonicalizeHostname=yes - - bz3567; ok dtucker - - OpenBSD-Commit-ID: 80a58e43c3a32f97361282f756ec8d3f37989efd - -commit ac383f3a5c6f529a2e8a5bc44af79a08c7da294e -Author: jsg@openbsd.org -Date: Wed Apr 12 14:22:04 2023 +0000 - - upstream: remove duplicate signal.h include - - OpenBSD-Commit-ID: 30c0a34d74d91ddd0e6992525da70d3293392f70 - -commit 740dafa20f3f3d325f6f5d44e990b8c8a6d3d816 -Author: jsg@openbsd.org -Date: Wed Apr 12 08:53:54 2023 +0000 - - upstream: fix double words ok dtucker@ - - OpenBSD-Commit-ID: 44d3223902fbce5276422bdc8063ab72a4078489 - -commit 6452f89577ec4f22440c31b8e19b061d1a7c4b2a -Author: Darren Tucker -Date: Tue Apr 11 16:49:19 2023 +1000 - - Test against LibreSSL 3.7.2. - -commit 2138f6be595ca106fe4805a1e3ab9c4d8acc697b -Author: Damien Miller -Date: Thu Apr 6 14:33:10 2023 +1000 - - remove unused upper-case const strings in fmtfp - - no float format that uses upper-case is supported nor are hex floats. - ok dtucker - -commit 484c5e6168fdb22cbcd73c4ff987cf9ca47989ca -Author: djm@openbsd.org -Date: Thu Apr 6 03:56:02 2023 +0000 - - upstream: simplify sshsig_find_principals() similar to what happened to - - sshsig_check_allowed_keys() in r1.31, removing some dead code - - OpenBSD-Commit-ID: a493e628d4d6c08f878c276d998f4313ba61702d - -commit 3a7b110fbc7e096423f8f7b459deffe4c65d70f4 -Author: djm@openbsd.org -Date: Thu Apr 6 03:21:31 2023 +0000 - - upstream: remove redundant ssh!=NULL check; we'd already - - dereferenced it - - OpenBSD-Commit-ID: 852bf12591ec5a9fb12dcbde9b1fd3945ad0df3c - -commit 2519110659a1efac6c976895a86659d1b341c91b -Author: djm@openbsd.org -Date: Thu Apr 6 03:19:32 2023 +0000 - - upstream: match_user() shouldn't be called with user==NULL unless - - host and ipaddr are also NULL - - OpenBSD-Commit-ID: fa3518346c21483e9e01a2e4b9436ae501daf8ea - -commit 3b9ceaad7ad63c1c03c2a89e148340ad3a62a482 -Author: djm@openbsd.org -Date: Thu Apr 6 03:12:32 2023 +0000 - - upstream: don't care about glob() return value here. - - OpenBSD-Commit-ID: 85bb82fea90478a482e9f65a1bec0aa24227fd66 - -commit 09d8da0849e2791b2500267cda333cd238f38754 -Author: dtucker@openbsd.org -Date: Mon Apr 3 08:10:54 2023 +0000 - - upstream: Move up null check and simplify process_escapes. - - Based on Coverity CID 291863 which points out we check the channel - pointer for NULLness after dereferencing it. Move this to the start - of the function, and while there simplify initialization of efc a bit. - ok djm@ - - OpenBSD-Commit-ID: de36e5ad6fde0fe263ca134e986b9095dc59380a - -commit b36b162be5e6206f12b734222b7bc517c13a6bc8 -Author: Damien Miller -Date: Fri Mar 31 14:51:20 2023 +1100 - - need va_end() after va_copy(); ok dtucker - - spotted by Coverity - -commit f703757234a5c585553e72bba279b255a272750a -Author: dtucker@openbsd.org -Date: Fri Mar 31 05:56:36 2023 +0000 - - upstream: Explicitly ignore return from waitpid here too. - - OpenBSD-Commit-ID: eef2403df083c61028969fc679ee370373eacacb - -commit 6b73aa29035991d1448a1a76f63ac152a6bf931c -Author: dtucker@openbsd.org -Date: Fri Mar 31 04:45:08 2023 +0000 - - upstream: Explictly ignore return codes - - where we don't check them. - - OpenBSD-Commit-ID: 1ffb03038ba1b6b72667be50cf5e5e396b5f2740 - -commit 6f0308a3e717ebe68eeb3f95253612fab5dbf20e -Author: dtucker@openbsd.org -Date: Fri Mar 31 04:42:29 2023 +0000 - - upstream: Return immediately from get_sock_port - - if sock <0 so we don't call getsockname on a negative FD. From Coverity - CID 291840, ok djm@ - - OpenBSD-Commit-ID: de1c1130646230c2eda559831fc6bfd1b61d9618 - -commit 1c1124dc901fca1ea2cb762044b8f1a5793a2bed -Author: djm@openbsd.org -Date: Fri Mar 31 04:23:02 2023 +0000 - - upstream: don't leak arg2 on parse_pubkey_algos error path; ok - - dtucker@ - - OpenBSD-Commit-ID: 7d0270ad3dd102412ca76add2b3760518abdef75 - -commit 8ba2d4764bb6a4701cd447d8b52604622ffe65f4 -Author: djm@openbsd.org -Date: Fri Mar 31 04:22:27 2023 +0000 - - upstream: clamp max number of GSSAPI mechanisms to 2048; ok dtucker - - OpenBSD-Commit-ID: ce66db603a913d3dd57063e330cb5494d70722c4 - -commit 1883841fc13d0eada8743cac5d3abe142ee2efa7 -Author: djm@openbsd.org -Date: Fri Mar 31 04:21:56 2023 +0000 - - upstream: don't print key if printing hostname failed; with/ok - - dtucker@ - - OpenBSD-Commit-ID: ad42971a6ee5a46feab2d79f7f656f8cf4b119f3 - -commit c6011129cafe4c411f6ef670a4cf271314708eb8 -Author: djm@openbsd.org -Date: Fri Mar 31 04:04:15 2023 +0000 - - upstream: remove redundant test - - OpenBSD-Commit-ID: 6a0b719f9b1ae9d42ad8c5b144c7962c93792f7c - -commit 4fb29eeafb40a2076c0dbe54e46b687c318f87aa -Author: djm@openbsd.org -Date: Fri Mar 31 04:00:37 2023 +0000 - - upstream: don't attempt to decode a ridiculous number of - - attributes; harmless because of bounds elsewhere, but better to be explicit - - OpenBSD-Commit-ID: 1a34f4b6896155b80327d15dc7ccf294b538a9f2 - -commit fc437c154ef724621a4af236de9bc7e51a8381ae -Author: djm@openbsd.org -Date: Fri Mar 31 03:22:49 2023 +0000 - - upstream: remove unused variable; prompted by Coverity CID 291879 - - OpenBSD-Commit-ID: 4c7d20ef776887b0ba1aabcfc1b14690e4ad0a40 - -commit 0eb8131e4a53b33a8fc9b9ab694e6b6778b87ade -Author: dtucker@openbsd.org -Date: Fri Mar 31 00:44:29 2023 +0000 - - upstream: Check fd against >=0 instead of >0 in error path. The - - dup could in theory return fd 0 although currently it doesn't in practice. - From Dmitry Belyavskiy vi github PR#238. - - OpenBSD-Commit-ID: 4a95f3f7330394dffee5c749d52713cbf3b54846 - -commit 7174ba6f8a431ca4257767a260fc50e204068242 -Author: dtucker@openbsd.org -Date: Thu Mar 30 07:19:50 2023 +0000 - - upstream: Ignore return value from muxclient(). It normally loops - - without returning, but it if returns on failure we immediately exit. - Coverity CID 405050. - - OpenBSD-Commit-ID: ab3fde6da384ea588226037c38635a6b2e015295 - -commit a4c1c2513e36f111eeaa1322c510067930e5e51e -Author: Damien Miller -Date: Fri Mar 31 14:17:22 2023 +1100 - - don't call connect() on negative socket - - Coverity CID 405037 - -commit 34ee842cdd981a759fe8f0d4a37521f9a1c63170 -Author: djm@openbsd.org -Date: Thu Mar 30 03:05:01 2023 +0000 - - upstream: return SSH_ERR_KEY_NOT_FOUND if the allowed_signers file - - is empty, not SSH_ERR_INTERNAL_ERROR. Also remove some dead code spotted - by Coverity; with/ok dtucker@ - - OpenBSD-Commit-ID: 898a1e817cda9869554b1f586a434f67bcc3b650 - -commit f108e77a9dc9852e72215af1bf27731c48434557 -Author: dtucker@openbsd.org -Date: Thu Mar 30 00:49:37 2023 +0000 - - upstream: Remove dead code from inside if block. - - The only way the if statement can be true is if both dup()s fail, and - in that case the tmp2 can never be set. Coverity CID 291805, ok djm@ - - OpenBSD-Commit-ID: c0d6089b3fb725015462040cd94e23237449f0c8 - -commit 05b8e88ebe23db690abbfb1a91111abea09cde08 -Author: Darren Tucker -Date: Thu Mar 30 13:53:29 2023 +1100 - - child_set_eng: verify both env pointer and count. - - If child_set env was called with a NULL env pointer and a non-zero count - it would end up in a null deref, although we don't currently do this. - Prompted by Coverity CID 291850, tweak & ok djm@ - -commit 28f1b8ef9b84b8cd2f6c9889a0c60aa4a90dadfa -Author: dtucker@openbsd.org -Date: Wed Mar 29 01:07:48 2023 +0000 - - upstream: Ignore return from sshpkt_disconnect - - since we set our own return value for the function. Coverity CID 291797, - ok djm@ - - OpenBSD-Commit-ID: 710b57ba954c139240895e23feea41f203201f04 - -commit c3da05d95922f5550bcc7815e799474d6a160175 -Author: dtucker@openbsd.org -Date: Wed Mar 29 00:59:08 2023 +0000 - - upstream: Plug potential mem leak in process_put. - - It allocates abs_dst inside a loop but only frees it on exit, so free - inside the loop if necessary. Coverity CID 291837, ok djm@ - - OpenBSD-Commit-ID: a01616503a185519b16f00dde25d34ceaf4ae1a3 - -commit 13ae327eae598b1043e5ec30e4b170edb3c898a5 -Author: djm@openbsd.org -Date: Wed Mar 29 00:18:35 2023 +0000 - - upstream: fix memory leak; Coverity CID 291848 - - with/ok dtucker@ - - OpenBSD-Commit-ID: 37f80cb5d075ead5a00ad1b74175684ab1156ff8 - -commit 9ffa76e1284c85bf459c3dcb8e995733a8967e1b -Author: dtucker@openbsd.org -Date: Tue Mar 28 07:44:32 2023 +0000 - - upstream: Plug more mem leaks in sftp by making - - make_absolute_pwd_glob work in the same way as make_absolute: you - pass it a dynamically allocated string and it either returns it, or - frees it and allocates a new one. Patch from emaste at freebsd.org and - https://reviews.freebsd.org/D37253 ok djm@ - - OpenBSD-Commit-ID: 85f7404e9d47fd28b222fbc412678f3361d2dffc - -commit 82b2b8326962b1a98af279bc5bbbbbcab15b3e45 -Author: dtucker@openbsd.org -Date: Tue Mar 28 06:12:38 2023 +0000 - - upstream: Remove compat code for OpenSSL < 1.1.* - - since -portable no longer supports them. - - OpenBSD-Commit-ID: ea2893783331947cd29a67612b4e56f818f185ff - -commit b500afcf00ae1b6b73b2ccf171111dfbfeaef74d -Author: dtucker@openbsd.org -Date: Mon Mar 27 23:56:54 2023 +0000 - - upstream: Remove compat code for OpenSSL 1.0.* - - versions now that -portable has dropped support for those versions. - - OpenBSD-Regress-ID: 82a8eacd87aec28e4aa19f17246ddde9d5ce7fe7 - -commit 727560e6011efcb36d2f3ac6910444bc775abaa1 -Author: Darren Tucker -Date: Tue Mar 28 18:06:42 2023 +1100 - - Prevent conflicts between Solaris SHA2 and OpenSSL. - - We used to prevent conflicts between native SHA2 headers and OpenSSL's - by setting OPENSSL_NO_SHA but that was removed prior to OpenSSL 1.1.0 - -commit 46db8e14b7f186d32173dcdecd5b785334429b8b -Author: Darren Tucker -Date: Tue Mar 28 12:44:03 2023 +1100 - - Remove HEADER_SHA_H from previous... - - since it causes more problems than it solves. - -commit 72bd68d37387aa5f81da928f6e82f1c88ed8f674 -Author: Darren Tucker -Date: Tue Mar 28 10:35:18 2023 +1100 - - Replace OPENSSL_NO_SHA with HEADER_SHA_H. - - Since this test doesn't use OpenSSL's SHA2 and may cause conflicts we - don't want to include it, but OPENSSL_NO_SHA was removed beginning in - OpenSSL's 1.1 series. - -commit 99668f2e6e0deb833e46cfab56db59ff0fc28c7e -Author: Darren Tucker -Date: Tue Mar 28 09:50:06 2023 +1100 - - Configure with --target instead of deprecated form. - -commit f751d9306c62cd1061f966e6a7483d9bab9c379b -Author: Darren Tucker -Date: Mon Mar 27 22:05:29 2023 +1100 - - Pass rpath when building 64bit Solaris. - -commit a64b935cd450ee8d04c26c9cd728629cf9ca5c91 -Author: Darren Tucker -Date: Mon Mar 27 19:21:19 2023 +1100 - - Explicitly disable OpenSSL on AIX test VM. - -commit 7ebc6f060fc2f70495a56e16d210baae6424cd96 -Author: dtucker@openbsd.org -Date: Mon Mar 27 03:56:50 2023 +0000 - - upstream: Add RevokedHostKeys to percent expansion test. - - OpenBSD-Regress-ID: c077fd12a38005dd53d878c5b944154dec88d2ff - -commit f1a17de150f8d309d0c52f9abfaebf11c51a8537 -Author: dtucker@openbsd.org -Date: Mon Mar 27 03:56:11 2023 +0000 - - upstream: Add tilde and environment variable expansion to - - RevokedHostKeys. bz#3552, ok djm@ - - OpenBSD-Commit-ID: ce5d8e0219b63cded594c17d4c2958c06918ec0d - -commit 009eb4cb48a9708ab9174684dcbcc0f942907abe -Author: djm@openbsd.org -Date: Mon Mar 27 03:31:05 2023 +0000 - - upstream: fix test: getnameinfo returns a non-zero value on error, not - - (neccessarily) -1. From GHPR#384 - - OpenBSD-Commit-ID: d35e2b71268f66f5543a7ea68751972b3ae22b25 - -commit 4f0a676486700f10a4788f7e9426e94e39c1c89e -Author: djm@openbsd.org -Date: Mon Mar 27 03:25:08 2023 +0000 - - upstream: scp: when copying local->remote, check that source file - - exists before opening SFTP connection to the server. Based on GHPR#370 ok - dtucker, markus - - OpenBSD-Commit-ID: b4dd68e15bfe22ce4fac9960a1066a2b721e54fb - -commit 154d8baf631327163571760c2c524bc93c37567c -Author: Darren Tucker -Date: Mon Mar 27 12:22:30 2023 +1100 - - Also look for gdb error message from OpenIndiana. - -commit fbd3811ddb2b6ce2e6dba91fde7352c8978e5412 -Author: Darren Tucker -Date: Mon Mar 27 11:08:00 2023 +1100 - - Explicitly disable security key test on aix51 VM. - - We don't know how to build the shared objects required for the security - key tests so skip them. - -commit 4922ac3be8a996780ef3dc220411da2e27c29d9c -Author: Darren Tucker -Date: Sun Mar 26 14:49:43 2023 +1100 - - Split libcrypto and other config flags. - - This should allow the automatic OpenSSL version selection in the tests - to work better. - -commit 4a948b1469f185e871160a2d70e2a0fce2858f9e -Author: Darren Tucker -Date: Sun Mar 26 14:39:45 2023 +1100 - - Specify test target if we build without OpenSSL. - - When we decide we can't use the versions of OpenSSL available, also - restrict the tests we run to avoid the ones that need OpenSSL. - -commit b308c636f5b5d89eecb98be00b3d56306a005a09 -Author: Darren Tucker -Date: Sun Mar 26 14:22:53 2023 +1100 - - Find suitable OpenSSL version. - - Check the installed OpenSSL versions for a suitable one, and if there - isn't (and we don't have a specific version configured) then build - without OpenSSL. - -commit 021ea5c2860f133f44790970968e0e73208b3a87 -Author: Damien Miller -Date: Fri Mar 24 15:02:52 2023 +1100 - - Github testing support for BoringSSL - -commit 9a97cd106466a2a9bda2bfaa4c48c4f1b2cc9c1b -Author: Damien Miller -Date: Fri Mar 24 15:34:29 2023 +1100 - - BoringSSL doesn't support EC_POINT_point2bn() - - so don't invoke it in unittest - -commit cc5969c033a032d126ff78e5d95cf20abbede4c7 -Author: Damien Miller -Date: Fri Mar 24 15:34:05 2023 +1100 - - another ERR_load_CRYPTO_strings() vestige - -commit 4974293899a068133e976f81d6693670d2b576ca -Author: Damien Miller -Date: Fri Mar 24 15:24:05 2023 +1100 - - don't use obsolete ERR_load_CRYPTO_strings() - - OpenSSL (and elsewhere in OpenSSH) uses ERR_load_crypto_strings() - -commit 3c527d55f906e6970d17c4cab6db90ae9e013235 -Author: Damien Miller -Date: Fri Mar 24 15:23:05 2023 +1100 - - Allow building with BoringSSL - -commit b7e27cfd7f163fc16b4c5d041cc28ee488a5eeec -Author: Damien Miller -Date: Fri Mar 24 15:21:18 2023 +1100 - - put back SSLeay_version compat in configure test - - Needed to detect old versions and give good "your version is bad" - messages at configure time; spotted by dtucker@ - -commit 7280401bdd77ca54be6867a154cc01e0d72612e0 -Author: Damien Miller -Date: Fri Mar 24 13:56:25 2023 +1100 - - remove support for old libcrypto - - OpenSSH now requires LibreSSL 3.1.0 or greater or - OpenSSL 1.1.1 or greater - - with/ok dtucker@ - -commit abda22fb48302f2142233f71d27c74040288c518 -Author: Darren Tucker -Date: Sun Mar 19 15:36:13 2023 +1100 - - Test latest OpenSSL 1.1, 3.0 and LibreSSL 3.7. - -commit 610ac1cb077cd5a1ebfc21612154bfa13d2ec825 -Author: Darren Tucker -Date: Thu Mar 16 21:38:04 2023 +1100 - - Show 9.3 branch instead of 9.2. - -commit cb30fbdbee869f1ce11f06aa97e1cb8717a0b645 -Author: Damien Miller -Date: Thu Mar 16 08:28:19 2023 +1100 - - depend - -commit 1dba63eb10c40b6fda9f5012ed6ae87e2d3d028e -Author: Damien Miller -Date: Thu Mar 16 08:27:54 2023 +1100 - - crank version - -commit ba7532d0dac9aaf0ad7270664c43837fc9f64a5f -Author: djm@openbsd.org -Date: Wed Mar 15 21:19:57 2023 +0000 - - upstream: openssh-9.3 - - OpenBSD-Commit-ID: 8011495f2449c1029bb316bd015eab2e00509848 - -commit 6fd4daafb949b66bf555f3100f715a9ec64c3390 -Author: dtucker@openbsd.org -Date: Tue Mar 14 07:28:47 2023 +0000 - - upstream: Free KRL ptr in addition to its contents. - - From Coverity CID 291841, ok djm@ - - OpenBSD-Commit-ID: f146ba08b1b43af4e0d7ad8c4dae3748b4fa31b6 - -commit 1d270bd303afaf6d94e9098cbbf18e5e539e2088 -Author: dtucker@openbsd.org -Date: Tue Mar 14 07:26:25 2023 +0000 - - upstream: Check pointer for NULL before deref. - - None of the existing callers seem to do that, but it's worth checking. - From Coverity CID 291834, ok djm@ - - OpenBSD-Commit-ID: a0a97113f192a7cb1a2c97b932f677f573cda7a4 - -commit d95af508e78c0cd3dce56b83853baaa59ae295cf -Author: dtucker@openbsd.org -Date: Sun Mar 12 10:40:39 2023 +0000 - - upstream: Limit number of entries in SSH2_MSG_EXT_INFO - - request. This is already constrained by the maximum SSH packet size but this - makes it explicit. Prompted by Coverity CID 291868, ok djm@ markus@ - - OpenBSD-Commit-ID: aea023819aa44a2dcb9dd0fbec10561896fc3a09 - -commit 8f287ba60d342b3e2f750e7332d2131e3ec7ecd0 -Author: dtucker@openbsd.org -Date: Sun Mar 12 09:41:18 2023 +0000 - - upstream: calloc can return NULL but xcalloc can't. - - From Coverity CID 291881, ok djm@ - - OpenBSD-Commit-ID: 50204b755f66b2ec7ac3cfe379d07d85ca161d2b - -commit 83a56a49fd50f4acf900f934279482e4ef329715 -Author: dtucker@openbsd.org -Date: Fri Mar 10 07:17:08 2023 +0000 - - upstream: Explicitly ignore return from fcntl - - (... FD_CLOEXEC) here too. Coverity CID 291853. - - OpenBSD-Commit-ID: 99d8b3da9d0be1d07ca8dd8e98800a890349e9b5 - -commit 0fda9d704d3bbf54a5e64ce02a6fecb11fe7f047 -Author: Damien Miller -Date: Fri Mar 10 15:59:46 2023 +1100 - - bounds checking for getrrsetbyname() replacement; - - Spotted by Coverity in CID 405033; ok millert@ - -commit 89b8df518f21677045599df0ad3e5dd0f39909b5 -Author: dtucker@openbsd.org -Date: Fri Mar 10 04:06:21 2023 +0000 - - upstream: Plug mem leak on error path. Coverity CID 405026, ok djm@. - - OpenBSD-Commit-ID: 8212ca05d01966fb5e72205c592b2257708a2aac - -commit bf4dae0ad192c3e2f03f7223834b00d88ace3d3e -Author: Darren Tucker -Date: Fri Mar 10 14:46:57 2023 +1100 - - Add prototypes for mkstemp replacements. - - Should prevent warnings due to our wrapper function. - -commit 4e04d68d6a33cdc73b831fd4b5e6124175555d3d -Author: dtucker@openbsd.org -Date: Fri Mar 10 03:01:51 2023 +0000 - - upstream: Expliticly ignore return code from fcntl(.. FD_CLOEXEC) since - - there's not much we can do anyway. From Coverity CID 291857, ok djm@ - - OpenBSD-Commit-ID: 051429dd07af8db3fec10d82cdc78d90bb051729 - -commit d6d38fd77cbe091c59e1bb720c3a494df4990640 -Author: djm@openbsd.org -Date: Fri Mar 10 02:32:04 2023 +0000 - - upstream: Like sshd_config, some ssh_config options are not - - first-match-wins. sshd_config.5 was fixed in r1.348, this is the same for - this file - - OpenBSD-Commit-ID: 7be55b9351cde449b136afcc52d07aa4113b215e - -commit 7187d3f86bf8f2066cc9941f217d23b0cacae25e -Author: dtucker@openbsd.org -Date: Fri Mar 10 02:24:56 2023 +0000 - - upstream: Remove no-op (int) > INT_MAX checks - - since they can never be true. From Coverity CID 405031, ok djm@ - - OpenBSD-Commit-ID: 9df3783b181e056595e2bb9edf7ed41d61cf8e84 - -commit 77adde4305542ebe3005dd456122624fe2347b01 -Author: Darren Tucker -Date: Fri Mar 10 13:27:29 2023 +1100 - - Wrap mkstemp calls with umask set/restore. - - glibc versions 2.06 and earlier did not set a umask on files created by - mkstemp created the world-writable. Wrap mkstemp to set and restore - the umask. From Coverity (CIDs 291826 291886 291891), ok djm@ - -commit 633d3dc2a1e9e2a013d019a0576a0771c8423713 -Author: jcs@openbsd.org -Date: Thu Mar 9 21:06:24 2023 +0000 - - upstream: modify parentheses in conditionals to make it clearer what is - - being assigned and what is being checked - - ok djm dtucker - - OpenBSD-Commit-ID: 19c10baa46ae559474409f75a5cb3d0eade7a9b8 - -commit 733030840c4772f858de95d5940ec0c37663e8b0 -Author: dtucker@openbsd.org -Date: Thu Mar 9 07:11:05 2023 +0000 - - upstream: Re-split the merge of the reorder-hostkeys test. - - In the kex_proposal_populate_entries change I merged the the check for - reordering hostkeys with the actual reordering, but kex_assemble_names - mutates options.hostkeyalgorithms which renders the check ineffective. - Put the check back where it was. Spotted and tested by jsg@, ok djm@ - - OpenBSD-Commit-ID: a7469f25a738db5567395d1881e32479a7ffc9de - -commit 54ac4ab2b53ce9fcb66b8250dee91c070e4167ed -Author: djm@openbsd.org -Date: Thu Mar 9 06:58:26 2023 +0000 - - upstream: include destination constraints for smartcard keys too. - - Spotted by Luci Stanescu; ok deraadt@ markus@ - - OpenBSD-Commit-ID: add879fac6903a1cb1d1e42c4309e5359c3d870f - -commit bfd1ad01d974a316b60622759ad17537fa2d92b4 -Author: Darren Tucker -Date: Thu Mar 9 18:24:54 2023 +1100 - - Limit the number of PAM environment variables. - - xcalloc has its own limits, but these are specific to PAM. From - Coverity CID 405198, ok djm@ - -commit a231414970e01a35f45a295d5f93698fa1249b28 -Author: Darren Tucker -Date: Thu Mar 9 18:19:44 2023 +1100 - - Limit the number of PAM environment variables. - - From Coverity CID 405194, tweaks and ok djm@ - -commit 36c6c3eff5e4a669ff414b9daf85f919666e8e03 -Author: dtucker@openbsd.org -Date: Wed Mar 8 06:21:32 2023 +0000 - - upstream: Plug mem leak. Coverity CID 405196, ok djm@ - - OpenBSD-Commit-ID: 175f09349387c292f626da68f65f334faaa085f2 - -commit dfb9b736e1ccf9e6b03eea21cd961f4fd0634c98 -Author: tb@openbsd.org -Date: Wed Mar 8 05:33:53 2023 +0000 - - upstream: ssh-pkcs11: synchronize error messages with errors - - A handful of error messages contained incorrect function names or - otherwise inaccurate descriptions. Fix them to match reality. - - input/ok djm - - OpenBSD-Commit-ID: 165a15db52f75b31e1804b043480c36af09f3411 - -commit 51875897b81b5c21b80c256a29597916edbde454 -Author: guenther@openbsd.org -Date: Wed Mar 8 04:43:12 2023 +0000 - - upstream: Delete obsolete /* ARGSUSED */ lint comments. - - ok miod@ millert@ - - OpenBSD-Commit-ID: 7be168a570264d59e96a7d2d22e927d45fee0e4c - -commit a76085bda883c2104afb33ab0334eca190927362 -Author: Darren Tucker -Date: Wed Mar 8 17:25:37 2023 +1100 - - Extra brackets to prevent warning. - -commit 147ae57d4dfa0508109f93b78a7d8b92819e1f83 -Author: djm@openbsd.org -Date: Wed Mar 8 00:05:58 2023 +0000 - - upstream: use RSA/SHA256 when testing usability of private key in - - agent; with/ok dtucker - - OpenBSD-Commit-ID: fe1382e2fdf23fcae631308e72342bad56066a56 - -commit 27fd251bc906a763e70ce0f27c8abdf8bbd1e416 -Author: djm@openbsd.org -Date: Wed Mar 8 00:05:37 2023 +0000 - - upstream: use RSA/SHA256 when testing usability of private key; - - based on fix in bz3546 by Dmitry Belyavskiy; with/ok dtucker - - OpenBSD-Commit-ID: 0ef414cc363a832f9fab92a5da0234448bce2eba - -commit eee9f3fc3d52ae7d2106929bb06b7f291fb0b81a -Author: djm@openbsd.org -Date: Tue Mar 7 21:47:42 2023 +0000 - - upstream: refactor to be more readable top to bottom. Prompted by - - Coverity CID 405048 which was a false-positive fd leak; ok dtucker@ - - OpenBSD-Commit-ID: fc55ec2af622a017defb9b768bf26faefc792c00 - -commit 42a06b29a4c99272bf690f9b3be520b08b448dc5 -Author: Darren Tucker -Date: Tue Mar 7 18:34:41 2023 +1100 - - Add header changes missed in previous. - -commit 4710077096edff2e6926dd5b15bf586491d317db -Author: dtucker@openbsd.org -Date: Tue Mar 7 06:09:14 2023 +0000 - - upstream: Fix mem leak in environment setup. - - From jjelen at redhat.com via bz#2687, ok djm@ - - OpenBSD-Commit-ID: 9f9e4ba3cac003e6f81da3bcebd1b9ec43e7f353 - -commit 03acc50d0ccb78fc91d1570de1cd0fdfea646028 -Author: dtucker@openbsd.org -Date: Mon Mar 6 12:15:47 2023 +0000 - - upstream: Unit test for kex_proposal_populate_entries. - - OpenBSD-Regress-ID: bdb211d80d572a08bf14b49fe2a58b9ff265c006 - -commit 3f9231c2e1f374ebb08016ba00ea97b47c0ed20b -Author: djm@openbsd.org -Date: Tue Mar 7 05:37:26 2023 +0000 - - upstream: fix memory leak in process_read() path; Spotted by James - - Robinson in GHPR363; ok markus@ - - OpenBSD-Commit-ID: cdc2d98e6478b7e7f3a36976845adae3820429d8 - -commit c5e6e890839ec520ab9301a92cba56303749dea2 -Author: djm@openbsd.org -Date: Tue Mar 7 01:30:52 2023 +0000 - - upstream: correct size for array argument when changing - - UMAC_OUTPUT_LEN Coverity CID 291845; ok dtucker@ - - OpenBSD-Commit-ID: 2eb017d10705bb623d4418691f961c930eafaec0 - -commit 9641753e0fd146204d57b2a4165f552a81afade4 -Author: dtucker@openbsd.org -Date: Mon Mar 6 12:14:48 2023 +0000 - - upstream: Refactor creation of KEX proposal. - - This adds kex_proposal_populate_entries (and corresponding free) which - populates the KEX proposal array with dynamically allocated strings. - This replaces the previous mix of static and dynamic that has been the - source of previous leaks and bugs. Remove unused compat functions. - With & ok djm@. - - OpenBSD-Commit-ID: f2f99da4aae2233cb18bf9c749320c5e040a9c7b - -commit aa59d6a489fb20973fa461d0fdb1110db412947b -Author: dtucker@openbsd.org -Date: Sun Mar 5 09:24:35 2023 +0000 - - upstream: Fix mem and FILE leaks in moduli screening. - - If multiple -Ocheckpoint= options are passed, the earlier ones would - be overwritten and leaked. If we use an input file that wasn't stdin, - close that. From Coverity CIDs 291884 and 291894. - - OpenBSD-Commit-ID: a4d9d15f572926f841788912e2b282485ad09e8b - -commit 23b8cb41767af99a1aac24589d1882d9c8c2c205 -Author: dtucker@openbsd.org -Date: Sun Mar 5 08:18:58 2023 +0000 - - upstream: Plug mem leak in moduli checkpoint option parsing. - - From Coverity CID 291894. - - OpenBSD-Commit-ID: 9b1aba2d049741ae21c8dc4560a7e29ab17310f4 - -commit fc7f8f2188d4a4fc8ba77eddbe863c7665666db5 -Author: dtucker@openbsd.org -Date: Sun Mar 5 05:34:09 2023 +0000 - - upstream: Remove unused compat.h includes. - - We've previously removed a lot of the really old compatibility code, - and with it went the need to include compat.h in most of the files that - have it. - - OpenBSD-Commit-ID: 5af8baa194be00a3092d17598e88a5b29f7ea2b4 - -commit 6c165c36246d8004c20e1df5cec4961a5ac422d6 -Author: dtucker@openbsd.org -Date: Sat Mar 4 03:22:59 2023 +0000 - - upstream: Use time_t for x11 timeout. - - Use time_t instead of u_int for remaining x11 timeout checks for 64bit - time_t safety. From Coverity CIDs 405197 and 405028, ok djm@ - - OpenBSD-Commit-ID: 356685bfa1fc3d81bd95722d3fc47101cc1a4972 - -commit 4a3918f51bd2d968387e7aa87e33b32c78077fb4 -Author: dtucker@openbsd.org -Date: Fri Mar 3 10:23:42 2023 +0000 - - upstream: Ensure ms_remain is always initialized - - similar to what we do in ssh_packet_write_wait. bz#2687, from jjelen - at redhat.com. - - OpenBSD-Commit-ID: a50e0541cf823f8d1c72f71ccde925d3dbe6dfac - -commit e44846a4487d2885ac7f2610be09b1e2bf52249b -Author: dtucker@openbsd.org -Date: Fri Mar 3 09:48:51 2023 +0000 - - upstream: Check for non-NULL before string - - comparison. From jjelen at redhat.com via bz#2687. - - OpenBSD-Commit-ID: 0d9b2e0cac88a311b5766b1aef737082583c285f - -commit 1842d523fae63b862ce8e60725c9b606cddb86a6 -Author: djm@openbsd.org -Date: Fri Mar 3 05:00:34 2023 +0000 - - upstream: guard against getsockname(-1, ...) from Coverity CID - - 291832 - - OpenBSD-Commit-ID: e58d5227327917d189229b7f0b37d2780f360d5f - -commit 78571a5fe9847d40d7f220c92b707574ae9ec4ce -Author: djm@openbsd.org -Date: Fri Mar 3 04:36:20 2023 +0000 - - upstream: some options are not first-match-wins. Mention that there - - are exceptions at the start of the manpage and label some of them in the - option description. - - OpenBSD-Commit-ID: 3b74728446fa6fc8742769eeb8c3674e233e84c4 - -commit d1c1b3272e8895a96c4f5889bd6e07a8525bd9f1 -Author: djm@openbsd.org -Date: Fri Mar 3 04:34:49 2023 +0000 - - upstream: actually print "channeltimeout none" in config dump mode; - - spotted via Coverity CID 405022 - - OpenBSD-Commit-ID: b074b52bf138b75f08264e8da15880b29c7a630f - -commit 8bf61e95610b48192d4e1720cc15d9004617301d -Author: Darren Tucker -Date: Fri Mar 3 14:50:03 2023 +1100 - - Add Coverity badges. - -commit 93291bd723959adf462b1df958106cf07a7734dd -Author: dtucker@openbsd.org -Date: Fri Mar 3 03:12:24 2023 +0000 - - upstream: Check return values of dup2. Spotted by Coverity, ok djm@ - - OpenBSD-Commit-ID: 19fb1b53072826d00c67df677731d2f6c1dd602b - -commit e37261dff33af23f37202cfce0848d36f5c1055c -Author: dtucker@openbsd.org -Date: Fri Mar 3 02:37:58 2023 +0000 - - upstream: Use time_t for x11_refuse_time timeout. We need - - SSH_TIME_T_MAX for this, so move from misc.c to misc.h so it's available. - Fixes a Coverity warning for 64bit time_t safety, ok djm@ - - OpenBSD-Commit-ID: c69c4c3152cdaab953706db4ccf4d5fd682f7d8d - -commit 32755a98c29114b13f4c9d47454bbb265b932ad7 -Author: dtucker@openbsd.org -Date: Fri Mar 3 02:34:29 2023 +0000 - - upstream: Check return value from fctnl and warn on failure. - - Spotted by Coverity, ok djm@ - - OpenBSD-Commit-ID: 2097c7db3cf657f1e3a6c5077041bacc63143cab - -commit 5fc60e8246c36b8255f72a937ebe9787b39648c6 -Author: dtucker@openbsd.org -Date: Thu Mar 2 11:10:27 2023 +0000 - - upstream: Remove SUDO in proxy command wrapper. Anything that needs - - sudo is already run by it, and it breaks if root isn't in sudoers. - - OpenBSD-Regress-ID: 6cf22fda32a89c16915f31a6ed9bbdbef2a3bac9 - -commit 0d514659b23a257247491179cfbb53a6dd64e164 -Author: dtucker@openbsd.org -Date: Thu Mar 2 08:24:41 2023 +0000 - - upstream: Fix breakage on dhgex test. - - This was due to the sshd logs being written to the wrong log file. - While there, make save_debug_logs less verbose, write the name of the - tarball to regress.log and use $SUDO to remove the old symlinks (which - shouldn't be needed, but won't hurt). Initial problem spotted by anton@. - - OpenBSD-Regress-ID: 9c44fb9cd418e6ff31165e7a6c1f9f11a6d19f5b - -commit 860201201d4ae655702807966901682cff30a171 -Author: dtucker@openbsd.org -Date: Thu Mar 2 08:14:52 2023 +0000 - - upstream: Quote grep and log message better. - - OpenBSD-Regress-ID: 3823d9063127169736aa274b1784cb28e15b64d4 - -commit 03a03c6002525f5ad9c8fc874a5d5826a35d9858 -Author: dtucker@openbsd.org -Date: Thu Mar 2 06:41:56 2023 +0000 - - upstream: Always call fclose on checkpoints. - - In the case of an fprintf failure we would not call fclose which would - leak the FILE pointer. While we're there, try to clean up the temp file - on failure. Spotted by Coverity, ok djm@ - - OpenBSD-Commit-ID: 73c7ccc5d4fcc235f54c6b20767a2815408525ef - -commit 13fe8f9785e6d90400ce548939a0b0ddc11fcb3c -Author: dtucker@openbsd.org -Date: Wed Mar 1 21:54:50 2023 +0000 - - upstream: Remove old log symlinks - - before creating new ones. In -portable some platforms don't like - overwriting existing symlinks. - - OpenBSD-Regress-ID: 7e7ddc0beb73e945e1c4c58d51c8a125b518120f - -commit 131fcbcaffd1e3bcf5ab766ec497b5d768955310 -Author: Darren Tucker -Date: Wed Mar 1 23:23:02 2023 +1100 - - Adjust test jobs for new log directory. - -commit a6f4ac8a2baf77e5361cfa017d0dc250d1409bec -Author: dtucker@openbsd.org -Date: Wed Mar 1 09:29:32 2023 +0000 - - upstream: Rework logging for the regression tests. - - Previously we would log to ssh.log and sshd.log, but that is insufficient - for tests that have more than one concurent ssh/sshd. - - Instead, we'll log to separate datestamped files in a $OBJ/log/ and - leave a symlink at the previous location pointing at the most recent - instance with an entry in regress.log showing which files were created - at each point. This should be sufficient to reconstruct what happened - even for tests that use multiple instances of each program. If the test - fails, tar up all of the logs for later analysis. - - This will let us also capture the output from some of the other tools - which was previously sent to /dev/null although most of those will be - in future commits. - - OpenBSD-Regress-ID: f802aa9e7fa51d1a01225c05fb0412d015c33e24 - -commit 8ead62ed5e86c7df597d8604f332f49cd1527b85 -Author: dtucker@openbsd.org -Date: Tue Feb 28 21:31:50 2023 +0000 - - upstream: fatal out if allocating banner string fails to avoid - - potential null deref later in sscanf. Spotted by Coverity, ok deraadt@ - - OpenBSD-Commit-ID: 74e8d228ac00552e96e9e968dfcccf8dd1f46ad5 - -commit 44ca56ba0b3f531f1d85730cc701097cd49e6868 -Author: dtucker@openbsd.org -Date: Tue Feb 28 08:45:24 2023 +0000 - - upstream: Explicitly ignore return from fchmod - - similar to other calls to prevent warning. - - OpenBSD-Commit-ID: fdc5287dcee0860b5a493186414226c655b0eb0a - -commit 803392933a3a6f09f834aa5f0c2aab06a3b382f4 -Author: dtucker@openbsd.org -Date: Mon Feb 27 22:12:40 2023 +0000 - - upstream: Plug mem leak on globbed ls error path. - - Spotted by Coverity, ok deraadt@ - - OpenBSD-Commit-ID: de28476025db29820a9a2e56e98b964d8a02861c - -commit aa33b4d396abf47a2a45f982f28d054fb1dcb5c3 -Author: Darren Tucker -Date: Mon Feb 27 21:04:22 2023 +1100 - - Cast time_t's in debug output to long long. - - Should fix Coverity warning about truncation of 64bit time_t. - -commit b0fd60a9de62a03189ad57d0c07f0ac51dc00e95 -Author: Darren Tucker -Date: Mon Feb 27 17:28:59 2023 +1100 - - Do shadow expiry calcs using "long long". - - Coverity flags these as potentially not 64bit time_t safe so use - long long for the calculations and debug output. ok djm@ - -commit 01dbeb3084d714bbd001ff9d03b9de542e8cdf58 -Author: Damien Miller -Date: Mon Feb 27 17:07:52 2023 +1100 - - avoid clash between for getopt's struct option - - Since we don't use getopt_long() nothing outside the getopt() - implementation itself uses this structure, so move it into the - source to remove it from visibility and clashes with libc's - - ok dtucker@ - -commit eb88d07c43afe407094e7d609248d85a15e148ef -Author: Darren Tucker -Date: Sat Feb 25 14:45:41 2023 +1100 - - Revert explicit chmods on private keys. - - This should no longer be needed on Cygwin test runners due to previous - commit. - -commit 52b75db61030a6c8baf66b73644380cf3f58e26a -Author: Darren Tucker -Date: Sat Feb 25 14:43:28 2023 +1100 - - Remove extended ACLs from working dirs. - - This should allow umask to work as expected and prevent tests from - failing due to excessive permissions on private keys. - -commit 0c5d4c843df5605b043a758d69f9a611ef63c479 -Author: Darren Tucker -Date: Fri Feb 24 13:44:13 2023 +1100 - - Explicitly set permissions on user and host keys. - - On cygwin, the umask might not be sufficient. Should fix tests on - Github runners. - -commit 6c9fc9d7a9f7abf82c3294d74e6d4a25735862ce -Author: djm@openbsd.org -Date: Wed Feb 22 03:56:43 2023 +0000 - - upstream: fix progressmeter corruption on wide displays; bz3534 - - feedback/ok dtucker@ - - OpenBSD-Commit-ID: f4affee067cec7c182f3e0b307d758e0472762a3 - -commit fe0bd3cde9665d364e5eedd2c2c2e60d4cdc3786 -Author: dtucker@openbsd.org -Date: Tue Feb 21 06:48:18 2023 +0000 - - upstream: fseek to end of known_hosts before writing to it. - - POSIX and ANSI C require that applications call fseek or similar between - read and writing to a RW file. OpenBSD doesn't enforce this, but some - (System V derived) platforms need this to prevent it from writing a - spurious extra byte (in this case, a newline). ok djm@ deraadt@ - - OpenBSD-Commit-ID: 33e680dcd8110582a93a40a8491024e961f45137 - -commit 357fb8ae14c07cd025eeed66e73de91bab569849 -Author: Darren Tucker -Date: Tue Feb 21 17:51:09 2023 +1100 - - Also run unit tests on AIX VMs. - - In the past these tests took too long, but these days it only adds - about 5 min to the run. - -commit 17781aaa5188ee1477f7779b280d105512e3dbed -Author: Darren Tucker -Date: Tue Feb 21 17:38:55 2023 +1100 - - Wrap stdint.h inside ifdef. - -commit ef798bad38505f7bf1b5fa5c0843dfc5a2b192b9 -Author: Mayank Sharma -Date: Mon Feb 20 17:37:15 2023 +0530 - - Add includes to ptimeout test. - - Fixes test failures on AIX due to type mismatches. - -commit ab69dda05d5268454209f529fa80f477e60d846a -Author: Darren Tucker -Date: Mon Feb 20 18:24:39 2023 +1100 - - Always use the openssl binary configure tells us. - - This fixes tests on platforms that do not have the openssl tool - installed at all. - -commit 2a7e3449908571af601a4c2d12ab140096442e47 -Author: dtucker@openbsd.org -Date: Fri Feb 17 04:22:50 2023 +0000 - - upstream: Remove now-unused compat bit SSH_BUG_RSASIGMD5. The code - - to set this was removed in OpenSSH 7.7 when support for SSH implementations - dating back to before RFC standardization were removed. "burn it all" djm@ - - OpenBSD-Commit-ID: 6330935fbe23dd00be79891505e06d1ffdac7cda - -commit 0833ccf2c8b7ae08b296c06f17bd53e3ab94b0b0 -Author: dtucker@openbsd.org -Date: Fri Feb 17 03:06:18 2023 +0000 - - upstream: Remove now-unused compat bit SSH_BUG_BIGENDIANAES. This - - was previously set for OpenSSH 2.3 (released in 2000) but this check was - removed in OpenSSH 7.7 (2018). ok djm@ deraadt@ - - OpenBSD-Commit-ID: 326426ea328707fc9e83305291ab135c87f678af - -commit c81c2bea6e828d52b62b448b4ffdd3c163177975 -Author: Damien Miller -Date: Fri Feb 17 10:12:40 2023 +1100 - - whitespace fixes - -commit 500f90b39db5f0014e6b0c49ff1f45c994b69293 -Author: Damien Miller -Date: Fri Feb 17 10:02:08 2023 +1100 - - whitespace at EOL - -commit 68350152406339170721c15e97afdf827a5e4001 -Author: dtucker@openbsd.org -Date: Thu Feb 16 10:10:00 2023 +0000 - - upstream: Remove SSH_BUG_PASSWORDPAD compat bit - - since it's no longer used. ok markus@ - - OpenBSD-Commit-ID: b92c21f56fe4b7f9a54790d6a9650725c226820b - -commit 537cccd804eaf65f32bdce037cc31db4e0ab0f44 -Author: dtucker@openbsd.org -Date: Thu Feb 16 07:55:15 2023 +0000 - - upstream: Remove SSH_BUG_IGNOREMSG compat flag - - since it's only applicable to SSH1 and thus no longer used. ok markus@ - "kill it with fire" djm@ - - OpenBSD-Commit-ID: ea13318b1937795d9db4790d3ce0a6ed01584dab - -commit 285cf6cd4b91a0a0ce33193c358c99085af33e43 -Author: jmc@openbsd.org -Date: Fri Feb 10 06:41:53 2023 +0000 - - upstream: space between macro and punctuation; sort usage(); - - OpenBSD-Commit-ID: 6141610cfca037700730e41f868d1d9124958f8c - -commit d39a96f70f81878c77336ed35f5c648c1804b71a -Author: jmc@openbsd.org -Date: Fri Feb 10 06:40:48 2023 +0000 - - upstream: space between macro and punctuation; - - OpenBSD-Commit-ID: abc95e550be9e6d9a7ff64b65c104c7be21ab19e - -commit 16e82bf53fc34e43e3b948d43b68d5b27a7335e6 -Author: jmc@openbsd.org -Date: Fri Feb 10 06:39:27 2023 +0000 - - upstream: sort SYNOPSIS; - - OpenBSD-Commit-ID: dacd9da33277d5669a51213d880632599c890c1e - -commit d9685121ff6d57b8797411f3cb123884a4b96e30 -Author: Darren Tucker -Date: Sat Feb 11 12:32:19 2023 +1100 - - Improve seccomp compat on older systems. - - Check if flags to mmap and madvise are defined before using them. - Should fix problems building on older Linux systems that don't have - these. bz#3537, with & ok djm@. - -commit 6180b0fa4f7996687678702806257e661fd5931e -Author: djm@openbsd.org -Date: Fri Feb 10 05:06:03 2023 +0000 - - upstream: test -Ohashalg=... and that the default output contains both - - specified hash algorithms; prompted by dtucker@ - - OpenBSD-Regress-ID: 26f309208c8d8b8fa9c5f419767b85f1e9b22f51 - -commit d651f5c9fe37e61491eee46c49ba9fa03dbc0e6a -Author: djm@openbsd.org -Date: Fri Feb 10 04:56:30 2023 +0000 - - upstream: let ssh-keygen and ssh-keyscan accept - - -Ohashalg=sha1|sha256 when outputting SSHFP fingerprints to allow algorithm - selection. bz3493 ok dtucker@ - - OpenBSD-Commit-ID: e6e07fe21318a873bd877f333e189eb963a11b3d - -commit 18938d11a90b74d63c20b2d3c965d5bd64786ab1 -Author: djm@openbsd.org -Date: Fri Feb 10 04:47:19 2023 +0000 - - upstream: add a `sshd -G` option that parses and prints the - - effective configuration without attempting to load private keys and perform - other checks. This allows usage of the option before keys have been - generated. - - bz3460 feedback/ok dtucker@ - - OpenBSD-Commit-ID: 774504f629023fc25a559ab1d95401adb3a7fb29 - -commit df7d3dbf7194db8e97730ee0425d4d9d7bdb8b10 -Author: djm@openbsd.org -Date: Fri Feb 10 04:40:28 2023 +0000 - - upstream: make `ssh -Q CASignatureAlgorithms` work as the manpage says - - it should bz3532 - - OpenBSD-Commit-ID: 0ddb17b3fcbd99bfb5baea4ac5e449620cbd3adc - -commit d3b8d4198b6595f23b5859d43dc8fc701f97429b -Author: Darren Tucker -Date: Fri Feb 10 14:26:44 2023 +1100 - - Add CentOS 7 test targets. - -commit 22efb01e355bba4755b730ed417f91c081445bfc -Author: dtucker@openbsd.org -Date: Thu Feb 9 09:55:33 2023 +0000 - - upstream: Test adding terminating newline to known_hosts. - - OpenBSD-Regress-ID: 5fc3010ac450195b3fbdeb68e875564968800365 - -commit caec6da1a583ed8c32c6ad3b81bbcaab46ac8b61 -Author: dtucker@openbsd.org -Date: Wed Feb 8 08:06:03 2023 +0000 - - upstream: ssh-agent doesn't actually take -v, - - so the recently-added ones will result in the test not cleaning up - after itself. Patch from cjwatson at debian.org vi bz#3536. - - OpenBSD-Regress-ID: 1fc8283568f5bf2f918517c2c1e778072cf61b1a - -commit 3c379c9a849a635cc7f05cbe49fe473ccf469ef9 -Author: dtucker@openbsd.org -Date: Thu Feb 9 09:54:11 2023 +0000 - - upstream: Ensure that there is a terminating newline when adding a new - - entry to known_hosts. bz#3529, with git+openssh at limpsquid.nl, ok deraadt@ - markus@ - - OpenBSD-Commit-ID: fa8d90698da1886570512b96f051e266eac105e0 - -commit 95b6bbd2553547260b324b39d602061c88b774bc -Author: Darren Tucker -Date: Tue Feb 7 08:43:47 2023 +1100 - - Replace 9.1 with 9.2 on CI status page. - -commit 195313dfe10a23c82e9d56d5fdd2f59beee1bdcf -Author: Damien Miller -Date: Fri Feb 3 16:33:09 2023 +1100 - - harden Linux seccomp sandbox - - Linux mmap(2) and madvise(2) syscalls support quite a number of funky - flags that we don't expect that sshd/libc will ever need. We can - exclude this kernel attack surface by filtering the mmap(2) flags - and the madvise(2) advice arguments. - - Similarly, the sandboxed process in sshd is a single-threaded program - that does not use shared memory for synchronisation or communication. - Therefore, there should be no reason for the advanced priority - inheritance futex(2) operations to be necessary. These can also be - excluded. - - Motivated by Jann Horn pointing out that there have been kernel bugs - in nearby Linux kernel code, e.g. CVE-2020-29368, CVE-2020-29374 and - CVE-2022-42703. - - Feedback Jann Horn, ok dtucker@ - -commit 6dfb65de949cdd0a5d198edee9a118f265924f33 -Author: Damien Miller -Date: Thu Feb 2 23:21:54 2023 +1100 - - crank versions in RPM specs - -commit d07cfb11a0ca574eb68a3931d8c46fbe862a2021 -Author: Damien Miller -Date: Thu Feb 2 23:21:45 2023 +1100 - - update version in README - -commit 9fe207565b4ab0fe5d1ac5bb85e39188d96fb214 -Author: Damien Miller -Date: Thu Feb 2 23:17:49 2023 +1100 - - adapt compat_kex_proposal() test to portable - -commit 903c556b938fff2d7bff8da2cc460254430963c5 -Author: djm@openbsd.org -Date: Thu Feb 2 12:12:52 2023 +0000 - - upstream: test compat_kex_proposal(); by dtucker@ - - OpenBSD-Regress-ID: 0e404ee264db546f9fdbf53390689ab5f8d38bf2 - -commit 405fba71962dec8409c0c962408e09049e5624b5 -Author: dtucker@openbsd.org -Date: Thu Jan 19 07:53:45 2023 +0000 - - upstream: Check if we can copy sshd or need to use sudo to do so - - during reexec test. Skip test if neither can work. Patch from anton@, tweaks - from me. - - OpenBSD-Regress-ID: 731b96ae74d02d5744e1f1a8e51d09877ffd9b6d - -commit b2a2a8f69fd7737ea17dc044353c514f2f962f35 -Author: djm@openbsd.org -Date: Thu Feb 2 12:10:22 2023 +0000 - - upstream: openssh-9.2 - - OpenBSD-Commit-ID: f7389f32413c74d6e2055f05cf65e7082de03923 - -commit 12da7823336434a403f25c7cc0c2c6aed0737a35 -Author: djm@openbsd.org -Date: Thu Feb 2 12:10:05 2023 +0000 - - upstream: fix double-free caused by compat_kex_proposal(); bz3522 - - by dtucker@, ok me - - OpenBSD-Commit-ID: 2bfc37cd2d41f67dad64c17a64cf2cd3806a5c80 - -commit 79efd95ab5ff99f4cb3a955e2d713b3f54fb807e -Author: Darren Tucker -Date: Wed Feb 1 17:17:26 2023 +1100 - - Skip connection-timeout test on minix3. - - Minix 3's Unix domain sockets don't seem to work the way we expect, so - skip connection-timeout test on that platform. While there, group - together all similarly skipped tests and explicitly comment. - -commit 6b508c4e039619842bcf5a16f8a6b08dd6bec44a -Author: Damien Miller -Date: Wed Feb 1 12:12:05 2023 +1100 - - fix libfido2 detection without pkg-config - - Place libfido2 before additional libraries (that it may depend upon) - and not after. bz3530 from James Zhang; ok dtucker@ - -commit 358e300fed5e6def233a2c06326e51e20ebed621 -Author: deraadt@openbsd.org -Date: Wed Jan 18 20:56:36 2023 +0000 - - upstream: delete useless dependency - - OpenBSD-Commit-ID: e1dc11143f83082e3154d6094f9136d0dc2637ad - -commit a4cb9be1b021b511e281ee55c356f964487d9e82 -Author: deraadt@openbsd.org -Date: Wed Jan 18 20:43:15 2023 +0000 - - upstream: Create and install sshd random relink kit. - - ../Makefile.inc and Makfile are concatenated for reuse, which hopefully won't - be too fragile, we'll see if we need a different approach. The resulting sshd - binary is tested with the new sshd -V option before installation. As the - binary layout is now semi-unknown (meaning relative, fixed, and gadget - offsets are not precisely known), change the filesystem permissions to 511 to - prevent what I call "logged in BROP". I have ideas for improving this further - but this is a first step ok djm - - OpenBSD-Commit-ID: 1e0a2692b7e20b126dda60bf04999d1d30d959d8 - -commit bc7de6f91a9a0ae2f148a9d31a4027d441a51999 -Author: jmc@openbsd.org -Date: Wed Jan 18 06:55:32 2023 +0000 - - upstream: tweak previous; ok djm - - OpenBSD-Commit-ID: df71ce4180c58202dfdc1d92626cfe900b91b7c3 - -commit a20b7e999773e6333c8aa9b0a7fa41966e63b037 -Author: Darren Tucker -Date: Tue Jan 31 19:35:44 2023 +1100 - - Skip connection-timeout test under Valgrind. - - Valgrind slows things down so much that the timeout test fails. Skip - this test until we figure out if we can make it work. - -commit c3ffb54b4fc5e608206037921db6ccbc2f5ab25f -Author: Darren Tucker -Date: Wed Jan 25 21:58:40 2023 +1100 - - Skip connection-timeout when missing FD passing. - - This tests uses multiplexing which uses file descriptor passing, so - skip it if we don't have that. Fixes test failures on Cygwin. - -commit 35253af01d8c0ab444c8377402121816e71c71f5 -Author: djm@openbsd.org -Date: Wed Jan 18 02:00:10 2023 +0000 - - upstream: when restoring non-blocking mode to stdio fds, restore - - exactly the flags that ssh started with and don't just clobber them with - zero, as this could also remove the append flag from the set; - - bz3523; ok dtucker@ - - OpenBSD-Commit-ID: 1336b03e881db7564a4b66014eb24c5230e9a0c0 - -commit 7d17ea151c0b2519f023bd9cc7f141128833ac47 -Author: millert@openbsd.org -Date: Wed Jan 18 01:50:21 2023 +0000 - - upstream: Add a -V (version) option to sshd like the ssh client - - has. OK markus@ deraadt@ - - OpenBSD-Commit-ID: abe990ec3e636fb040132aab8cbbede98f0c413e - -commit 62360feb7f08f2a4c6fc36f3b3449309203c42c9 -Author: millert@openbsd.org -Date: Tue Jan 17 18:52:44 2023 +0000 - - upstream: For "ssh -V" always exit 0, there is no need to check opt - - again. This was missed when the fallthrough in the switch case above it was - removed. OK deraadt@ - - OpenBSD-Commit-ID: 5583e5d8f6d62a8a4215cfa95a69932f344c8120 - -commit 12492c0abf1eb415d08a897cc1d8b9e789888230 -Author: djm@openbsd.org -Date: Tue Jan 17 10:15:10 2023 +0000 - - upstream: also check that an active session inhibits - - UnusedConnectionTimeout idea markus@ - - OpenBSD-Regress-ID: 55c0fb61f3bf9e092b0a53f9041d3d2012f14003 - -commit cef2593c33ac46a58238ff998818754eabdf64ff -Author: djm@openbsd.org -Date: Tue Jan 17 10:02:34 2023 +0000 - - upstream: regression test for UnusedConnectionTimeout - - OpenBSD-Regress-ID: 7f29001374a68e71e5e078f69e4520cf4bcca084 - -commit aff9493a89c71d6a080419b49ac64eead9730491 -Author: djm@openbsd.org -Date: Mon Jan 16 04:11:29 2023 +0000 - - upstream: unbreak test: cannot access shell positional parameters - - past $9 without wrapping the position in braces (i.e. need ${10}, etc.) - - OpenBSD-Regress-ID: 3750ec98d5d409ce6a93406fedde6f220d2ea2ac - -commit 0293c19807f83141cdf33b443154459f9ee471f6 -Author: djm@openbsd.org -Date: Tue Jan 17 09:44:48 2023 +0000 - - upstream: Add a sshd_config UnusedConnectionTimeout option to terminate - - client connections that have no open channels for some length of time. This - complements the recently-added ChannelTimeout option that terminates inactive - channels after a timeout. - - ok markus@ - - OpenBSD-Commit-ID: ca983be74c0350364c11f8ba3bd692f6f24f5da9 - -commit 8ec2e3123802d2beeca06c1644b0b647f6d36dab -Author: djm@openbsd.org -Date: Sun Jan 15 23:35:10 2023 +0000 - - upstream: adapt to ed25519 changes in src/usr.bin/ssh - - OpenBSD-Regress-ID: 4b3e7ba7ee486ae8a0b4790f8112eded2bb7dcd5 - -commit 9fbbfeca1ce4c7ec0001c827bbf4189a3ba0964b -Author: djm@openbsd.org -Date: Sun Jan 15 23:05:32 2023 +0000 - - upstream: update OpenSSH's Ed25519 code to the last version of SUPERCOP - - (20221122) and change the import approach to the same one we use for - Streamlined NTRUPrime: use a shell script to extract the bits we need from - SUPERCOP, make some minor adjustments and squish them all into a single file. - - ok tb@ tobhe@ - - OpenBSD-Commit-ID: 1bc0fd624cb6af440905b8ba74ac7c03311b8e3b - -commit 6283f4bd83eee714d0f5fc55802eff836b06fea8 -Author: Darren Tucker -Date: Sat Jan 14 22:02:44 2023 +1100 - - Allow writev is seccomp sandbox. - - This seems to be used by recent glibcs at least in some configurations. - From bz#3512, ok djm@ - -commit 923c3f437f439cfca238fba37e97a7041782f615 -Author: dtucker@openbsd.org -Date: Sat Jan 14 10:05:54 2023 +0000 - - upstream: Shell syntax fix. From ren mingshuai vi github PR#369. - - OpenBSD-Regress-ID: 6696b2eeefe128099fc3d7ea9f23252cc35156f9 - -commit 4d87a00f704e0365e11c3c38b170c1275ec461fc -Author: dtucker@openbsd.org -Date: Sat Jan 14 09:57:08 2023 +0000 - - upstream: Instead of skipping the all-tokens test if we don't have - - OpenSSL (since we use it to compute the hash), put the hash at the end and - just omit it if we don't have it. Prompted by bz#3521. - - OpenBSD-Regress-ID: c79ecba64250ed3b6417294b6c965e6b12ca5eea - -commit b05406d6f93b8c8ec11ec8b27e7c76cc7a5a55fb -Author: jmc@openbsd.org -Date: Fri Jan 13 07:13:40 2023 +0000 - - upstream: fix double phrase in previous; - - OpenBSD-Commit-ID: 671e6c8dc5e9230518b2bbfa143daaa88adc66c2 - -commit 40564812b659c530eb1f4b62d09e85612aef3107 -Author: dtucker@openbsd.org -Date: Fri Jan 13 03:16:29 2023 +0000 - - upstream: Document "UserKnownHostsFile none". ok djm@ - - OpenBSD-Commit-ID: f695742d39e34ecdcc3c861c3739a84648a4bce5 - -commit d03e245e034019a37388f6f5f893ce848ab6d2e2 -Author: Darren Tucker -Date: Fri Jan 13 23:02:34 2023 +1100 - - Retry package installation 3 times. - - When setting up the CI environment, retry package installation 3 times - before going up. Should help prevent spurious failures during - infrastructure issues. - -commit 625f6bc39840167dafb3bf5b6a3e18503ac986e8 -Author: dtucker@openbsd.org -Date: Fri Jan 13 04:47:34 2023 +0000 - - upstream: Move scp path setting to a helper function. The previous - - commit to add scp to the test sshd's path causes the t-envpass test to fail - when the test scp is given using a fully qualified path. Put this in a - helper function and only call it from the scp tests. - - OpenBSD-Regress-ID: 7533dc1c4265c1de716abb062957994195b36df4 - -commit 6e6f88647042b3cde54a628545c2f5fb656a9327 -Author: dtucker@openbsd.org -Date: Fri Jan 13 04:23:00 2023 +0000 - - upstream: Add scp's path to test sshd's PATH. - - If the scp we're testing is fully qualified (eg it's not in the system - PATH) then add its path to the under-test sshd's PATH so we can find - it. Prompted by bz#3518. - - OpenBSD-Regress-ID: 7df4f5a0be3aa135495b7e5a6719d3cbc26cc4c0 - -commit 8a5e99a70fcf9b022a8aa175ebf6a71f58511da3 -Author: Darren Tucker -Date: Fri Jan 13 15:49:48 2023 +1100 - - Remove skipping test when scp not in path. - - An upcoming change renders this obsolete by adding scp's path to the - test sshd's PATH, and removing this first will make the subsequent sync - easier. - -commit 41f36dd896c8fb8337d403fcf476762986976e9d -Author: dtucker@openbsd.org -Date: Fri Jan 13 02:58:20 2023 +0000 - - upstream: Add a "Host" line to the output of ssh -G showing the - - original host arg. Inspired by patch from vincent at bernat.ch via bz#3343, - ok djm@ - - OpenBSD-Commit-ID: 59c0f60a222113a44d0650cd394376e3beecc883 - -commit f673b49f3be3eb51074fbb8a405beb6cd0f7d93e -Author: djm@openbsd.org -Date: Fri Jan 13 02:44:02 2023 +0000 - - upstream: avoid printf("%s", NULL) if using ssh - - -oUserKnownHostsFile=none and a hostkey in one of the system known hosts file - changes; ok dtucker@ - - OpenBSD-Commit-ID: 7ca87614bfc6da491315536a7f2301434a9fe614 - -commit 93fc7c576563e3d88a1dc019dd213f65607784cc -Author: djm@openbsd.org -Date: Wed Jan 11 05:39:38 2023 +0000 - - upstream: clamp the minimum buffer lengths and number of inflight - - requests too - - OpenBSD-Commit-ID: c4965f62fa0ba850940fd66ae3f60cf516bbcd56 - -commit 48bf234322e639d279c5a28435eae50155e9b514 -Author: djm@openbsd.org -Date: Wed Jan 11 05:36:50 2023 +0000 - - upstream: ignore bogus upload/download buffer lengths in the limits - - extension - - OpenBSD-Commit-ID: c5b023e0954693ba9a5376e4280c739b5db575f8 - -commit 36b00d31833ca74cb0f7c7d8eda1bde55700f929 -Author: djm@openbsd.org -Date: Wed Jan 11 02:13:52 2023 +0000 - - upstream: remove whitespace at EOL from code extracted from SUPERCOP - - OpenBSD-Commit-ID: 1ec524ff2fbb9387d731601437c82008f35a60f4 - -commit d888de06c5e4d7dbf2f2b85f2b5bf028c570cf78 -Author: djm@openbsd.org -Date: Wed Jan 11 00:51:27 2023 +0000 - - upstream: rewrite this test to use a multiplexed ssh session so we can - - control its lifecycle without risk of race conditions; fixes some of the - Github integration tests for openssh-portable - - OpenBSD-Regress-ID: 5451cad59ba0d43ae9eeda48ec80f54405fee969 - -commit 4bcc737a35fdd9cc4af7423d6c23dfd0c7ef4786 -Author: Damien Miller -Date: Wed Jan 11 11:45:17 2023 +1100 - - remove buffer len workaround for NetBSD 4.x - - Switching to from pipes to a socketpair for communicating with the - ssh process avoids the (kernel bug?) problem. - -commit f5154d2aac3e6a32a1b13dec23a701a087850cdc -Author: Damien Miller -Date: Wed Jan 11 11:44:19 2023 +1100 - - add back use of pipes in scp.c under USE_PIPES - - This matches sftp.c which prefers socketpair but uses pipes on - some older platforms. - -commit eec737b59cf13841de46134967a206607000acd4 -Author: millert@openbsd.org -Date: Tue Jan 10 23:22:15 2023 +0000 - - upstream: Switch scp from using pipes to a socketpair for - - communication with it's ssh sub-processes. We no longer need to reserve two - descriptors to ensure that we don't end up using fd 0-2 unexpectedly, that is - handled by sanitise_stdfd() in main(). Based on an original diff from djm@. - OK deraadt@ djm@ - - OpenBSD-Commit-ID: b80c372faac462471e955ddeab9480d668a2e48d - -commit d213d126a4a343abd3a1eb13687d39c1891fe5c8 -Author: jmc@openbsd.org -Date: Fri Jan 6 08:44:11 2023 +0000 - - upstream: tweak previous; ok djm - - OpenBSD-Commit-ID: 229c493452766d70a78b0f02f6ff9894f9028858 - -commit 4a5590a5ee47b7dfd49773e9fdba48ad3089fe64 -Author: Damien Miller -Date: Mon Jan 9 16:33:56 2023 +1100 - - try to improve logging for dynamic-forward test - - previously the logs from the ssh used to exercise the forwarding - channel would clobber the logs from the ssh actually doing the - forwarding - -commit 715bc25dcfccf9fb2bee820155fe071d01a618db -Author: Darren Tucker -Date: Sat Jan 7 23:24:50 2023 +1100 - - Skip dynamic-forward test on minix3. - - This test relies on loopback addresses which minix does not have. - Previously the test would not run at all since it also doesn't have - netcat, but now we use our own netcat it tries and fails. - -commit dd1249bd5c45128a908395c61b26996a70f82205 -Author: Damien Miller -Date: Sun Jan 8 12:08:59 2023 +1100 - - don't test IPv6 addresses if platform lacks support - -commit d77fc611a62f2dfee0b654c31a50a814b13310dd -Author: dtucker@openbsd.org -Date: Fri Jan 6 12:33:33 2023 +0000 - - upstream: When OpenSSL is not available, skip parts of percent test - - that require it. Based on github pr#368 from ren mingshuai. - - OpenBSD-Regress-ID: 49a375b2cf61ccb95b52e75e2e025cd10988ebb2 - -commit 1cd2aac312af9172f1b5cb06c2e1cd090abb83cf -Author: Darren Tucker -Date: Sat Jan 7 23:01:11 2023 +1100 - - Use our own netcat for dynamic-forward test. - - That way we can be surer about its behaviour rather than trying to - second-guess the behaviour of various netcat implementations. - -commit 26cab41c05d7b0859d2a1ea5b6ed253d91848a80 -Author: Darren Tucker -Date: Sat Jan 7 14:30:43 2023 +1100 - - Use autoconf to find openssl binary. - - It's possible to install an OpenSSL in a path not in the system's - default library search path. OpenSSH can still use this (eg if you - specify an rpath) but the openssl binary there may not work. If one is - available on the system path just use that. - -commit 5532e010a0eeb6aa264396514f9aed7948471538 -Author: Darren Tucker -Date: Sat Jan 7 10:34:18 2023 +1100 - - Check openssl_bin path is executable before using. - -commit 5d7b16cff48598d5908db970bfdc9ff9326142c8 -Author: Darren Tucker -Date: Fri Jan 6 23:19:07 2023 +1100 - - Set OPENSSL_BIN from OpenSSL directory. - -commit 344a0e8240eaf08da5d46a5e3a9ecad6e4f64c35 -Author: dtucker@openbsd.org -Date: Fri Jan 6 08:50:33 2023 +0000 - - upstream: Save debug logs from ssh for debugging purposes. - - OpenBSD-Regress-ID: 109e40b06de1c006a3b8e0d8745b790b2c5870a0 - -commit e1ef172646f7f49c80807eea90225ef5e0be55a8 -Author: djm@openbsd.org -Date: Fri Jan 6 08:07:39 2023 +0000 - - upstream: regression test for ChannelTimeout - - OpenBSD-Regress-ID: 280bfbefcfa415428ad744e43f69a8dede8ad685 - -commit 2393ea8daf25853459eb07a528d7577688847777 -Author: djm@openbsd.org -Date: Fri Jan 6 07:18:18 2023 +0000 - - upstream: fix typo in verbose logging - - OpenBSD-Regress-ID: 0497cdb66e003b2f50ed77291a9104fba2e017e9 - -commit 161a5378a3cc2e7aa3f9674cb7f4686ae6ce9586 -Author: djm@openbsd.org -Date: Fri Jan 6 02:59:50 2023 +0000 - - upstream: unit tests for misc.c:ptimeout_* API - - OpenBSD-Regress-ID: 01f8fb12d08e5aaadd4bd4e71f456b6588be9a94 - -commit 018d671d78145f03d6f07ae9d64d51321da70325 -Author: tb@openbsd.org -Date: Wed Jan 4 22:48:57 2023 +0000 - - upstream: Copy bytes from the_banana[] rather than banana() - - Fixes test failure due to segfault seen on arm64 with xonly snap. - - ok djm - - OpenBSD-Regress-ID: 86e2aa4bbd1dff1bc4ebb2969c0d6474485be046 - -commit ab6bb69e251faa8b24f81b25c72ec0120f20cad4 -Author: Damien Miller -Date: Fri Jan 6 19:13:36 2023 +1100 - - unbreak scp on NetBSD 4.x - - e555d5cad5 effectively increased the default copy buffer size for SFTP - transfers. This caused NetBSD 4.x to hang during the "copy local file to - remote file in place" scp.sh regression test. - - This puts back the original 32KB copy buffer size until we can properly - figure out why. - - lots of debugging assistance from dtucker@ - -commit 2d1ff2b9431393ad99ef496d5e3b9dd0d4f5ac8c -Author: djm@openbsd.org -Date: Fri Jan 6 02:47:18 2023 +0000 - - upstream: Implement channel inactivity timeouts - - This adds a sshd_config ChannelTimeouts directive that allows channels that - have not seen traffic in a configurable interval to be automatically closed. - Different timeouts may be applied to session, X11, agent and TCP forwarding - channels. - - Note: this only affects channels over an opened SSH connection and not - the connection itself. Most clients close the connection when their channels - go away, with a notable exception being ssh(1) in multiplexing mode. - - ok markus dtucker - - OpenBSD-Commit-ID: ae8bba3ed9d9f95ff2e2dc8dcadfa36b48e6c0b8 - -commit 0e34348d0bc0b1522f75d6212a53d6d1d1367980 -Author: djm@openbsd.org -Date: Fri Jan 6 02:42:34 2023 +0000 - - upstream: Add channel_set_xtype() - - This sets an "extended" channel type after channel creation (e.g. - "session:subsystem:sftp") that will be used for setting channel inactivity - timeouts. - - ok markus dtucker - - OpenBSD-Commit-ID: 42564aa92345045b4a74300528f960416a15d4ca - -commit ceedf09b2977f3a756c759a6e7eb8f8e9db86a18 -Author: djm@openbsd.org -Date: Fri Jan 6 02:41:49 2023 +0000 - - upstream: tweak channel ctype names - - These are now used by sshd_config:ChannelTimeouts to specify timeouts by - channel type, so force them all to use a similar format without whitespace. - - ok dtucker markus - - OpenBSD-Commit-ID: 66834765bb4ae14f96d2bb981ac98a7dae361b65 - -commit c60438158ad4b2f83d8504257aba1be7d0b0bb4b -Author: djm@openbsd.org -Date: Fri Jan 6 02:39:59 2023 +0000 - - upstream: Add channel_force_close() - - This will forcibly close an open channel by simulating read/write errors, - draining the IO buffers and calling the detach function. - - Previously the detach function was only ever called during channel garbage - collection, but there was no way to signal the user of a channel (e.g. - session.c) that its channel was being closed deliberately (vs. by the - usual state-machine logic). So this adds an extra "force" argument to the - channel cleanup callback to indicate this condition. - - ok markus dtucker - - OpenBSD-Commit-ID: 23052707a42bdc62fda2508636e624afd466324b - -commit d478cdc7ad6edd4b1bcd1e86fb2f23194ff33d5a -Author: djm@openbsd.org -Date: Fri Jan 6 02:38:23 2023 +0000 - - upstream: replace manual poll/ppoll timeout math with ptimeout API - - feedback markus / ok markus dtucker - - OpenBSD-Commit-ID: c5ec4f2d52684cdb788cd9cbc1bcf89464014be2 - -commit 4adf3817a24efe99b06e62630577d683c7cd8065 -Author: djm@openbsd.org -Date: Fri Jan 6 02:37:04 2023 +0000 - - upstream: add ptimeout API for keeping track of poll/ppoll - - timeouts; ok dtucker markus - - OpenBSD-Commit-ID: 3335268ca135b3ec15a947547d7cfbb8ff929ead - -commit 8c7c69d32375d2f3ce9da0109c9bffc560842316 -Author: djm@openbsd.org -Date: Thu Jan 5 05:49:13 2023 +0000 - - upstream: suppress "Connection closed" message when in quiet mode - - OpenBSD-Commit-ID: 8a3ab7176764da55f60bfacfeae9b82d84e3908f - -commit 845ceecea2ac311b0c267f9ecbd34862e1876fc6 -Author: djm@openbsd.org -Date: Mon Jan 2 07:03:57 2023 +0000 - - upstream: regression test for PermitRemoteOpen - - OpenBSD-Regress-ID: 8271aafbf5c21950cd5bf966f08e585cebfe630c - -commit b3daa8dc582348d6ab8150bc1e571b7aa08c5388 -Author: djm@openbsd.org -Date: Mon Jan 2 07:03:30 2023 +0000 - - upstream: fix bug in PermitRemoteOpen which caused it to ignore its - - first argument unless it was one of the special keywords "any" or "none". - - Reported by Georges Chaudy in bz3515; ok dtucker@ - - OpenBSD-Commit-ID: c5678a39f1ff79993d5ae3cfac5746a4ae148ea5 - -commit 0872663a7be0301bcc3d49acdbc9b740a3d972d4 -Author: jmc@openbsd.org -Date: Mon Dec 26 19:16:03 2022 +0000 - - upstream: spelling fixes; from paul tagliamonte amendments to his - - diff are noted on tech - - OpenBSD-Commit-ID: d776dd03d0b882ca9c83b84f6b384f6f9bd7de4a - -commit 797da2812a71785b34890bb6eb44767a7d09cd34 -Author: djm@openbsd.org -Date: Fri Dec 16 07:13:22 2022 +0000 - - upstream: Mention that scp uses the SFTP protocol and remove - - reference to legacy flag. Spotted by, feedback and ok jmc@ - - OpenBSD-Commit-ID: 9dfe04966f52e941966b46c7a2972147f95281b3 - -commit 93f2ce8c050a7a2a628646c00b40b9b53fef93ef -Author: djm@openbsd.org -Date: Fri Dec 16 06:56:47 2022 +0000 - - upstream: Clear signal mask early in main(); sshd may have been - - started with one or more signals masked (sigprocmask(2) is not cleared - on fork/exec) and this could interfere with various things, e.g. the - login grace timer. - - Execution environments that fail to clear the signal mask before running - sshd are clearly broken, but apparently they do exist. - - Reported by Sreedhar Balasubramanian; ok dtucker@ - - OpenBSD-Commit-ID: 77078c0b1c53c780269fc0c416f121d05e3010ae - -commit 4acfaabfae41badb9d334a2ee88c5c6ad041c0d5 -Author: jmc@openbsd.org -Date: Fri Dec 16 06:52:48 2022 +0000 - - upstream: add -X to usage(); - - OpenBSD-Commit-ID: 1bdc3df7de11d766587b0428318336dbffe4a9d0 - -commit e555d5cad5afae7d5ef2bbc02ca591178fe16fed -Author: djm@openbsd.org -Date: Fri Dec 16 03:40:03 2022 +0000 - - upstream: add a -X option to both scp(1) and sftp(1) to allow - - control over some SFTP protocol knobs: the copy buffer length and - the number of inflight requests, both of which are used during - upload/download. - - Previously these could be controlled in sftp(1) using the -b/-R options. - This makes them available in both SFTP protocol clients using the same - option character sequence. - - ok dtucker@ - - OpenBSD-Commit-ID: 27502bffc589776f5da1f31df8cb51abe9a15f1c - -commit 5a7a7acab2f466dc1d7467b5d05d35268c3137aa -Author: deraadt@openbsd.org -Date: Thu Dec 15 18:20:39 2022 +0000 - - upstream: The idiomatic way of coping with signed char vs unsigned - - char (which did not come from stdio read functions) in the presence of - ctype macros, is to always cast to (unsigned char). casting to (int) - for a "macro" which is documented to take int, is weird. And sadly wrong, - because of the sing extension risk.. same diff from florian - - OpenBSD-Commit-ID: 65b9a49a68e22ff3a0ebd593f363e9f22dd73fea - -commit b0b58222c7cc62efd8212c4fb65a545f58ebb22d -Author: Darren Tucker -Date: Mon Dec 19 18:49:51 2022 +1100 - - Simply handling of SSH_CONNECTION PAM env var. - - Prompted by bz#3508: there's no need to cache the value of - sshpam_conninfo so remove the global. While there, add check of - return value from pam_putenv. ok djm@ - -commit ed8444572ae684fdb892f97bae342c6cb6456f04 -Author: Darren Tucker -Date: Mon Dec 19 18:42:34 2022 +1100 - - Add tests for LibreSSL 3.7.0 and OpenSSL 1.1.1s. - -commit abb9a8aaddfcacbd12641f6e4f203da0fa85a287 -Author: Darren Tucker -Date: Sun Dec 18 21:36:25 2022 +1100 - - Use sudo when resetting perms on directories. - -commit 2f5664c5908d84697cbe91302d5d5c4d83cb2121 -Author: Darren Tucker -Date: Sun Dec 18 21:19:33 2022 +1100 - - Set group perms on regress dir. - - This ensures that the tests don't fail due to StrictMode checks. - -commit 137196300fc1540affadde880210f02ba6cb4abf -Author: Darren Tucker -Date: Sun Dec 18 21:13:42 2022 +1100 - - Fetch regress logs from obj dir. - -commit 5f93c4836527d9fda05de8944a1c7b4a205080c7 -Author: Darren Tucker -Date: Tue Dec 13 20:59:54 2022 +1100 - - obsdsnap test VMs runs-on libvirt too. - -commit 8386886fb1ab7fda73069fb0db1dbe0e5a52f758 -Author: Darren Tucker -Date: Tue Dec 13 20:55:37 2022 +1100 - - Run upstream obsdsnap tests on ephemeral runners. - -commit b6e01459b55ece85d7f296b2bc719d1841e1009e -Author: Darren Tucker -Date: Tue Dec 13 20:48:56 2022 +1100 - - Move obsdsnap test VMs to ephemeral runners. - -commit ea6fdf9a1aa71a411f7db218a986392c4fb55693 -Author: Damien Miller -Date: Fri Dec 9 18:00:21 2022 +1100 - - use calloc for allocating arc4random structs - - ok dtucker - -commit 4403b62f5548e91389cb3339d26a9d0c4bb07b34 -Author: dtucker@openbsd.org -Date: Fri Dec 9 00:22:29 2022 +0000 - - upstream: Warn if no host keys for hostbased auth can be loaded. - - OpenBSD-Commit-ID: 2a0a13132000cf8d3593133c1b49768aa3c95977 - -commit a6183e25e3f1842e21999fe88bc40bb99b121dc3 -Author: dtucker@openbsd.org -Date: Fri Dec 9 00:17:40 2022 +0000 - - upstream: Add server debugging for hostbased auth. - - auth_debug_add queues messages about the auth process which is sent to - the client after successful authentication. This also sends those to - the server debug log to aid in debugging. From bz#3507, ok djm@ - - OpenBSD-Commit-ID: 46ff67518cccf9caf47e06393e2a121ee5aa258a - -commit b85c3581c16aaf6e83b9a797c80705a56b1f312e -Author: cheloha@openbsd.org -Date: Sun Dec 4 23:50:49 2022 +0000 - - upstream: remove '?' from getopt(3) loops - - userspace: remove vestigial '?' cases from top-level getopt(3) loops - - getopt(3) returns '?' when it encounters a flag not present in the in - the optstring or if a flag is missing its option argument. We can - handle this case with the "default" failure case with no loss of - legibility. Hence, remove all the redundant "case '?':" lines. - - Prompted by dlg@. With help from dlg@ and millert@. - - Link: https://marc.info/?l=openbsd-tech&m=167011979726449&w=2 - - ok naddy@ millert@ dlg@ - - OpenBSD-Commit-ID: b2f89346538ce4f5b33ab8011a23e0626a67e66e - -commit 9a067e8d28a2249fd73f004961e30c113ee85e5d -Author: dtucker@openbsd.org -Date: Wed Dec 7 11:45:43 2022 +0000 - - upstream: Fix comment typo. - - OpenBSD-Regress-ID: 3b04faced6511bb5e74648c6a4ef4bf2c4decf03 - -commit ce3c3e78ce45d68a82c7c8dc89895f297a67f225 -Author: Darren Tucker -Date: Wed Dec 7 18:58:25 2022 +1100 - - Add SANDBOX_DEBUG to the kitchensink test build. - -commit bc234605fa3eb10f56bf0d74c8ecb0d91ada9d05 -Author: Damien Miller -Date: Wed Dec 7 18:38:25 2022 +1100 - - disable SANDBOX_SECCOMP_FILTER_DEBUG - - It was mistakenly enabled in 2580916e4872 - - Reported by Peter sec-openssh-com.22.fichtner AT 0sg.net - -commit b087c5cfa011b27992e01589314fec830266f99d -Author: Rose <83477269+AtariDreams@users.noreply.github.com> -Date: Tue Nov 29 15:12:54 2022 -0500 - - Update autotools - - Regenerate config files using latest autotools - -commit d63f5494978a185c7421d492b9c2f6f05bb54138 -Author: Darren Tucker -Date: Tue Dec 6 12:22:36 2022 +1100 - - Fix typo in comment. Spotted by tim@ - -commit 73dcca12115aa12ed0d123b914d473c384e52651 -Author: dtucker@openbsd.org -Date: Sun Dec 4 11:03:11 2022 +0000 - - upstream: Remove duplicate includes. - - Patch from AtariDreams via github PR#364. - - OpenBSD-Commit-ID: b9186638a05cb8b56ef7c0de521922b6723644ea - -commit 3cec15543010bc8d6997d896b1717a650afb7e92 -Author: djm@openbsd.org -Date: Fri Dec 2 04:40:27 2022 +0000 - - upstream: make struct sshbuf private - - and remove an unused field; ok dtucker - - OpenBSD-Commit-ID: c7a3d77c0b8c153d463398606a8d57569186a0c3 - -commit 5796bf8ca9535f9fa7d01829a540d2550e05c860 -Author: Darren Tucker -Date: Fri Dec 2 11:43:36 2022 +1100 - - Restore ssh-agent permissions on exit. - - ...enough that subsequent builds can overwrite ssh-agent if necessary. - -commit ccf5a13868cbb4659107458cac1e017c98abcbda -Author: dtucker@openbsd.org -Date: Thu Dec 1 02:22:13 2022 +0000 - - upstream: Clean up ssh-add and ssh-agent logs. - - OpenBSD-Regress-ID: 9eda8e4c3714d7f943ab2e73ed58a233bd29cd2c - -commit 7a8b40cf6a5eda80173140cc6750a6db8412fa87 -Author: dtucker@openbsd.org -Date: Thu Dec 1 02:19:29 2022 +0000 - - upstream: Log output of ssh-agent and ssh-add - - This should make debugging easier. - - OpenBSD-Regress-ID: 5974b02651f428d7e1079b41304c498ca7e306c8 - -commit 4a1805d532616233dd6072e5cd273b96dd3062e6 -Author: dtucker@openbsd.org -Date: Tue Nov 29 22:41:14 2022 +0000 - - upstream: Add void to client_repledge args to fix compiler warning. ok djm@ - - OpenBSD-Commit-ID: 7e964a641ce4a0a0a11f047953b29929d7a4b866 - -commit 815c4704930aa449edf6e812e99d69e9ffd31f01 -Author: djm@openbsd.org -Date: Mon Nov 28 01:38:22 2022 +0000 - - upstream: tighten pledge(2) after session establishment - - feedback, ok & testing in snaps deraadt@ - - OpenBSD-Commit-ID: aecf4d49d28586dfbcc74328d9333398fef9eb58 - -commit f7cebbbf407d772ed71403d314343766782fe540 -Author: djm@openbsd.org -Date: Mon Nov 28 01:37:36 2022 +0000 - - upstream: New EnableEscapeCommandline ssh_config(5) option - - This option (default "no") controls whether the ~C escape is available. - Turning it off by default means we will soon be able to use a stricter - default pledge(2) in the client. - - feedback deraadt@ dtucker@; tested in snaps for a while - - OpenBSD-Commit-ID: 7e277595d60acb8263118dcb66554472257b387a - -commit d323f7ecf52e3d4ec1f4939bf31693e02f891dca -Author: mbuhl@openbsd.org -Date: Fri Nov 18 19:47:40 2022 +0000 - - upstream: In channel_request_remote_forwarding the parameters for - - permission_set_add are leaked as they are also duplicated in the call. Found - by CodeChecker. ok djm - - OpenBSD-Commit-ID: 4aef50fa9be7c0b138188814c8fe3dccc196f61e - -commit 62cc33e6eed847aafdc29e34aa69e9bd82a0ee16 -Author: Darren Tucker -Date: Wed Nov 30 11:23:11 2022 +1100 - - Use -fzero-call-used-regs=used on clang 15. - - clang 15 seems to have a problem with -fzero-call-used-reg=all which - causes spurious "incorrect signature" failures with ED25519. On those - versions, use -fzero-call-used-regs=used instead. (We may add exceptions - later if specific versions prove to be OK). Also move the GCC version - check to match. - - Initial investigation by Daniel Pouzzner (douzzer at mega nu), workaround - suggested by Bill Wendling (morbo at google com). bz#3475, ok djm@ - -commit f84b9cffd52c9c5c359a54a1929f9948e803ab1d -Author: Darren Tucker -Date: Mon Nov 28 21:09:28 2022 +1100 - - Skip unit tests on slow riscv64 hardware. - -commit 9f2747e0bed3faca92679eae69aef10c95dc82f5 -Author: Darren Tucker -Date: Sun Nov 27 15:26:22 2022 +1100 - - Rework how selfhosted tests interact with runners. - - Previously there was one runner per test target (mostly VMs). This had - a few limitations: - - multiple tests that ran on the same target (eg multiple build - configs) were serialized on availability or that runner. - - it needed manual balancing of VMs over host machines. - - To address this, make VMs that use ephemeral disks (ie most of them) - all use a pool of runners with the "libvirt" label. This requires that - we distinguish between "host" and "target" for those. Native runners - and VMs with persistent disks (eg the constantly-updated snapshot ones) - specify the same host and target. - - This should improve test throughput. - -commit d664ddaec87bdc7385be8ef7f1337793e1679d48 -Author: Darren Tucker -Date: Sun Nov 27 12:19:37 2022 +1100 - - Run vmstartup from temp dir. - - This will allow us to create ephemeral disk images per-runner. - -commit 0fa16e952b1fc1c4cf65e3dd138b0e87003e2e45 -Author: Darren Tucker -Date: Sun Nov 27 12:14:00 2022 +1100 - - Make "config" in matrix singular and pass in env. - - This will allow the startup scripts to adapt their behaviour based on - the type and config. - -commit e8857043af54809187be1e8b06749db61112899f -Author: Darren Tucker -Date: Sun Nov 27 11:42:22 2022 +1100 - - Add "libvirt" label to dfly30. - -commit 9775473d84902dc37753686cd10ae71fbe67efda -Author: Darren Tucker -Date: Sun Nov 27 09:28:20 2022 +1100 - - Rename "os" in matrix to "target". - - This is in preparation to distinguish this from the host that the runner - runs on in case where they are separate (eg VMs). - -commit 04fd00ceff39f4544ced6f5342060abe584835d0 -Author: Darren Tucker -Date: Sun Nov 27 09:23:04 2022 +1100 - - Remove unused self-hosted test targets. - -commit c9d9fcad2a11c1cd1550a541f44091d65f0b5584 -Author: Darren Tucker -Date: Sun Nov 27 09:16:15 2022 +1100 - - Remove explicit "default" test config argument. - - Not specifying the test config implicitly selects default args. - -commit 15a01cf15f396f87c6d221c5a6af98331c818962 -Author: Darren Tucker -Date: Wed Nov 23 13:18:54 2022 +1100 - - Add fallback for old platforms w/out MAP_ANON. - -commit 6b9bbbfe8b26db6e9a30a7e08c223e85421aed98 -Author: Darren Tucker -Date: Wed Nov 23 13:09:11 2022 +1100 - - If we haven't found it yet, recheck for sys/stat.h. - - On some very old platforms, sys/stat.h needs sys/types.h, however - autoconf 2.71's AC_CHECK_INCLUDES_DEFAULT checks for them in the - opposite order, which in combination with modern autoconf's - "present but cannot be compiled" behaviour causes it to not be - detected. - -commit 8926956f22639132a9f2433fcd25224e01b900f5 -Author: Darren Tucker -Date: Fri Nov 11 11:25:37 2022 +1100 - - Add dfly62 test target. - -commit 650de7ecd3567b5a5dbf16dd1eb598bd8c20bca8 -Author: dtucker@openbsd.org -Date: Thu Nov 10 23:03:10 2022 +0000 - - upstream: Handle dynamic remote port forwarding in escape commandline's - - -R processing. bz#3499, ok djm@ - - OpenBSD-Commit-ID: 194ee4cfe7ed0e2b8ad0727f493c798a50454208 - -commit 5372db7e7985ba2c00f20fdff8942145ca99e033 -Author: Darren Tucker -Date: Thu Nov 10 12:44:51 2022 +1100 - - Remove seed passing over reexec. - - This was added for the benefit of platforms using ssh-rand-helper to - prevent a delay on each connection as sshd reseeded itself. - - ssh-random-helper is long gone, and since the re-exec happens before the - chroot the re-execed sshd can reseed itself normally. ok djm@ - -commit ca98d3f8c64cfc51af81e1b01c36a919d5947ec2 -Author: Darren Tucker -Date: Wed Nov 9 20:59:20 2022 +1100 - - Skip reexec test on OpenSSL 1.1.1 specifically. - - OpenSSL 1.1.1 has a bug in its RNG that breaks reexec fallback, so skip - that test. See bz#3483 for details. - -commit 5ec4ebc2548e5f7f1b55b2a5cef5b67bdca8146f -Author: dtucker@openbsd.org -Date: Wed Nov 9 09:04:12 2022 +0000 - - upstream: Fix typo in fatal error message. - - Patch from vapier at chromium.org. - - OpenBSD-Commit-ID: 8a0c164a6a25eef0eedfc30df95bfa27644e35cf - -commit e6abafe9a6d809422d3432b95b3f9747b0acaa71 -Author: dtucker@openbsd.org -Date: Wed Nov 9 09:01:52 2022 +0000 - - upstream: Remove errant colon and simplify format - - string in error messages. Patch from vapier at chromium.org. - - OpenBSD-Commit-ID: fc28466ebc7b74e0072331947a89bdd239c160d3 - -commit db2027a687516f87c3fb141e87154bb3d8a7807c -Author: djm@openbsd.org -Date: Wed Nov 9 01:37:44 2022 +0000 - - upstream: rename client_global_hostkeys_private_confirm() to - - client_global_hostkeys_prove_confirm(), as it handles the - "hostkeys-prove00@openssh.com" message; no functional change - - OpenBSD-Commit-ID: 31e09bd3cca6eed26855b88fb8beed18e9bd026d - -commit 1c2be7c2004cf1abcd172fee9fe3eab57cd4c426 -Author: djm@openbsd.org -Date: Wed Nov 9 00:15:59 2022 +0000 - - upstream: typo in comment - - OpenBSD-Commit-ID: 39c58f41e0f32d1ff31731fa6f5bbbc3ad25084a - -commit cf1a9852d7fc93e4abc4168aed09529a57427cdc -Author: Darren Tucker -Date: Wed Nov 9 09:23:47 2022 +1100 - - Defer seed_rng until after closefrom call. - - seed_rng will initialize OpenSSL, and some engine providers (eg Intel's - QAT) will open descriptors for their own use. bz#3483, patch from - joel.d.schuetze at intel.com, ok djm@ - -commit dffa64480163fbf76af7e4fb62c26bb0dd6642aa -Author: Darren Tucker -Date: Wed Nov 9 08:27:47 2022 +1100 - - Fix comment text. From emaste at freebsd.org. - -commit d9df5689c29823ab830ec4f54c83c6cc3c0077ad -Author: Pierre Ossman -Date: Wed Jul 6 13:52:10 2022 +0200 - - Avoid assuming layout of fd_set - - POSIX doesn't specify the internal layout of the fd_set object, so let's - not assume it is just a bit mask. This increases compatibility with - systems that have a different layout. - - The assumption is also worthless as we already refuse to use file - descriptors over FD_SETSIZE anyway. Meaning that the default size of - fd_set is quite sufficient. - -commit 419aa8a312e8d8f491933ca3d5933e602cb05aae -Author: Darren Tucker -Date: Tue Nov 8 12:42:52 2022 +1100 - - Shutdown any VM before trying to check out repo. - - In the case where the previous run did not clean up, the checkout will - fail as it'll leave a stale mount. - -commit a32c07cbb78f65d8527642b96474a83b413f8108 -Author: Darren Tucker -Date: Tue Nov 8 11:33:25 2022 +1100 - - Run vm startup and shutdown from runner temp dir. - - Should work even if the github workspace dir is on a stale sshfs mount. - -commit 2b40a7dfcdb8e616155b9504145aa52b271455aa -Author: Darren Tucker -Date: Tue Nov 8 11:03:31 2022 +1100 - - Add valrind-5 test here too. - -commit 2ea03d1f6d0a05ee2b63ed2dc0f2d54f1e4655a1 -Author: Darren Tucker -Date: Tue Nov 8 09:21:10 2022 +1100 - - Update checkout and upload actions. - - Update actions/checkout and actions/upload-artifact to main branch for - compatibility with node.js v16. - -commit 4e316ff0f18a118232bb9ac6512ee62773a9e8ea -Author: Darren Tucker -Date: Tue Nov 8 09:17:04 2022 +1100 - - Split out rekey test since it runs the longest. - -commit 21625a6424258a92a96a3bb73ae6aabc5ed8a6b4 -Author: dtucker@openbsd.org -Date: Mon Nov 7 10:09:28 2022 +0000 - - upstream: The IdentityFile option in ssh_config can also be used to - - specify a public key file, as documented in ssh.1 for the -i option. Document - this also for IdentityFile in ssh_config.5, for documentation completeness. - From laalsaas at systemli.org via portable github PR#352, ok jmc@ djm@ - - OpenBSD-Commit-ID: 2f943be9f96e60ef81a9a4faa25b009999f9883b - -commit 747691604d3325ed2b62bad85b6fd8563ad32f6c -Author: dtucker@openbsd.org -Date: Mon Nov 7 10:05:38 2022 +0000 - - upstream: Remove some set but otherwise unused variables, spotted - - in -portable by clang 16's -Wunused-but-set-variable. ok djm@ - - OpenBSD-Commit-ID: 3d943ddf2369b38fbf89f5f19728e7dc1daf3982 - -commit 1d78d25653805aefc7a8dd9d86cd7359ada3823c -Author: dtucker@openbsd.org -Date: Mon Nov 7 10:02:59 2022 +0000 - - upstream: Check for and disallow MaxStartups values less than or - - equal to zero during config parsing, rather than faling later at runtime. - bz#3489, ok djm@ - - OpenBSD-Commit-ID: d79c2b7a8601eb9be493629a91245d761154308b - -commit a00f59a645072e5f5a8d207af15916a7b23e2642 -Author: djm@openbsd.org -Date: Mon Nov 7 04:04:40 2022 +0000 - - upstream: fix parsing of hex cert expiry time; was checking whether the - - start time began with "0x", not the expiry time. - - from Ed Maste - - OpenBSD-Commit-ID: 6269242c3e1a130b47c92cfca4d661df15f05739 - -commit f58acaf8c7315483f4ac87d46a1aa2142a713cd8 -Author: Darren Tucker -Date: Mon Nov 7 15:10:59 2022 +1100 - - Fix merge conflict. - -commit 162e5741020a8d996c0c12b988b118e71ed728e6 -Author: Darren Tucker -Date: Mon Nov 7 15:04:33 2022 +1100 - - Branch-specific links for master status badges. - -commit e4b7c12ab24579312aa3ed38ce7041a439ec2d56 -Author: Darren Tucker -Date: Mon Nov 7 14:46:38 2022 +1100 - - Add CIFuzz status badge. - -commit b496b9f831acd1e5bcd875e26e797488beef494a -Author: Darren Tucker -Date: Mon Nov 7 14:45:16 2022 +1100 - - Do not run CIFuzz on selfhosted tree. - - We already run it on the regular tree, no need to double up. - -commit 2138b1c4ddb300129a41a5104627b0d561184c7b -Author: Darren Tucker -Date: Mon Nov 7 14:41:58 2022 +1100 - - Whitespace change to trigger CIFuzz workflow. - -commit 4670b97ef87c7b0f21283c9b07c7191be88dda05 -Author: Darren Tucker -Date: Mon Nov 7 14:34:04 2022 +1100 - - Run cifuzz workflow on the actions as regular CI. - -commit 79391e66ce851ace1baf3c6a35e83a23f08ec2ba -Author: David Korczynski -Date: Tue Nov 30 11:45:20 2021 +0000 - - Add CIFuzz integration - -commit c1893364a0be243270014d7d34362a8101d55112 -Author: dtucker@openbsd.org -Date: Mon Nov 7 02:21:22 2022 +0000 - - upstream: Import regenerated moduli. - - OpenBSD-Commit-ID: b0e54ee4d703bd6929bbc624068666a7a42ecb1f - -commit 5c3f18fb994ef27e685b205ee2351851b80fdbd1 -Author: dtucker@openbsd.org -Date: Mon Nov 7 01:53:01 2022 +0000 - - upstream: Fix typo. From pablomh via -portable github PR#344. - - OpenBSD-Commit-ID: d056ee2e73691dc3ecdb44a6de68e6b88cd93827 - -commit e1c6fcc142066417c9832e634463faa3dd5d116c -Author: Darren Tucker -Date: Mon Nov 7 12:46:58 2022 +1100 - - Link to branch-specific queries for V_9_1 status. - -commit 4f4a5fad6d8892c3f8ee9cd81ec7de6458210c9f -Author: Darren Tucker -Date: Sun Nov 6 10:55:59 2022 +1100 - - Use "prohibit-password" in -portable comments. - - "without-password" is the deprecated alias for "prohibit-password", - so we should reference the latter. From emaste at freebsd.org. - -commit 0f7e1eba55259ec037f515000b4c4afbf446230a -Author: Darren Tucker -Date: Sun Nov 6 10:50:01 2022 +1100 - - Fix tracing disable on FreeBSD. - - Some versions of FreeBSD do not support using id 0 to refer to the - current pid for procctl, so pass getpid() explicitly. From - emaste at freebsd.org. - -commit 32fddb982fd61b11a2f218a115975a87ab126d43 -Author: Darren Tucker -Date: Mon Nov 7 10:39:01 2022 +1100 - - Fix setres*id checks to work with clang-16. - - glibc has the prototypes for setresuid and setresgid behind _GNU_SOURCE, - and clang 16 will error out on implicit function definitions, so add - _GNU_SOURCE and the required headers to the configure checks. From - sam at @gentoo.org via bz#3497. - -commit 12af712d116f42164bcfa56db901d06e4fa27199 -Author: Sam James -Date: Sun Nov 6 04:52:38 2022 +0000 - - configure.ac: Fix -Wstrict-prototypes - - Clang 16 now warns on this and it'll be removed in C23, so let's - just be future proof. It also reduces noise when doing general - Clang 16 porting work (which is a big job as it is). github PR#355. - - Signed-off-by: Sam James - -commit 40b0a5eb6e3edfa2886b60c09c7803353b0cc7f5 -Author: Sam James -Date: Sun Nov 6 04:47:35 2022 +0000 - - configure.ac: Add include for openpty - - Another Clang 16ish fix (which makes -Wimplicit-function-declaration - an error by default). github PR#355. - - See: 2efd71da49b9cfeab7987058cf5919e473ff466b - See: be197635329feb839865fdc738e34e24afd1fca8 - -commit 6b17e128879ec6cc32ca2c28b5d894b4aa72e32d -Author: Rochdi Nassah -Date: Fri Oct 28 01:26:31 2022 +0100 - - Fix broken zlib link. - -commit 99500df246ccb736ddbdd04160dcc82165d81a77 -Author: Darren Tucker -Date: Fri Nov 4 16:59:26 2022 +1100 - - Don't run openbsd-compat tests on Cygwin. - - Add "compat-tests" to the default TEST_TARGET so we can override as - necessary. Override TEST_TARGET for Cygwin as the tests don't currently - compile there. - -commit 3cae9f92a31897409666aa1e6f696f779759332b -Author: djm@openbsd.org -Date: Thu Nov 3 21:59:20 2022 +0000 - - upstream: replace recently-added valid_domain() check for hostnames - - going to known_hosts with a more relaxed check for bad characters; previous - commit broke address literals. Reported by/feedback from florian@ - - OpenBSD-Commit-ID: 10b86dc6a4b206adaa0c11b58b6d5933898d43e0 - -commit 9655217231c9056200bea7ae2dffcc9c0c3eb265 -Author: Darren Tucker -Date: Thu Nov 3 23:07:50 2022 +1100 - - Rerun tests on changes to Makefile.in in any dir. - -commit 3500f0405a3ab16b59a26f3508c4257a3fc3bce6 -Author: Darren Tucker -Date: Thu Nov 3 23:04:08 2022 +1100 - - Link libssh into compat tests. - - The cygwin compat code uses xmalloc, so add libssh.a so pick up that. - -commit ec59effcf65b8a4c85d47ff5a271123259dd0ab8 -Author: Darren Tucker -Date: Thu Nov 3 21:44:23 2022 +1100 - - Fix compat regress to work with non-GNU make. - -commit 73550a218e7dfbbd599534cbf856309bc924f6fd -Author: Darren Tucker -Date: Thu Nov 3 13:41:16 2022 +1100 - - Increase selfhosted job timeout. - - The default job timeout of 360 (6h) is not enough to complete the - regress tests for some of the slow VMs depending on the load on the host. - Increase to 600 (10h). - -commit db97d8d0b90c6ce52b94b153d6f8f5f7d3b11777 -Author: Darren Tucker -Date: Thu Nov 3 10:00:43 2022 +1100 - - Only run opensslver tests if built with OpenSSL. - -commit ba053709638dff2f6603df0c1f340352261d63ea -Author: Darren Tucker -Date: Wed Nov 2 14:16:04 2022 +1100 - - Add tests for OpenSSL 3.0.7 and LibreSSL 3.6.1. - -commit edd24101c7e17d1a8f6576e1aaf62233b47ad6f5 -Author: Darren Tucker -Date: Thu Nov 3 08:17:39 2022 +1100 - - Run compat regress tests too. - -commit fe88d67e7599b0bc73f6e4524add28d743e7f977 -Author: Darren Tucker -Date: Thu Nov 3 08:14:05 2022 +1100 - - Compat tests need libcrypto. - - This was moved to CHANNELLIBS during the libs refactor. Spotted by - rapier at psc.edu. - -commit 96b519726b7944eee3c23a54eee3d5c031ba1533 -Author: Darren Tucker -Date: Thu Nov 3 04:24:39 2022 +1100 - - Include time.h when defining timegm. - - Fixes build on some platforms eg recent AIX. - -commit da6038bd5cd55eb212eb2aec1fc8ae79bbf76156 -Author: Darren Tucker -Date: Tue Nov 1 19:10:30 2022 +1100 - - Always use compat getentropy. - - Have it call native getentropy and fall back as required. Should fix - issues of platforms where libc has getentropy but it is not implemented - in the kernel. Based on github PR#354 from simsergey. - -commit 5ebe18cab6be3247b44c807ac145164010465b82 -Author: Darren Tucker -Date: Wed Nov 2 10:51:48 2022 +1100 - - Check for sockaddr_in.sin_len. - - If found, set SOCK_HAS_LEN which is used in addr.c. Should fix keyscan - tests on platforms with this (eg old NetBSD). - -commit a1febadf426536612c2734168d409147c392e7cf -Author: dtucker@openbsd.org -Date: Sun Oct 30 18:42:07 2022 +0000 - - upstream: Use variable for diff options - - instead of unconditionally specifying "-rN". This will make life easier - in -portable where not all diff's understand -N. - - OpenBSD-Regress-ID: 8b8a407115546be1c6d72d350b1e4f1f960d3cd3 - -commit f6d3ed9a8a9280cbb68d6a499850cfe810e92bd0 -Author: Darren Tucker -Date: Mon Oct 31 05:13:02 2022 +1100 - - OpenSSL dev branch is 302 not 320. - - While there, also accept 301 which it shat it was previously. - -commit 25c8a2bbcc10c493d27faea57c42a6bf13fa51f2 -Author: djm@openbsd.org -Date: Fri Oct 28 02:47:04 2022 +0000 - - upstream: put sshkey_check_rsa_length() back in sshkey.c to unbreak - - OPENSSL=no builds - - OpenBSD-Commit-ID: 99eec58abe382ecd14b14043b195ee1babb9cf6e - -commit 1192588546c29ceec10775125f396555ea71850f -Author: djm@openbsd.org -Date: Fri Oct 28 02:29:34 2022 +0000 - - upstream: allow ssh-keyscan(1) to accept CIDR address ranges, e.g. - - ssh-keyscan 192.168.0.0/24 - - If a CIDR range is passed, then it will be expanded to all possible - addresses in the range including the all-0s and all-1s addresses. - - bz#976 feedback/ok markus@ - - OpenBSD-Commit-ID: ce6c5211f936ac0053fd4a2ddb415277931e6c4b - -commit 64af4209309461c79c39eda2d13f9d77816c6398 -Author: Damien Miller -Date: Fri Oct 28 12:54:35 2022 +1100 - - fix merge botch - -commit 27267642699342412964aa785b98afd69d952c88 -Author: djm@openbsd.org -Date: Fri Oct 28 00:44:44 2022 +0000 - - upstream: refactor sshkey_private_deserialize - - feedback/ok markus@ - - OpenBSD-Commit-ID: f5ca6932fdaf840a5e8250becb38315a29b5fc9f - -commit 2519a7077a9332f70935e5242ba91ee670ed6b87 -Author: djm@openbsd.org -Date: Fri Oct 28 00:44:17 2022 +0000 - - upstream: refactor sshkey_private_serialize_opt() - - feedback/ok markus@ - - OpenBSD-Commit-ID: 61e0fe989897901294efe7c3b6d670cefaf44cbd - -commit 11a768adf98371fe4e43f3b06014024c033385d5 -Author: djm@openbsd.org -Date: Fri Oct 28 00:43:30 2022 +0000 - - upstream: refactor certify - - feedback/ok markus@ - - OpenBSD-Commit-ID: 35d742992e223eaca3537e6fb3d3002c08eed4f6 - -commit 3fbc58bb249d967cc43ebdc554f6781bb73d4a58 -Author: djm@openbsd.org -Date: Fri Oct 28 00:43:08 2022 +0000 - - upstream: refactor sshkey_sign() and sshkey_verify() - - feedback/ok markus@ - - OpenBSD-Commit-ID: 368e662c128c99d05cc043b1308d2b6c71a4d3cc - -commit a1deb6cdbbe6afaab74ecb08fcb62db5739267be -Author: djm@openbsd.org -Date: Fri Oct 28 00:41:52 2022 +0000 - - upstream: refactor sshkey_from_blob_internal() - - feedback/ok markus@ - - OpenBSD-Commit-ID: 1f46c0cbb8060ee9666a02749594ad6658c8e283 - -commit 7d00799c935271ce89300494c5677190779f6453 -Author: djm@openbsd.org -Date: Fri Oct 28 00:41:17 2022 +0000 - - upstream: refactor sshkey_from_private() - - feedback/ok markus@ - - OpenBSD-Commit-ID: e5dbe7a3545930c50f70ee75c867a1e08b382b53 - -commit 262647c2e920492ca57f1b9320d74f4a0f6e482b -Author: djm@openbsd.org -Date: Fri Oct 28 00:39:29 2022 +0000 - - upstream: factor out key generation - - feedback/ok markus@ - - OpenBSD-Commit-ID: 5b4211bff4de8d9adb84bc72857a8c42c44e7ceb - -commit 401c74e7dc15eab60540653d2f94d9306a927bab -Author: djm@openbsd.org -Date: Fri Oct 28 00:38:58 2022 +0000 - - upstream: refactor and simplify sshkey_read() - - feedback/ok markus@ - - OpenBSD-Commit-ID: 0d93b7a56e31cd06a8bb0d2191d084ce254b0971 - -commit 591fed94e66a016acf87f4b7cd416ce812f2abe8 -Author: djm@openbsd.org -Date: Fri Oct 28 00:37:24 2022 +0000 - - upstream: factor out public key serialization - - feedback/ok markus@ - - OpenBSD-Commit-ID: a3570c4b97290c5662890aea7328d87f55939033 - -commit 1e78844ae2b2dc01ba735d5ae740904c57e13685 -Author: djm@openbsd.org -Date: Fri Oct 28 00:36:31 2022 +0000 - - upstream: factor out sshkey_equal_public() - - feedback/ok markus@ - - OpenBSD-Commit-ID: 1368ba114cb37732fe6ec3d89c7e6d27ea6fdc94 - -commit 25de1c01a8b9a2c8ab9b1da22444a03e89c982de -Author: djm@openbsd.org -Date: Fri Oct 28 00:35:40 2022 +0000 - - upstream: begin big refactor of sshkey - - Move keytype data and some of the type-specific code (allocation, - cleanup, etc) out into each key type's implementation. Subsequent - commits will move more, with the goal of having each key-*.c file - owning as much of its keytype's implementation as possible. - - lots of feedback + ok markus@ - - OpenBSD-Commit-ID: 0f2b4334f73914344e9e5b3d33522d41762a57ec - -commit 445363433ba20b8a3e655b113858c836da46a1cb -Author: djm@openbsd.org -Date: Mon Oct 24 22:43:36 2022 +0000 - - upstream: Be more paranoid with host/domain names coming from the - - never write a name with bad characters to a known_hosts file. - - reported by David Leadbeater, ok deraadt@ - - OpenBSD-Commit-ID: ba9b25fa8b5490b49398471e0c9657b0cbc7a5ad - -commit 7190154de2c9fe135f0cc1ad349cb2fa45152b89 -Author: djm@openbsd.org -Date: Mon Oct 24 21:52:50 2022 +0000 - - upstream: regress test for unmatched glob characters; fails before - - previous commit but passes now. bz3488; prodded by dtucker@ - - OpenBSD-Regress-ID: 0cc5cc9ea4a6fd170dc61b9212f15badaafb3bbd - -commit a4821a592456c3add3cd325db433110cdaaa3e5c -Author: djm@openbsd.org -Date: Mon Oct 24 21:51:55 2022 +0000 - - upstream: when scp(1) is using the SFTP protocol for transport (the - - default), better match scp/rcp's handling of globs that don't match the - globbed characters but do match literally (e.g. trying to transfer - "foo.[1]"). - - Previously scp(1) in SFTP mode would not match these pathnames but - legacy scp/rcp mode would. - - Reported by Michael Yagliyan in bz3488; ok dtucker@ - - OpenBSD-Commit-ID: d8a3773f53015ba811fddba7473769a2fd343e11 - -commit 18376847b8043ba967eabbe23692ef74c9a3fddc -Author: jsg@openbsd.org -Date: Thu Oct 13 09:09:28 2022 +0000 - - upstream: use correct type with sizeof ok djm@ - - OpenBSD-Commit-ID: d6c882c2e8a42ff831a5b3cbc2c961ecb2dd6143 - -commit 4a4883664d6b4e9e4e459a8cdc16bd8d4b735de9 -Author: jmc@openbsd.org -Date: Fri Oct 7 06:00:58 2022 +0000 - - upstream: ssh-agent.1: - use Nm not Xr for self-ref - while here, - - wrap a long line - - ssh-agent.c: - - add -O to usage() - - OpenBSD-Commit-ID: 855dac4695cef22e96d69c53436496bc408ca389 - -commit 9fd2441113fce2a83fc7470968c3b27809cc7f10 -Author: djm@openbsd.org -Date: Fri Oct 7 04:06:26 2022 +0000 - - upstream: document "-O no-restrict-websafe"; spotted by Ross L - - Richardson - - OpenBSD-Commit-ID: fe9eaa50237693a14ebe5b5614bf32a02145fe8b - -commit 614252b05d70f798a0929b1cd3d213030ad4d007 -Author: Darren Tucker -Date: Tue Oct 18 06:29:16 2022 +1100 - - OpenSSL dev branch now identifies as 3.2.0. - -commit 195e5a65fd793a738ea8451ebfdd1919db5aff3e -Author: Damien Miller -Date: Mon Oct 17 09:41:47 2022 +1100 - - revert c64b62338b4 and guard POLL* defines instead - - c64b62338b4 broke OSX builds, which do have poll.h but lack ppoll(2) - Spotted by dtucker - -commit bc2e480d99613bd59720edae244d1764636544c4 -Author: Damien Miller -Date: Fri Oct 14 14:52:22 2022 +1100 - - undef _get{short,long} before redefining - -commit 5eb796a369c64f18d55a6ae9b1fa9b35eea237fb -Author: Harmen Stoppels -Date: Thu Oct 13 16:08:46 2022 +0200 - - Fix snprintf configure test for clang 15 - - Clang 15 -Wimplicit-int defaults to an error in C99 mode and above. - A handful of tests have "main(..." and not "int main(..." which caused - the tests to produce incorrect results. - -commit c64b62338b46ffa08839f05f21ad69fa6234dc17 -Author: Damien Miller -Date: Mon Oct 10 12:32:43 2022 +1100 - - skip bsd-poll.h if poll.h found; ok dtucker - -commit 5ee2b8ccfcf4b606f450eb0ff2305e311f68b0be -Author: djm@openbsd.org -Date: Thu Oct 6 22:42:37 2022 +0000 - - upstream: honour user's umask if it is more restrictive then the ssh - - default (022); based on patch from Alex Henrie, ok dtucker@ deraadt@ - - OpenBSD-Commit-ID: fe1b9e15fc9a4f49fc338e848ce14d8727abe82d - -commit a75cffc2700cebd3e2dd9093f7f7388d2be95cb7 -Author: Darren Tucker -Date: Fri Oct 7 03:54:56 2022 +1100 - - Add LibreSSL 3.6.0 to test suite. - - While there, bump OpenSSL to latest 1.1.1q release. - -commit fcc0f0c0e96a30076683fea9a7c9eedc72931742 -Author: Darren Tucker -Date: Thu Oct 6 21:18:16 2022 +1100 - - Add 9.1 branch to CI status page. - -commit ef211eee63821d894a8bf81f22bfba9f6899d0fe -Author: Darren Tucker -Date: Tue Oct 4 23:20:23 2022 +1100 - - Test commits to all branches of portable. - - Only test OpenBSD upstream on commits to master since that's what it - tracks. - -commit fe646de03cafb6593ff4e4954bca9ec4b4b753a8 -Author: Damien Miller -Date: Wed Oct 5 03:47:26 2022 +1100 - - whitespace at EOL - -commit a6e1852d10c63a830196e82168dadd957aaf28ec -Author: Damien Miller -Date: Wed Oct 5 03:40:01 2022 +1100 - - mention libfido2 autodetection - -commit 7360c2c206f33d309edbaf64036c96fadf74d640 -Author: Damien Miller -Date: Wed Oct 5 03:37:36 2022 +1100 - - remove mention of --with-security-key-builtin - - it is enabled by default when libfido2 is installed - -commit 0ffb46f2ee2ffcc4daf45ee679e484da8fcf338c -Author: Damien Miller -Date: Tue Oct 4 01:51:42 2022 +1100 - - update .depend - -commit 657e676ff696c7bb787bffb0e249ea1be3b474e1 -Author: Damien Miller -Date: Tue Oct 4 01:45:52 2022 +1100 - - update release notes URL - -commit f059da2b29840c0f048448809c317ce2ae014da7 -Author: Damien Miller -Date: Tue Oct 4 01:45:41 2022 +1100 - - crank versions in RPM spec files - -commit b51f3f172d87cbdb80ca4eb7b2149e56a7647557 -Author: djm@openbsd.org -Date: Mon Sep 26 22:18:40 2022 +0000 - - upstream: openssh-9.1 - - OpenBSD-Commit-ID: 5a467b2ee81da01a86adf1ad93b62b1728494e56 - -commit 4cf8d0c0f3030f594a238bab21a0695735515487 -Author: dtucker@openbsd.org -Date: Wed Sep 21 22:26:50 2022 +0000 - - upstream: Fix typo. From AlexanderStohr via github PR#343. - - OpenBSD-Commit-ID: a134c9b4039e48803fc6a87f955b0f4a03181497 - -commit 8179fed3264d5919899900ed8881d5f9bb57ca33 -Author: djm@openbsd.org -Date: Mon Sep 19 21:39:16 2022 +0000 - - upstream: add RequiredRSASize to the list of keywords accepted by - - -o; spotted by jmc@ - - OpenBSD-Commit-ID: fe871408cf6f9d3699afeda876f8adbac86a035e - -commit 5f954929e9f173dd1e279e07d0e8b14fa845814d -Author: Damien Miller -Date: Mon Sep 19 20:59:34 2022 +1000 - - no need for glob.h here - - it also causes portability problems - -commit 03d94a47207d58b3db37eba4f87eb6ae5a63168a -Author: Damien Miller -Date: Mon Sep 19 20:59:04 2022 +1000 - - avoid Wuninitialized false positive in gcc-12ish - -commit 9d952529113831fb3071ab6e408d2726fd72e771 -Author: djm@openbsd.org -Date: Mon Sep 19 10:46:00 2022 +0000 - - upstream: use users-groups-by-id@openssh.com sftp-server extension - - (when available) to fill in user/group names for directory listings. - Implement a client-side cache of see uid/gid=>user/group names. ok markus@ - - OpenBSD-Commit-ID: f239aeeadfa925a37ceee36ee8b256b8ccf4466e - -commit 8ff680368b0bccf88ae85d4c99de69387fbad7a6 -Author: djm@openbsd.org -Date: Mon Sep 19 10:43:12 2022 +0000 - - upstream: sftp client library support for - - users-groups-by-id@openssh.com; ok markus@ - - OpenBSD-Commit-ID: ddb2f33a2da6349a9a89a8b5bcb9ca7c999394de - -commit 488f6e1c582212c2374a4bf8cd1b703d2e70fb8b -Author: djm@openbsd.org -Date: Mon Sep 19 10:41:58 2022 +0000 - - upstream: extend sftp-common.c:extend ls_file() to support supplied - - user/group names; ok markus@ - - OpenBSD-Commit-ID: c70c70498b1fdcf158531117e405b6245863bfb0 - -commit 74b77f7497dba3a58315c8f308883de448078057 -Author: djm@openbsd.org -Date: Mon Sep 19 10:40:52 2022 +0000 - - upstream: sftp-server(8): add a "users-groups-by-id@openssh.com" - - extension request that allows the client to obtain user/group names that - correspond to a set of uids/gids. - - Will be used to make directory listings more useful and consistent - in sftp(1). - - ok markus@ - - OpenBSD-Commit-ID: 7ebabde0bcb95ef949c4840fe89e697e30df47d3 - -commit 231a346c0c67cc7ca098360f9a554fa7d4f1eddb -Author: djm@openbsd.org -Date: Mon Sep 19 08:49:50 2022 +0000 - - upstream: better debugging for connect_next() - - OpenBSD-Commit-ID: d16a307a0711499c971807f324484ed3a6036640 - -commit 1875042c52a3b950ae5963c9ca3774a4cc7f0380 -Author: djm@openbsd.org -Date: Sat Sep 17 10:34:29 2022 +0000 - - upstream: Add RequiredRSASize for sshd(8); RSA keys that fall - - beneath this limit will be ignored for user and host-based authentication. - - Feedback deraadt@ ok markus@ - - OpenBSD-Commit-ID: 187931dfc19d51873df5930a04f2d972adf1f7f1 - -commit 54b333d12e55e6560b328c737d514ff3511f1afd -Author: djm@openbsd.org -Date: Sat Sep 17 10:33:18 2022 +0000 - - upstream: add a RequiredRSASize for checking RSA key length in - - ssh(1). User authentication keys that fall beneath this limit will be - ignored. If a host presents a host key beneath this limit then the connection - will be terminated (unfortunately there are no fallbacks in the protocol for - host authentication). - - feedback deraadt, Dmitry Belyavskiy; ok markus@ - - OpenBSD-Commit-ID: 430e339b2a79fa9ecc63f2837b06fdd88a7da13a - -commit 07d8771bacfefbcfb37fa8a6dc6103bcc097e0ab -Author: djm@openbsd.org -Date: Sat Sep 17 10:30:45 2022 +0000 - - upstream: Add a sshkey_check_rsa_length() call for checking the - - length of an RSA key; ok markus@ - - OpenBSD-Commit-ID: de77cd5b11594297eda82edc594b0d32b8535134 - -commit 3991a0cf947cf3ae0f0373bcec5a90e86a7152f5 -Author: djm@openbsd.org -Date: Sat Sep 17 10:11:29 2022 +0000 - - upstream: actually hook up restrict_websafe; the command-line flag - - was never actually used. Spotted by Matthew Garrett - - OpenBSD-Commit-ID: 0b363518ac4c2819dbaa3dfad4028633ab9cdff1 - -commit 30b2a7e4291fb9e357f80a237931ff008d686d3b -Author: djm@openbsd.org -Date: Fri Sep 16 06:55:37 2022 +0000 - - upstream: correct error value - - OpenBSD-Commit-ID: 780efcbad76281f11f14b2a5ff04eb6db3dfdad4 - -commit ac1ec9545947d9f9657259f55d04cb49d3a94c8a -Author: djm@openbsd.org -Date: Fri Sep 16 03:33:14 2022 +0000 - - upstream: sftp: Be a bit more clever about completions - - There are commands (e.g. "get" or "put") that accept two - arguments, a local path and a remote path. However, the way - current completion is written doesn't take this distinction into - account and always completes remote or local paths. - - By expanding CMD struct and "cmds" array this distinction can be - reflected and with small adjustment to completer code the correct - path can be completed. - - By Michal Privoznik, ok dtucker@ - - OpenBSD-Commit-ID: 1396d921c4eb1befd531f5c4a8ab47e7a74b610b - -commit 590db83384f9d99fc51c84505792d26d1ef60df9 -Author: djm@openbsd.org -Date: Fri Sep 16 03:13:34 2022 +0000 - - upstream: sftp: Don't attempt to complete arguments for - - non-existent commands - - If user entered a non-existent command (e.g. because they made a - typo) there is no point in trying to complete its arguments. Skip - calling complete_match() if that's the case. - - From Michal Privoznik - - OpenBSD-Commit-ID: cf39c811a68cde2aeb98fc85addea4000ef6b07a - -commit ff9809fdfd1d9a91067bb14a77d176002edb153c -Author: djm@openbsd.org -Date: Wed Sep 14 00:14:37 2022 +0000 - - upstream: sk_enroll: never drop SSH_SK_USER_VERIFICATION_REQD flag - - from response - - Now that all FIDO signing calls attempt first without PIN and then - fall back to trying PIN only if that attempt fails, we can remove the - hack^wtrick that removed the UV flag from the keys returned during - enroll. - - By Corinna Vinschen - - OpenBSD-Commit-ID: 684517608c8491503bf80cd175425f0178d91d7f - -commit 940dc10729cb5a95b7ee82c10184e2b9621c8a1d -Author: djm@openbsd.org -Date: Wed Sep 14 00:13:13 2022 +0000 - - upstream: a little extra debugging - - OpenBSD-Commit-ID: edf1601c1d0905f6da4c713f4d9cecc7d1c0295a - -commit 4b5f91cb959358141181b934156513fcb8a6c1e3 -Author: djm@openbsd.org -Date: Wed Sep 14 00:02:03 2022 +0000 - - upstream: ssh-agent: attempt FIDO key signing without PIN and use - - the error to determine whether a PIN is required and prompt only if - necessary. from Corinna Vinschen - - OpenBSD-Commit-ID: dd6be6a0b7148608e834ee737c3479b3270b00dd - -commit 113523bf0bc33600b07ebb083572c8c346b6fdf4 -Author: jmc@openbsd.org -Date: Sun Sep 11 06:38:11 2022 +0000 - - upstream: .Li -> .Vt where appropriate; from josiah frentsos, - - tweaked by schwarze - - ok schwarze - - OpenBSD-Commit-ID: 565046e3ce68b46c2f440a93d67c2a92726de8ed - -commit 86af013b56cecb5ee58ae0bd9d495cd586fc5918 -Author: jsg@openbsd.org -Date: Sat Sep 10 08:50:53 2022 +0000 - - upstream: fix repeated words ok miod@ jmc@ - - OpenBSD-Commit-ID: 6765daefe26a6b648cc15cadbbe337596af709b7 - -commit 0ba39b93b326a7d5dfab776cc9b9d326161a9b16 -Author: djm@openbsd.org -Date: Fri Sep 9 03:31:42 2022 +0000 - - upstream: notifier_complete(NULL, ...) is a noop, so no need to test - - that ctx!=NULL; from Corinna Vinschen - - OpenBSD-Commit-ID: ade2f2e9cc519d01a586800c25621d910bce384a - -commit be197635329feb839865fdc738e34e24afd1fca8 -Author: Sam James -Date: Thu Sep 8 02:49:29 2022 +0100 - - openbsd-compat/bsd-asprintf: add include for vsnprintf - - Fixes the following build failure with Clang 15 on musl: - ``` - bsd-asprintf.c:51:8: error: call to undeclared library function 'vsnprintf' with type 'int (char *, unsigned long, const char *, struct __va_list_tag *)'; ISO C99 and laterclang -O2 -pipe -fdiagnostics-color=always -frecord-gcc-switches -pipe -Wunknown-warning-option -Qunused-arguments -Wall -Wpointer-arith -Wuninitialized -Wsign-compare -Wformat-security -Wsizeof-pointer-memaccess -Wno-pointer-sign -Wno-unused-result -Wmisleading-indentation -Wbitwise-instead-of-logical -fno-strict-aliasing -mretpoline -ftrapv -fzero-call-used-regs=all -fno-builtin-memset -fstack-protector-strong -fPIE -I. -I. -D_XOPEN_SOURCE=600 -D_BSD_SOURCE -D_DEFAULT_SOURCE -DSSHDIR=\"/etc/ssh\" -D_PATH_SSH_PROGRAM=\"/usr/bin/ssh\" -D_PATH_SSH_ASKPASS_DEFAULT=\"/usr/lib/misc/ssh-askpass\" -D_PATH_SFTP_SERVER=\"/usr/lib/misc/sftp-server\" -D_PATH_SSH_KEY_SIGN=\"/usr/lib/misc/ssh-keysign\" -D_PATH_SSH_PKCS11_HELPER=\"/usr/lib/misc/ssh-pkcs11-helper\" -D_PATH_SSH_SK_HELPER=\"/usr/lib/misc/ssh-sk-helper\" -D_PATH_SSH_PIDDIR=\"/run\" -D_PATH_PRIVSEP_CHROOT_DIR=\"/var/empty\" -DHAVE_CONFIG_H -c cipher-aes.c -o cipher-aes.o - do not support - implicit function declarations [-Wimplicit-function-declaration] - ret = vsnprintf(string, INIT_SZ, fmt, ap2); - ^ - bsd-asprintf.c:51:8: note: include the header or explicitly provide a declaration for 'vsnprintf' - 1 error generated. - ``` - -commit 6cb6f660bb35f77a0456dd2581ddf39c29398a5e -Author: Darren Tucker -Date: Fri Sep 2 16:43:27 2022 +1000 - - Remove DEF_WEAK, it's already in defines.h. - -commit ce39e7d8b70c4726defde5d3bc4cb7d40d131153 -Author: Darren Tucker -Date: Fri Sep 2 14:28:14 2022 +1000 - - Resync arc4random with OpenBSD. - - This brings us up to current, including djm's random-reseeding change, - as prompted by logan at cyberstorm.mu in bz#3467. It brings the - platform-specific hooks from LibreSSL Portable, simplified to match our - use case. ok djm@. - -commit beaddde26f30e2195b8aa4f3193970e140e17305 -Author: Darren Tucker -Date: Fri Sep 2 14:20:04 2022 +1000 - - Move OPENBSD ORIGINAL marker. - - Putting this after the copyright statement (which doesn't change) - instead of before the version identifier (which does) prevents merge - conflicts when resyncing changes. - -commit c83e467ead67a8cb48ef4bec8085d6fb880a2ff4 -Author: Darren Tucker -Date: Fri Sep 2 14:17:28 2022 +1000 - - Remove arc4random_uniform from arc4random.c - - This was previously moved into its own file (matching OpenBSD) which - prematurely committed in commit 73541f2. - -commit 5f45c2395c60865e59fa44152ff1d003a128c5bc -Author: djm@openbsd.org -Date: Fri Sep 2 04:20:02 2022 +0000 - - upstream: sk-usbhid: fix key_lookup() on tokens with built-in UV - - explicitly test whether the token performs built-in UV (e.g. biometric - tokens) and enable UV in that case. From Pedro Martelletto via GHPR#388 - - OpenBSD-Commit-ID: 007eb7e387d27cf3029ab06b88224e03eca62ccd - -commit 03277a4aa49b80af541a3e691f264c0c0d8f9cec -Author: Darren Tucker -Date: Wed Aug 31 20:26:30 2022 +1000 - - Move sftp from valgrind-2 to 3 to rebalance. - -commit fcf5365da69c516817321ba89c3a91df98d098df -Author: djm@openbsd.org -Date: Wed Aug 31 02:56:40 2022 +0000 - - upstream: whitespace - - OpenBSD-Commit-ID: c2bcbf93610d3d62ed206cdf9bf9ff98c6aaf232 - -commit e60136a3d7a223dd8e84ba8a6895bc3142360993 -Author: Damien Miller -Date: Mon Aug 29 13:27:45 2022 +1000 - - additional keys - -commit 2b02dcb505288c462d1b5dd1ac04e603d01340eb -Author: Damien Miller -Date: Mon Aug 29 13:23:43 2022 +1000 - - cross-sign allowed_signers with PGP key - - Provides continuity of trust from legacy PGP release key to - the SSHSIG signing keys that we will use henceforth for git - signing. - -commit 51b345f177ae981b8755f6bdf8358b1cc5e83d67 -Author: Darren Tucker -Date: Sat Aug 27 21:49:27 2022 +1000 - - Add libcrypt-devel to cygwin-release deps. - - Based on feedback from vinschen at redhat.com. - -commit 9f81736cf16dd8dda1c8942f1973a5f80b8cd78c -Author: Darren Tucker -Date: Sat Aug 27 09:37:40 2022 +1000 - - Add Windows 2022 test targets. - -commit 85e1a69243f12be8520438ad6a3cfdc0b7fcbb2d -Author: Darren Tucker -Date: Fri Aug 26 16:26:06 2022 +1000 - - Add cygwin-release test target. - - This also moves the cygwin package install from the workflow file to - setup_ci.sh so that we can install different sets of Cygwin packages - for different test configs. - -commit 92382dbe8bf9ea1225b16858f9b9b208c15c7e8d -Author: djm@openbsd.org -Date: Fri Aug 26 08:16:27 2022 +0000 - - upstream: whitespace - - OpenBSD-Commit-ID: a5d015efbfd228dc598ffdef612d2da3a579e5d8 - -commit 70a5de0a50e84d7250eb4e4537f765599f64c4af -Author: djm@openbsd.org -Date: Fri Aug 26 08:12:56 2022 +0000 - - upstream: whitespace - - OpenBSD-Commit-ID: d297e4387935d4aef091c5e9432578c2e513f538 - -commit 3a683a19fd116ea15ebf8aa13d02646cceb302a9 -Author: Damien Miller -Date: Fri Aug 26 14:23:55 2022 +1000 - - initial list of allowed signers - -commit 6851f4b8c3fc1b3e1114c56106e4dc31369c8513 -Author: Darren Tucker -Date: Fri Aug 19 17:22:18 2022 +1000 - - Install Cygwin packages based on OS not config. - -commit f96480906893ed93665df8cdf9065865c51c1475 -Author: djm@openbsd.org -Date: Fri Aug 19 06:07:47 2022 +0000 - - upstream: attemp FIDO key signing without PIN and use the error - - code returned to fall back only if necessary. Avoids PIN prompts for FIDO - tokens that don't require them; part of GHPR#302 - - OpenBSD-Commit-ID: 4f752aaf9f2e7c28bcaaf3d4f8fc290131bd038e - -commit 5453333b5d28e313284cb9aae82899704103f98d -Author: djm@openbsd.org -Date: Fri Aug 19 05:53:28 2022 +0000 - - upstream: remove incorrect check that can break enrolling a - - resident key (introduced in r1.40) - - OpenBSD-Commit-ID: 4cab364d518470e29e624af3d3f9ffa9c92b6f01 - -commit ff89b1bed80721295555bd083b173247a9c0484e -Author: dtucker@openbsd.org -Date: Fri Aug 19 04:02:46 2022 +0000 - - upstream: Strictly enforce the maximum allowed SSH2 banner size in - - ssh-keyscan and prevent a one-byte buffer overflow. Patch from Qualys, ok - djm@ - - OpenBSD-Commit-ID: 6ae664f9f4db6e8a0589425f74cd0bbf3aeef4e4 - -commit 1b470b9036639cef4f32fb303bb35ea0b711178d -Author: Darren Tucker -Date: Fri Aug 19 15:18:09 2022 +1000 - - Fix cygwin conditional steps. - -commit fd6ee741ab16714b7035d60aca924123ba28135a -Author: Darren Tucker -Date: Fri Aug 19 15:12:57 2022 +1000 - - Add a bit more debug output. - -commit a9305c4c739f4d91a3d3a92c0b6d4949404a36c5 -Author: Darren Tucker -Date: Fri Aug 12 15:08:47 2022 +1000 - - Add Cygwin (on windows-2019) test target. - - In addition to installing the requisite Cygwin packages, we also need to - explicitly invoke "sh" for steps that run other scripts since the runner - environment doesn't understand #! paths. - -commit 5062ad48814b06162511c4f5924a33d97b6b2566 -Author: djm@openbsd.org -Date: Fri Aug 19 03:06:30 2022 +0000 - - upstream: double free() in error path; from Eusgor via GHPR333 - - OpenBSD-Commit-ID: 39f35e16ba878c8d02b4d01d8826d9b321be26d4 - -commit 5a5c580b48fc6006bdfa731fc2f6d4945c2c0e4e -Author: Darren Tucker -Date: Thu Aug 18 21:36:39 2022 +1000 - - Check for perms to run agent-getpeereid test. - - Ubuntu 22.04 defaults to private home dirs which prevents "nobody" - running ssh-add during the agent-getpeereid test. Check for this and - add the necessary permissions. - -commit cd06a76b7ccc706e2bb4f1cc4aa9e9796a28a812 -Author: Damien Miller -Date: Wed Aug 17 16:04:16 2022 +1000 - - on Cygwin, prefer WinHello FIDO device - - If no FIDO device was explictly specified, then prefer the - windows://hello FIDO device. An exception to this is when - probing resident FIDO keys, in which case hardware FIDO - devices are preferred. - -commit 47f72f534ac5cc2cd3027675a3df7b00a8f77575 -Author: djm@openbsd.org -Date: Wed Aug 17 06:01:57 2022 +0000 - - upstream: add an extra flag to sk_probe() to indicate whether we're - - probing for a FIDO resident key or not. Unused here, but will make like - easier for portable - - OpenBSD-Commit-ID: 432c8ff70e270378df9dbceb9bdeaa5b43b5a832 - -commit edb0bcb3c79b16031dc87a8e57aecc3c4a3414f0 -Author: jmc@openbsd.org -Date: Tue Aug 16 20:24:08 2022 +0000 - - upstream: use .Cm for "sign"; from josiah frentsos - - OpenBSD-Commit-ID: 7f80a53d54857ac6ae49ea6ad93c5bd12231d1e4 - -commit cccb011e130cbbac538b1689d10e4a067298df8b -Author: Corinna Vinschen -Date: Thu Aug 11 20:19:35 2022 +0200 - - Revert "check_sk_options: add temporary WinHello workaround" - - Cygwin now comes with libfido2 1.11.0, so this workaround - isn't required anymore. - - This reverts commit 242c044ab111a37aad3b0775727c36a4c5f0102c. - - Signed-off-by: Corinna Vinschen - -commit 9468cd7cf9d989dfa2ac20e2a0268ba6e93bfa5a -Author: Corinna Vinschen -Date: Thu Aug 11 20:18:17 2022 +0200 - - fido_dev_is_winhello: return 0, not "false" - - "false" is not used anywhere in OpenSSH, so return 0 like - everywhere else. - - Signed-off-by: Corinna Vinschen - -commit 730a80609472ee0451c99482d75c9c41f3ebc42d -Author: djm@openbsd.org -Date: Fri Aug 12 05:20:28 2022 +0000 - - upstream: sftp-server: support home-directory request - - Add support to the sftp-server for the home-directory extension defined - in draft-ietf-secsh-filexfer-extensions-00. This overlaps a bit with the - existing expand-path@openssh.com, but uses a more official protocol name, - and so is a bit more likely to be implemented by non-OpenSSH clients. - - From Mike Frysinger, ok dtucker@ - - OpenBSD-Commit-ID: bfc580d05cc0c817831ae7ecbac4a481c23566ab - -commit 5e820bf79ce3ce99ef7e98b0ab642b0a0a4f396c -Author: Darren Tucker -Date: Fri Aug 12 14:56:55 2022 +1000 - - Replace deprecated ubuntu-18.04 runners with 22.04 - -commit 87b0d9c1b789d3ff958ec45df2ac912e24461bae -Author: Darren Tucker -Date: Thu Aug 11 22:48:23 2022 +1000 - - Add a timegm implementation from Heimdal via Samba. - - Fixes build on (at least Solaris 10). - -commit d0c4fa58594577994921b593f10037c5282597ca -Author: Darren Tucker -Date: Thu Aug 11 14:23:58 2022 +1000 - - Rerun tests if any .github config file changes. - -commit 113fe6c77ab43769fc61e953d07cb619fd7ea54b -Author: Darren Tucker -Date: Thu Aug 11 13:33:51 2022 +1000 - - Skip hostbased during Valgrind tests. - - Valgrind doesn't let ssh exec ssh-keysign (because it's setuid) so skip - it during the Valgrind based tests. - - See https://bugs.kde.org/show_bug.cgi?id=119404 for a discussion of this - (ironically there the problematic binary was ssh(1) back when it could - still be setuid). - -commit b98a42afb69d60891eb0488935990df6ee571c4d -Author: djm@openbsd.org -Date: Thu Aug 11 01:57:50 2022 +0000 - - upstream: add some tests for parse_absolute_time(), including cases - - where it is forced to the UTC timezone. bz3468 ok dtucker - - OpenBSD-Regress-ID: ea07ca31c2f3847a38df028ca632763ae44e8759 - -commit ec1ddb72a146fd66d18df9cd423517453a5d8044 -Author: djm@openbsd.org -Date: Thu Aug 11 01:56:51 2022 +0000 - - upstream: allow certificate validity intervals, sshsig verification - - times and authorized_keys expiry-time options to accept dates in the UTC time - zone in addition to the default of interpreting them in the system time zone. - YYYYMMDD and YYMMDDHHMM[SS] dates/times will be interpreted as UTC if - suffixed with a 'Z' character. - - Also allow certificate validity intervals to be specified in raw - seconds-since-epoch as hex value, e.g. -V 0x1234:0x4567890. This - is intended for use by regress tests and other tools that call - ssh-keygen as part of a CA workflow. - - bz3468 ok dtucker - - OpenBSD-Commit-ID: 454db1cdffa9fa346aea5211223a2ce0588dfe13 - -commit 4df246ec75751da7eb925e1880498300d8bda187 -Author: Darren Tucker -Date: Thu Aug 11 10:23:55 2022 +1000 - - Fix conditional for running hostbased tests. - -commit 2580916e48721802220c61ce9e0df1297c00bc07 -Author: Damien Miller -Date: Thu Aug 11 08:58:28 2022 +1000 - - fix SANDBOX_SECCOMP_FILTER_DEBUG - -commit fdbd5bf507fc271ff813714fab8a72ff2c6cb5ca -Author: Darren Tucker -Date: Wed Aug 10 17:35:52 2022 +1000 - - Test hostbased auth on github runners. - -commit 7e2f51940ba48a1c0fae1107801ea643fa83c971 -Author: Darren Tucker -Date: Wed Aug 10 17:25:24 2022 +1000 - - Rename our getentropy to prevent possible loops. - - Since arc4random seeds from getentropy, and we use OpenSSL for that - if enabled, there's the possibility that if we build on a system that - does not have getentropy then run on a system that does have it, then - OpenSSL could end up calling our getentropy and getting stuck in a loop. - Pointed out by deraadt@, ok djm@ - -commit 7a01f61be8d0aca0e975e7417f26371495fe7674 -Author: Darren Tucker -Date: Mon Aug 8 12:17:04 2022 +1000 - - Actually put HAVE_STDINT_H around the stdint.h. - -commit 73541f29f0b50480da6c20dceb7a7191bd8ea7d3 -Author: Darren Tucker -Date: Mon Aug 8 10:30:34 2022 +1000 - - Give unused param a name. - - Fixes builds on platforms that do have fido2 but don't have - fido_dev_is_winhello. - -commit 2a108c0ea960381bd9b14ee0d84e818a23df4482 -Author: djm@openbsd.org -Date: Fri Aug 5 05:01:40 2022 +0000 - - upstream: don't prompt for FIDO passphrase before attempting to enroll - - the credential, just let the enroll operating fail and we'll attempt to get a - PIN anyway. Might avoid some unneccessary PIN prompts. - - Part of GHPR#302 from Corinna Vinschen; ok dtucker@ - - OpenBSD-Commit-ID: bd5342ffc353ee37d39617906867c305564d1ce2 - -commit 2886975c0ad9244e60dc5e4be34fde3aa573a4b5 -Author: Corinna Vinschen -Date: Fri Feb 11 14:33:41 2022 +0100 - - sk_sign: set FIDO2 uv attribute explicitely for WinHello - - WinHello via libfido2 performs user verification by default. - However, if we stick to that, there's no way to differentiate - between keys created with or without "-O verify-required". - Set FIDO2 uv attribute explicitely to FIDO_OPT_FALSE, then check - if user verification has been requested. - - Signed-off-by: Corinna Vinschen - -commit 242c044ab111a37aad3b0775727c36a4c5f0102c -Author: Corinna Vinschen -Date: Tue Feb 15 11:28:08 2022 +0100 - - check_sk_options: add temporary WinHello workaround - - Up to libfido 1.10.0, WinHello advertises "clientPin" rather - than "uv" capability. This is fixed in 1.11.0. For the time - being, workaround it here. - - Signed-off-by: Corinna Vinschen - -commit 78774c08cc4b4997382975b0f414a86e06b6780c -Author: Corinna Vinschen -Date: Thu Feb 10 18:19:29 2022 +0100 - - compat code for fido_dev_is_winhello() - - Signed-off-by: Corinna Vinschen - -commit 3d3a932a019aedfb891e0779bb4990cd5008a390 -Author: Darren Tucker -Date: Fri Aug 5 13:12:27 2022 +1000 - - Factor out getrnd() and rename to getentropy(). - - Factor out the arc4random seeding into its own file and change the - interface to match getentropy. Use native getentropy if available. - This will make it easier to resync OpenBSD changes to arc4random. - Prompted by bz#3467, ok djm@. - -commit 9385d277b787403be9dfcb229cf372202496d2f3 -Author: Darren Tucker -Date: Thu Aug 4 18:55:48 2022 +1000 - - Include CHANNEL and FIDO2 libs in configure output - -commit 141535b904b6fba01724444f38193a8599201f82 -Author: djm@openbsd.org -Date: Mon Aug 1 11:09:26 2022 +0000 - - upstream: avoid double-free in error path introduced in r1.70; report - - and fix based on GHPR#332 by v-rzh ok dtucker@ - - OpenBSD-Commit-ID: 3d21aa127b1f37cfc5bdc21461db369a663a951f - -commit dba7099ffcba3ca07b3946f017ba6a4c3158d9b1 -Author: Darren Tucker -Date: Wed Jul 27 18:40:12 2022 +1000 - - Remove deprecated MacOS 10.15 runners. - -commit 722a56439aa5972c830e4a9a724cf52aff4a950a -Author: Darren Tucker -Date: Wed Jul 27 18:31:14 2022 +1000 - - Move stale-configure check as early as possible. - - We added a check in Makefile to catch the case where configure needs to - be rebuilt, however this did not happen until a build was attempted in - which case all of the work done by configure was wasted. Move this check - to the start of configure to catch it as early as possible. ok djm@ - -commit 099d6b56288b421ba38531d26dc1bd6bb685e311 -Author: Darren Tucker -Date: Fri Jul 22 10:47:19 2022 +1000 - - Move libcrypto into CHANNELLIBS. - - This will result in sftp, sftp-server and scp no longer being linked - against libcrypto. ok djm@ - -commit 1bdf86725b77733bb5f17c54888b88a10b2f6538 -Author: Darren Tucker -Date: Fri Jul 22 10:45:47 2022 +1000 - - Remove seed_rng calls from scp, sftp, sftp-server. - - These binaries don't use OpenSSL's random functions. The next step - will be to stop linking them against libcrypto. ok djm@ - -commit d73f77b8cb9b422f1ac4facee7890aa10ff2bc21 -Author: Darren Tucker -Date: Fri Jul 22 09:51:51 2022 +1000 - - Group libcrypto and PRNGD checks together. - - They're related more than the libcrypt or libiaf checks which are - currently between them. ok djm@ - -commit f117e372b3f42f2fbdb0a578d063b2609ab58e1f -Author: Darren Tucker -Date: Fri Jul 22 09:24:45 2022 +1000 - - Do not link scp, sftp and sftp-server w/ zlib. - - Some of our binaries (eg sftp, sftp-server, scp) do not interact with - the channels code and thus do use libraries such as zlib and libcrypto - although they are linked with them. This adds a CHANNELLIBS and starts - by moving zlib into it, which means the aformentioned binaries are no - longer linked against zlib. ok djm@ - -commit 800c2483e68db38bd1566ff69677124be974aceb -Author: Darren Tucker -Date: Mon Jul 25 21:49:04 2022 +1000 - - Remove workarounds for OpenSSL missing AES-CTR. - - We have some compatibility hacks that were added to support OpenSSL - versions that do not support AES CTR mode. Since that time, however, - the minimum OpenSSL version that we support has moved to 1.0.1 which - *does* have CTR, so this is no longer needed. ok djm@ - -commit b7c56b65c12f51fe0dbae798d19c8f58224a5d95 -Author: Darren Tucker -Date: Mon Jul 25 21:43:00 2022 +1000 - - Remove workarounds for OpenSSL missing AES-GCM. - - We have some compatibility hacks that were added to support OpenSSL - versions that do not support AES GCM mode. Since that time, however, - the minimum OpenSSL version that we support has moved to 1.0.1 which - *does* have GCM, so this is no longer needed. ok djm@ - -commit 5a4a9f7a968fbf92cc1eac519c65638e79ae9f1f -Author: dtucker@openbsd.org -Date: Mon Jul 25 07:12:45 2022 +0000 - - upstream: Restore missing "!" in TEST_SSH_ELAPSED_TIMES test. - - OpenBSD-Regress-ID: 38783f9676ec348c5a792caecee9a16e354b37b0 - -commit 0ff886be132299386cc29d87c2aa16ff68a1aa08 -Author: dtucker@openbsd.org -Date: Sun Jul 24 23:29:10 2022 +0000 - - upstream: Test TEST_SSH_ELAPSED_TIMES for empty string not - - executable. No-op on most platforms but should prevent warnings in -portable - on systems that don't have 'date %s'. - - OpenBSD-Regress-ID: e39d79867b8065e33d0c5926fa1a31f85659d2a4 - -commit f69319ad8ad1dd50f90bbcf5912e11cc8ed3e037 -Author: Darren Tucker -Date: Sat Jul 23 14:38:22 2022 +1000 - - Convert "have_prog" function into "which". - - "which" and its behaviour is not standardized, so convert the existing - have_prog function into "which" so we can rely on it being available - and what its semantics are. Add a have_prog wrapper that maintains the - existing behaviour. - -commit ea7ecc2c3ae39fdf5c6ad97b7bc0b47a98847f43 -Author: Darren Tucker -Date: Sat Jul 23 14:36:38 2022 +1000 - - Skip scp3 test if there's no scp on remote path. - - scp -3 ends up using the scp that's in the remote path and will fail if - one is not available. Based on a patch from rapier at psc.edu. - -commit c46f6fed419167c1671e4227459e108036c760f8 -Author: Damien Miller -Date: Wed Jul 20 13:39:14 2022 +1000 - - crank SSH_SK_VERSION_MAJOR in sk-dummy.so - -commit f208e3b9ffb5ee76cf9c95df7ff967adc7f51c7d -Author: djm@openbsd.org -Date: Wed Jul 20 03:33:22 2022 +0000 - - upstream: ssh-keygen: fix touch prompt, pin retries; - - part of GHPR329 from Pedro Martelletto - - OpenBSD-Commit-ID: 75d1005bd2ef8f29fa834c90d2684e73556fffe8 - -commit 8638a2ce7e90c8a51d9af3143404282126c524f8 -Author: djm@openbsd.org -Date: Wed Jul 20 03:31:42 2022 +0000 - - upstream: sk-usbhid: preserve error code returned by key_lookup() - - it conveys useful information, such as the supplied pin being wrong. - - Part of GHPR329 from Pedro Martelletto - - OpenBSD-Commit-ID: c0647eb9290f793add363d81378439b273756c1b - -commit 9ab929ca2d820520327b41929372bcb9e261534c -Author: djm@openbsd.org -Date: Wed Jul 20 03:29:14 2022 +0000 - - upstream: when enrolling a resident key on a security token, check - - if a credential with matching application and user ID strings already exists. - if so, prompt the user for confirmation before overwriting the credential. - - patch from Pedro Martelletto via GHPR329 - - NB. cranks SSH_SK_VERSION_MAJOR, so any third-party FIDO middleware - implementations will need to adjust - - OpenBSD-Commit-ID: e45e9f1bf2b2f32d9850669e7a8dbd64acc5fca4 - -commit 5bcfc788b38d5b64e4c347bdc04bd9a01bbc36da -Author: djm@openbsd.org -Date: Wed Jul 20 03:13:04 2022 +0000 - - upstream: pull passphrase reading and confirmation into a separate - - function so it can be used for FIDO2 PINs; no functional change - - OpenBSD-Commit-ID: bf34f76b8283cc1d3f54633e0d4f13613d87bb2f - -commit eb679e2959bdb15454eb94751930eb4c9110da94 -Author: Darren Tucker -Date: Fri Jul 15 21:31:48 2022 +1000 - - Move vmshutdown to first step. - - If a previous run on a physical runner has failed to clean up, the next - run will fail because it'll try to check out the code to a broken - directory mount. Make cleanup the first step. - -commit 46b91b70ff3cb9c147e2875ef5dc609fd64c0c96 -Author: Darren Tucker -Date: Fri Jul 15 20:25:27 2022 +1000 - - Rename bbone test target to ARM. - -commit 751d22cdeffed9fe921db78eedc32a29f9e80510 -Author: Darren Tucker -Date: Fri Jul 15 13:37:29 2022 +1000 - - Add AUDIT_ARCH_PPC to supported seccomp arches. - - Patch from dries.deschout at dodeco.eu. - -commit a061792a6e8d235fc40a9b5d4c22a1762bb75a7b -Author: Darren Tucker -Date: Thu Jul 14 19:20:24 2022 +1000 - - Remove unintended changes. - - I inadvertently included a couple of local changes with the OpenSSL - 3.0.4 change. Revert, anything that should be there will be committed - separately. - -commit 527cb43fa1b4e55df661feabbac51b8e608b6519 -Author: Darren Tucker -Date: Thu Jul 14 11:22:08 2022 +1000 - - Return ERANGE from getcwd() if buffer size is 1. - - If getcwd() is supplied a buffer size of exactly 1 and a path of "/", it - could result in a nul byte being written out of array bounds. POSIX says - it should return ERANGE if the path will not fit in the available buffer - (with terminating nul). 1 byte cannot fit any possible path with its nul, - so immediately return ERANGE in that case. - - OpenSSH never uses getcwd() with this buffer size, and all current - (and even quite old) platforms that we are currently known to work - on have a native getcwd() so this code is not used on those anyway. - Reported by Qualys, ok djm@ - -commit 36857fefd8849c4b0e877cfd9d1eb22f79b76650 -Author: Darren Tucker -Date: Thu Jul 14 10:02:35 2022 +1000 - - Split README.platform into its own line. - - README.platform has general platform-specific information, having it - following text about FIDO2 on the same line could imply that it only - has information about FIDO2. - -commit 00a496c6c14f2d41f2a9365714d494dd5f3aac9f -Author: Darren Tucker -Date: Thu Jul 14 09:56:01 2022 +1000 - - Clarify README.md text. - - Clarify the text about the implications of building without OpenSSL, and - prefix the "configure --help" example command with a "./" so it's likely - to work as-is in more shells. From bz#3461. - -commit f40b52f21fbc52eb513279168a49d3285c65256c -Author: Darren Tucker -Date: Tue Jul 12 19:48:44 2022 +1000 - - Remove special casing of crypt(). - - Configure goes to some lengths to pick crypt() from either libcrypt - or OpenSSL's libcrypto because they can more or less featureful (eg - supporting md5-style passwords). - - OpenSSL removed its crypt() interface in 2002: - https://github.com/openssl/openssl/commit/69deec58 so these hijinks - should no longer be necessary. This also only links sshd with libcrypt - which is the only thing that needs it. ok djm@ - -commit 76f4e48631d7b09fb243b47d7b393d100d3741b7 -Author: Darren Tucker -Date: Wed Jul 13 13:17:47 2022 +1000 - - Only refuse to use OpenSSL 3.0.4 on x86_64. - - The potential RCE only impacts x86_64, so only refuse to use it if we're - targetting a potentially impacted architecture. ok djm@ - -commit e75bbc1d88491fa85e61b2cc8783d4bbd00cd131 -Author: Darren Tucker -Date: Tue Jul 12 14:37:15 2022 +1000 - - Capture stderr output from configure. - -commit d9eaea4bea6271bcee6a2b9428f1271faf2d033b -Author: Darren Tucker -Date: Tue Jul 12 12:54:49 2022 +1000 - - Refuse to use OpenSSL 3.0.4 due to potential RCE. - - OpenSSL has a potential RCE in its RSA implementation (CVE-2022-2274) - so refuse to use that specific version. - -commit fb2f3a61bf3d28fff285524535f7ffcd177c9235 -Author: Darren Tucker -Date: Tue Jul 12 12:54:24 2022 +1000 - - Move unset to before we set anything. - -commit c483a5c0fb8e8b8915fad85c5f6113386a4341ca -Author: Darren Tucker -Date: Wed Jul 6 11:52:54 2022 +1000 - - Test against openssl-3.0.5. - -commit 669a56bcfe73f8b985f2bba476ba834d55253acf -Author: Darren Tucker -Date: Tue Jul 5 18:35:53 2022 +1000 - - Update sanitizer test targets: - - - remove clang-sanitize-memory for now. It takes so long that the test - times out. - - add gcc sanitize-address and sanitize-undefined test targets. - -commit 48cc68b69118b3ce8d07fd4f82e00d58667d5379 -Author: Darren Tucker -Date: Tue Jul 5 16:23:28 2022 +1000 - - Add GCC address sanitizer build/test. - -commit 55c60bdd39b82457e92efa77da8d16cfa6a49391 -Author: Darren Tucker -Date: Tue Jul 5 12:02:33 2022 +1000 - - Move sanitizer logs into regress for collection. - -commit 35ef2b3b6ef198f8574904a45780487ec2f17858 -Author: dtucker@openbsd.org -Date: Mon Jul 4 09:10:31 2022 +0000 - - upstream: Add TEST_REGRESS_CACHE_DIR. - - If set, it is used to cache regress test names that have succeeded and - skip those on a re-run. - - OpenBSD-Regress-ID: a7570dd29a58df59f2cca647c3c2ec989b49f247 - -commit 7394ed80c4de8b228a43c8956cf2fa1b9c6b2622 -Author: Darren Tucker -Date: Sun Jul 3 21:46:44 2022 +1000 - - Add clang sanitizer tests. - -commit bfce0e66b6017a9bfab450b9dc7d4b16f90de817 -Author: Darren Tucker -Date: Sun Jul 3 18:14:09 2022 +1000 - - Skip all rlimit tests when sandboxing disabled. - - The rlimit tests can hang when being run with some compiler sanitizers - so skip all of them if sandbox=no. - -commit 6208d611520f9ea94d5369f9da404b709930029d -Author: Darren Tucker -Date: Sun Jul 3 17:54:49 2022 +1000 - - Move checks for pollfd.fd and nfds_t. - - Move the checks for struct pollfd.fd and nfds_t to before the sandboxing - checks. This groups all the sandbox checks together so we can skip them - all when sandboxing is disabled. - -commit 322964f8f2e9c321e77ebae1e4d2cd0ccc5c5a0b -Author: dtucker@openbsd.org -Date: Fri Jul 1 05:08:23 2022 +0000 - - upstream: Remove leftover line. - - Remove extra line leftover from merge conflict. ok djm@ - - OpenBSD-Commit-ID: 460e2290875d7ae64971a7e669c244b1d1c0ae2e - -commit 7ec81daad0e03a64e8d91c5590960c48c1a899a3 -Author: djm@openbsd.org -Date: Fri Jul 1 04:45:50 2022 +0000 - - upstream: use consistent field names (s/char/byte) - - in format description - - OpenBSD-Commit-ID: 3de33572733ee7fcfd7db33d37db23d2280254f0 - -commit 32e82a392d9f263485effdd606ff5862d289a4a0 -Author: Darren Tucker -Date: Fri Jul 1 13:55:19 2022 +1000 - - Skip select+rlimit check if sandboxing is disabled - - It's not needed in that case, and the test can fail when being built - with some compiler memory sanitizer flags. bz#3441 - -commit 4be7184ebe2a2ccef175983517a35ee06766e1b4 -Author: djm@openbsd.org -Date: Fri Jul 1 03:52:57 2022 +0000 - - upstream: bump up loglevel from debug to info when unable to open - - authorized keys/principals file for errno != ENOENT; bz2042 ok dtucker - - OpenBSD-Commit-ID: e79aa550d91ade6a80f081bda689da24c086d66b - -commit 6c31ba10e97b6953c4f325f526f3e846dfea647a -Author: dtucker@openbsd.org -Date: Fri Jul 1 03:39:44 2022 +0000 - - upstream: Don't leak the strings allocated by order_hostkeyalgs() - - and list_hostkey_types() that are passed to compat_pkalg_proposal(). Part of - github PR#324 from ZoltanFridrich, ok djm@ - - This is a roll-forward of the previous rollback now that the required - changes in compat.c have been done. - - OpenBSD-Commit-ID: c7cd93730b3b9f53cdad3ae32462922834ef73eb - -commit 486c4dc3b83b4b67d663fb0fa62bc24138ec3946 -Author: dtucker@openbsd.org -Date: Fri Jul 1 03:35:45 2022 +0000 - - upstream: Always return allocated strings from the kex filtering so - - that we can free them later. Fix one leak in compat_kex_proposal. Based on - github PR#324 from ZoltanFridrich with some simplications by me. ok djm@ - - OpenBSD-Commit-ID: 9171616da3307612d0ede086fd511142f91246e4 - -commit 96faa0de6c673a2ce84736eba37fc9fb723d9e5c -Author: djm@openbsd.org -Date: Fri Jul 1 00:36:30 2022 +0000 - - upstream: ignore SIGPIPE earlier in main(), specifically before - - muxclient() which performs operations that could cause one; Reported by Noam - Lewis via bz3454, ok dtucker@ - - OpenBSD-Commit-ID: 63d8e13276869eebac6d7a05d5a96307f9026e47 - -commit 33efac790f6b09d54894ba6c3e17dfb08b6fc7e1 -Author: jmc@openbsd.org -Date: Tue Jun 28 06:09:14 2022 +0000 - - upstream: reflect the update to -D arg name in usage(); - - OpenBSD-Commit-ID: abdcde4f92b1ef094ae44210ee99d3b0155aad9c - -commit c71a1442d02f0a3586109dfe2cb366de36dee08e -Author: Darren Tucker -Date: Wed Jun 29 18:28:47 2022 +1000 - - Update OpenSSL tests to the most recent releases. - -commit 2a822f29300b2de7335fbff65f0b187a0c582304 -Author: djm@openbsd.org -Date: Mon Jun 27 21:41:55 2022 +0000 - - upstream: allow arguments to sftp -D option, e.g. sftp -D - - "/usr/libexec/sftp-server -el debug3" - - ok markus@ - - OpenBSD-Commit-ID: 5a002b9f3a7aef2731fc0ffa9c921cf15f38ecce - -commit 2369a2810187e08f2af5d58b343956062fb96ee8 -Author: dtucker@openbsd.org -Date: Fri Jun 24 10:45:06 2022 +0000 - - upstream: Roll back previous KEX changes as they aren't safe until - - compat_pkalg_proposal and friends always allocate their returned strings. - Reported by Qualys. - - OpenBSD-Commit-ID: 1c7a88a0d5033f42f88ab9bec58ef1cf72c81ad0 - -commit 646686136c34c2dbf6a01296dfaa9ebee029386d -Author: dtucker@openbsd.org -Date: Fri Jun 24 04:37:00 2022 +0000 - - upstream: Don't leak the strings allocated by order_hostkeyalgs() - - and list_hostkey_types() that are passed to compat_pkalg_proposal(). Part of - github PR#324 from ZoltanFridrich, ok djm@ - - OpenBSD-Commit-ID: b2f6e5f60f2bba293b831654328a8a0035ef4a1b - -commit 193c6d8d905dde836b628fc07a7b9cf2d347e2a3 -Author: Darren Tucker -Date: Sat Jun 25 12:16:15 2022 +1000 - - Zero out LIBFIDO2 when SK support not usable. - - Prevents us from trying to link them into ssh-sk-helper and failing to - build. - -commit 40f5d849d25c60b4ae21261e78484d435f5cfd51 -Author: Darren Tucker -Date: Sat Jun 25 11:47:28 2022 +1000 - - Disable SK support if FIDO libs not found. - -commit 5fd922ade1b25880fe8a8249f5c0385e413108f9 -Author: Damien Miller -Date: Fri Jun 24 14:43:54 2022 +1000 - - fix broken case statement in previous - -commit f51423bdaf0008d46b6af082bcfd7a22a87375f0 -Author: Damien Miller -Date: Fri Jun 24 14:40:42 2022 +1000 - - request 1.1x API compatibility for OpenSSL >=3.x - - idea/patch from Pedro Martelletto via GHPR#322; ok dtucker@ - -commit 455cee8d6c2e4c48c5af9faead3599c49948411e -Author: djm@openbsd.org -Date: Fri Jun 24 04:27:14 2022 +0000 - - upstream: make it clear that RekeyLimit applies to both transmitted - - and received data. GHPR#328 from Jan Pazdziora - - OpenBSD-Commit-ID: d180a905fec9ff418a75c07bb96ea41c9308c3f9 - -commit 17904f05802988d0bb9ed3c8d1d37411e8f459c3 -Author: tobhe@openbsd.org -Date: Tue Jun 21 14:52:13 2022 +0000 - - upstream: Make sure not to fclose() the same fd twice in case of an - - error. - - ok dtucker@ - - OpenBSD-Commit-ID: e384c4e05d5521e7866b3d53ca59acd2a86eef99 - -commit f29d6cf98c25bf044079032d22c1a57c63ab9d8e -Author: dtucker@openbsd.org -Date: Sat Jun 18 02:17:16 2022 +0000 - - upstream: Don't attempt to fprintf a null identity comment. From - - Martin Vahlensieck via tech@. - - OpenBSD-Commit-ID: 4c54d20a8e8e4e9912c38a7b4ef5bfc5ca2e05c2 - -commit ad1762173bb38716a106e8979806149fd0f2753e -Author: dtucker@openbsd.org -Date: Fri Jun 17 01:00:03 2022 +0000 - - upstream: Log an error if pipe() fails while accepting a - - connection. bz#3447, from vincent-openssh at vinc17 net, ok djm@ - - OpenBSD-Commit-ID: 9d59f19872b94900a5c79da2d57850241ac5df94 - -commit 9c59e7486cc8691401228b43b96a3edbb06e0412 -Author: Damien Miller -Date: Fri Jun 24 14:20:43 2022 +1000 - - automatically enable built-in FIDO support - - If libfido2 is found and usable, then enable the built-in - security key support unless --without-security-key-builtin - was requested. - - ok dtucker@ - -commit 7d25b37fb2a5ff4dadabcbdac6087a97479434f5 -Author: Damien Miller -Date: Fri Jun 24 13:46:39 2022 +1000 - - fix possible NULL deref when built without FIDO - - Analysis/fix from kircher in bz3443; ok dtucker@ - -commit f5ba85daddfc2da6a8dab6038269e02c0695be44 -Author: djm@openbsd.org -Date: Wed Jun 15 16:08:25 2022 +0000 - - upstream: make sure that UseDNS hostname lookup happens in the monitor - - and not in the pledge(2)'d unprivileged process; fixes regression caused by - recent refactoring spotted by henning@ - - OpenBSD-Commit-ID: a089870b95101cd8881a2dff65b2f1627d13e88d - -commit acb2059febaddd71ee06c2ebf63dcf211d9ab9f2 -Author: djm@openbsd.org -Date: Fri Jun 3 04:47:21 2022 +0000 - - upstream: move auth_openprincipals() and auth_openkeyfile() over to - - auth2-pubkeyfile.c too; they make more sense there. - - OpenBSD-Commit-ID: 9970d99f900e1117fdaab13e9e910a621b7c60ee - -commit 3d9b0845f34510111cc693bb99a667662ca50cd8 -Author: djm@openbsd.org -Date: Fri Jun 3 04:31:54 2022 +0000 - - upstream: test setenv in both client and server, test first-match-wins - - too - - OpenBSD-Regress-ID: 4c8804f9db38a02db480b9923317457b377fe34b - -commit 22e1a3a71ad6d108ff0c5f07f93c3fcbd30f8b40 -Author: djm@openbsd.org -Date: Fri Jun 3 04:30:46 2022 +0000 - - upstream: Make SetEnv directives first-match-wins in both - - sshd_config and sshd_config; previously if the same name was reused then the - last would win (which is the opposite to how the config is supposed to work). - - While there, make the ssh_config parsing more like sshd_config. - - bz3438, ok dtucker - - OpenBSD-Commit-ID: 797909c1e0262c0d00e09280459d7ab00f18273b - -commit 38ed6c57e9e592c08e020fa6e82b45b4e1040970 -Author: dtucker@openbsd.org -Date: Fri Jun 3 04:00:15 2022 +0000 - - upstream: Add missing *-sk types to ssh-keyscan manpage. From - - skazi0 via github PR#294. - - OpenBSD-Commit-ID: fda2c869cdb871f3c90a89fb3f985370bb5d25c0 - -commit ea97ec98c41ec2b755dfab459347db674ff9a5de -Author: dtucker@openbsd.org -Date: Fri Jun 3 03:21:09 2022 +0000 - - upstream: Add period at end of "not known by any other names" - - message. github PR#320 from jschauma, ok djm@ - - OpenBSD-Commit-ID: bd60809803c4bfd3ebb7c5c4d918b10e275266f2 - -commit 88e376fcd67478ad1660d94bc73ab348ac9f4527 -Author: dtucker@openbsd.org -Date: Fri Jun 3 03:17:42 2022 +0000 - - upstream: ssh-keygen -A: do not generate DSA keys by default. - - Based on github PR#303 from jsegitz with man page text from jmc@, ok markus@ - djm@ - - OpenBSD-Commit-ID: 5c4c57bdd7063ff03381cfb6696659dd3f9f5b9f - -commit 6b3fb624675082a1e5aa615d1b8479873d8b5731 -Author: naddy@openbsd.org -Date: Tue May 31 14:05:12 2022 +0000 - - upstream: ssh-keygen: implement "verify-required" certificate option. - - This was already documented when support for user-verified FIDO - keys was added, but the ssh-keygen(1) code was missing. - - ok djm@ - - OpenBSD-Commit-ID: f660f973391b593fea4b7b25913c9a15c3eb8a06 - -commit b7f86ffc301be105bba9a3e0618b6fab3ae379bd -Author: jmc@openbsd.org -Date: Sat May 28 05:57:56 2022 +0000 - - upstream: keywords ref ssh_config.5; - - from caspar schutijser - - OpenBSD-Commit-ID: f146a19d7d5c9374c3b9c520da43b2732d7d1a4e - -commit dc7bc52372f2744fa39191577be5306ee57aacd4 -Author: Damien Miller -Date: Mon May 30 09:29:09 2022 +1000 - - fix some bugs in the fuzzer - -commit 1781f507c113667613351c19898efaf1e311a865 -Author: Darren Tucker -Date: Fri May 27 18:19:48 2022 +1000 - - Test against OpenSSL 1.1.1o and 3.0.3. - -commit c53906e0c59e569691b4095d3e8db79cf78fa058 -Author: Darren Tucker -Date: Fri May 27 18:18:31 2022 +1000 - - Test against LibreSSL 3.5.3. - -commit 9b3ad432ad2f19319bcc089370e356c6315d682f -Author: Damien Miller -Date: Fri May 27 17:00:43 2022 +1000 - - fuzzer for authorized_keys parsing - - mostly redundant to authopt_fuzz, but it's sensitive code so IMO it - makes sense to test this layer too - -commit c83d8c4d6f3ccceef84d46de107f6b71cda06359 -Author: djm@openbsd.org -Date: Fri May 27 05:02:46 2022 +0000 - - upstream: split the low-level file handling functions out from - - auth2-pubkey.c - - Put them in a new auth2-pubkeyfile.c to make it easier to refer to them - (e.g. in unit/fuzz tests) without having to refer to everything else - pubkey auth brings in. - - ok dtucker@ - - OpenBSD-Commit-ID: 3fdca2c61ad97dc1b8d4a7346816f83dc4ce2217 - -commit 3b0b142d2a0767d8cd838e2f3aefde8a0aaa41e1 -Author: djm@openbsd.org -Date: Fri May 27 05:01:25 2022 +0000 - - upstream: refactor authorized_keys/principals handling - - remove "struct ssh *" from arguments - this was only used to pass the - remote host/address. These can be passed in instead and the resulting - code is less tightly coupled to ssh_api.[ch] - - ok dtucker@ - - OpenBSD-Commit-ID: 9d4373d013edc4cc4b5c21a599e1837ac31dda0d - -commit 2c334fd36f80cb91cc42e4b978b10aa35e0df236 -Author: dtucker@openbsd.org -Date: Fri May 27 04:29:40 2022 +0000 - - upstream: f sshpkt functions fail, then password is not cleared - - with freezero. Unconditionally call freezero to guarantee that password is - removed from RAM. - - From tobias@ and c3h2_ctf via github PR#286, ok djm@ - - OpenBSD-Commit-ID: 6b093619c9515328e25b0f8093779c52402c89cd - -commit 5d3a77f4c5ae774c6796387266503f52c7cdc7c2 -Author: dtucker@openbsd.org -Date: Fri May 27 04:27:49 2022 +0000 - - upstream: Avoid kill with -1 argument. The out_ctx label can be - - reached before fork has been called. If this happens, then kill -1 would be - called, sending SIGTERM to all processes reachable by the current process. - - From tobias@ and c3h2_ctf via github PR#286, ok djm@ - - OpenBSD-Commit-ID: 6277af1207d81202f5daffdccfeeaed4c763b1a8 - -commit 533b31cd08e4b97f455466f91c36915e2924c15a -Author: dtucker@openbsd.org -Date: Fri May 27 04:13:24 2022 +0000 - - upstream: Note that ProxyJump also accepts the same tokens as - - ProxyCommand. From pallxk via github PR#305. - - OpenBSD-Commit-ID: 7115ac351b129205f1f1ffa6bbfd62abd76be7c5 - -commit 9d8c80f8a304babe61ca28f2e3fb5eb6dc9c39bf -Author: djm@openbsd.org -Date: Wed May 25 06:03:44 2022 +0000 - - upstream: revert previous; it was broken (spotted by Theo) - - OpenBSD-Commit-ID: 457c79afaca2f89ec2606405c1059b98b30d8b0d - -commit 9e0d02ef7ce88b67643bfb1c2272c9f5f04cc680 -Author: djm@openbsd.org -Date: Wed May 25 00:31:13 2022 +0000 - - upstream: make SSHBUF_DBG/SSHBUF_TELL (off by default and only enabled - - via #define) dump to stderr rather than stdout - - OpenBSD-Commit-ID: 10298513ee32db8390aecb0397d782d68cb14318 - -commit 2487163630f28be28b7e2396b4bd6511b98f1d3e -Author: Tim Rice -Date: Tue May 24 10:21:25 2022 -0700 - - configure.ac: Add missing AC_DEFINE for caph_cache_tzdata test causing - HAVE_CAPH_CACHE_TZDATA to be missing from config.h.in. - Spotted by Bryan Drewery - -commit bedb93415b60db3dfd704a3d525e82adb14a2481 -Author: djm@openbsd.org -Date: Sun May 15 23:48:07 2022 +0000 - - upstream: regress test for in-place transfers and clobbering larger - - files with smaller ones; would have caught last regression in scp(1) - - OpenBSD-Regress-ID: 19de4e88dd3a4f7e5c1618c9be3c32415bd93bc2 - -commit b4f0d719c2548cb74da509fb65f384dada4ebd37 -Author: anton@openbsd.org -Date: Fri Apr 22 05:08:43 2022 +0000 - - upstream: Only run agent-ptrace.sh if gdb is available as all - - architectures do not ship with gdb. - - OpenBSD-Regress-ID: ec53e928803e6b87f9ac142d38888ca79a45348d - -commit 9b73345f80255a7f3048026462f2c0c6a241eeac -Author: djm@openbsd.org -Date: Sun May 15 23:47:21 2022 +0000 - - upstream: fix in-place copies; r1.163 incorrectly skipped truncation in - - all cases, not just at the start of a transfer. This could cause overwrites - of larger files to leave junk at the end. Spotted by tb@ - - OpenBSD-Commit-ID: b189f19cd68119548c8e24e39c79f61e115bf92c - -commit 56a0697fe079ff3e1ba30a2d5c26b5e45f7b71f8 -Author: djm@openbsd.org -Date: Fri May 13 06:31:50 2022 +0000 - - upstream: arrange for scp, when in sftp mode, to not ftruncate(3) files - - early - - previous behavious of unconditionally truncating the destination file - would cause "scp ~/foo localhost:" and "scp localhost:foo ~/" to - delete all the contents of their destination. - - spotted by solene@ sthen@, also bz3431; ok dtucker@ - - OpenBSD-Commit-ID: ca39fdd39e0ec1466b9666f15cbcfddea6aaa179 - -commit fbcef70c2832712f027bccea1aa9bc4b4103da93 -Author: dtucker@openbsd.org -Date: Mon May 9 08:25:27 2022 +0000 - - upstream: Remove errant apostrophe. From haruyama at queen-ml org. - - OpenBSD-Commit-ID: dc6b294567cb84b384ad6ced9ca469f2bbf0bd10 - -commit 0086a286ea6bbd11ca9b664ac3bb12b27443d6eb -Author: djm@openbsd.org -Date: Mon May 9 03:09:53 2022 +0000 - - upstream: Allow existing -U (use agent) flag to work with "-Y sign" - - operations, where it will be interpreted to require that the private keys is - hosted in an agent; bz3429, suggested by Adam Szkoda; ok dtucker@ - - OpenBSD-Commit-ID: a7bc69873b99c32c42c7628ed9ea91565ba08c2f - -commit cb010744cc98f651b1029bb09efa986eb54e4ccf -Author: djm@openbsd.org -Date: Sun May 8 22:58:35 2022 +0000 - - upstream: improve error message when 'ssh-keygen -Y sign' is unable to - - load a private key; bz3429, reported by Adam Szkoda ok dtucker@ - - OpenBSD-Commit-ID: bb57b285e67bea536ef81b1055467be2fc380e74 - -commit aa61fc82c63d309a90c22ca74fb1da6c6f4372fd -Author: Tobias Heider -Date: Mon May 9 02:00:01 2022 +0200 - - Remove duplicate bcrypt_pbkdf.o from Makefile - - bcrypt_pbkdf.o is duplicated in the openbsd-compat Makefile's object - file list. - -commit deb506d00da8d11fb04c1e7b9b1e1cc379c1705c -Author: djm@openbsd.org -Date: Sun May 8 22:32:36 2022 +0000 - - upstream: When performing operations that glob(3) a remote path, ensure - - that the implicit working directory used to construct that path escapes - glob(3) characters. - - This prevents glob characters from being processed in places they - shouldn't, e.g. "cd /tmp/a*/", "get *.txt" should have the get operation - treat the path "/tmp/a*" literally and not attempt to expand it. - - Reported by Lusia Kundel; ok markus@ - - OpenBSD-Commit-ID: 4f647f58482cbad3d58b1eab7f6a1691433deeef - -commit f38cf74f20b5da113cfa823afd5bfb5c6ba65f3d -Author: Darren Tucker -Date: Fri May 6 14:50:18 2022 +1000 - - Also retest OpenBSD upstream on .yml changes. - -commit f87a132800ba3710ab130d703448a31ef1128d77 -Author: Darren Tucker -Date: Fri May 6 14:46:09 2022 +1000 - - Note that, for now, we need variadic macros. - -commit 217b518e0f7c52c4b909e935141a55344c61e644 -Author: Darren Tucker -Date: Fri May 6 14:39:34 2022 +1000 - - Add ubsan minimal testcase on OpenBSD. - - As suggested by djm@. - -commit 457dce2cfef6a48f5442591cd8b21c7e8cba13f8 -Author: djm@openbsd.org -Date: Thu May 5 01:04:14 2022 +0000 - - upstream: sshkey_unshield_private() contains a exact duplicate of - - the code in private2_check_padding(). Pull private2_check_padding() up so the - code can be reused. From Martin Vahlensieck, ok deraadt@ - - OpenBSD-Commit-ID: 876884c3f0e62e8fd8d1594bab06900f971c9c85 - -commit 0e44db4d9cb313e68a59a44d27884af66c02356e -Author: djm@openbsd.org -Date: Thu May 5 00:56:58 2022 +0000 - - upstream: channel_new no longer frees remote_name. So update the - - comment accordingly. As remote_name is not modified, it can be const as - well. From Martin Vahlensieck - - OpenBSD-Commit-ID: e4e10dc8dc9f40c166ea5a8e991942bedc75a76a - -commit 37b62fd5caf19c85a48241535277cefff65adace -Author: djm@openbsd.org -Date: Thu May 5 00:55:11 2022 +0000 - - upstream: mux.c: mark argument as const; from Martin Vahlensieck - - OpenBSD-Commit-ID: 69a1a93a55986c7c2ad9f733c093b46a47184341 - -commit f4e67c0ad259b4cf10177277a5827fa5545bac53 -Author: markus@openbsd.org -Date: Wed May 4 07:31:22 2022 +0000 - - upstream: make sure stdout is non-blocking; ok djm@ - - OpenBSD-Commit-ID: 64940fffbd1b882eda2d7c8c7a43c79368309c0d - -commit e5c036d2092c00bef395e9161dc5ce42d4be9565 -Author: florian@openbsd.org -Date: Tue May 3 07:42:27 2022 +0000 - - upstream: Add FIDO AUTHENTICATOR section and explain a bit how FIDO - - works. The wording came mostly from the 8.2 OpenSSH release notes, addapted - to fit the man page. Then move the -O bits into the new section as is already - done for CERTIFICATES and MODULI GENERATION. Finally we can explain the - trade-offs of resident keys. While here, consistently refer to the FIDO - thingies as "FIDO authenticators", not "FIDO tokens". - - input & OK jmc, naddy - - OpenBSD-Commit-ID: dd98748d7644df048f78dcf793b3b63db9ab1d25 - -commit 575771bf79bef7127be6aaccddc46031ea15529e -Author: jmc@openbsd.org -Date: Mon May 2 05:40:37 2022 +0000 - - upstream: remove an obsolete rsa1 format example from an example; - - from megan batty - ok djm - - OpenBSD-Commit-ID: db2c89879c29bf083df996bd830abfb1e70d62bf - -commit 0bc6b4c8f04e292577bdb44d5dc6b630d3448087 -Author: djm@openbsd.org -Date: Sun May 1 23:20:30 2022 +0000 - - upstream: fix some integer overflows in sieve_large() that show up when - - trying to generate modp groups > 16k bits. Reported via GHPR#306 by Bertram - Felgenhauer, but fixed in a different way. feedback/ok tb@ - - OpenBSD-Commit-ID: 81cbc6dd3a21c57bd6fadea10e44afe37bca558e - -commit a45615cb172bc827e21ec76750de39dfb30ecc05 -Author: djm@openbsd.org -Date: Fri Apr 29 04:55:07 2022 +0000 - - upstream: be stricter in which characters will be accepted in - - specifying a mask length; allow only 0-9. From khaleesicodes via GHPR#278; ok - dtucker@ - - OpenBSD-Commit-ID: e267746c047ea86665cdeccef795a8a56082eeb2 - -commit 4835544d2dd31de6ffc7dba59f92093aea98155b -Author: Darren Tucker -Date: Sat Apr 30 10:56:41 2022 +1000 - - Add Mac OS X 12 test target. - -commit 97a6a8b8c1f2da09712d0e72d0ef800e4edd34cd -Author: Darren Tucker -Date: Fri Apr 29 18:27:34 2022 +1000 - - Only run tests when source files change. - - Also run tests on changes to V_9_0 branch. - -commit 6d0392b9ff4b50a56ac5685d1b9392e2cd432ca3 -Author: Darren Tucker -Date: Fri Apr 29 18:22:34 2022 +1000 - - Remove now-empty int32_minmax.inc. - -commit af59463553b5ad52d3b42c4455ee3c5600158bb7 -Author: djm@openbsd.org -Date: Fri Apr 29 03:24:30 2022 +0000 - - upstream: mention that the helpers are used by ssh(1), ssh-agent(1) - - and ssh-keygen(1). Previously only ssh(1) was mentioned. From Pedro - Martelletto - - OpenBSD-Commit-ID: 30f880f989d4b329589c1c404315685960a5f153 - -commit 3e26b3a6eebcee27be177207cc0846fb844b7a56 -Author: dtucker@openbsd.org -Date: Fri Apr 29 03:16:48 2022 +0000 - - upstream: Don't leak SK device. Patch from Pedro Martelletto via - - github PR#316. ok djm@ - - OpenBSD-Commit-ID: 17d11327545022e727d95fd08b213171c5a4585d - -commit 247082b5013f0d4fcae8f97453f2a2f01bcda811 -Author: djm@openbsd.org -Date: Fri Apr 29 03:13:32 2022 +0000 - - upstream: fix memleak on session-bind path; from Pedro Martelletto, ok - - dtucker@ - - OpenBSD-Commit-ID: e85899a26ba402b4c0717b531317e8fc258f0a7e - -commit e05522008092ceb86a87bdd4ad7878424315db89 -Author: djm@openbsd.org -Date: Thu Apr 28 02:53:31 2022 +0000 - - upstream: avoid printing hash algorithm twice; from lucas AT sexy.is - - OpenBSD-Commit-ID: 9d24671e10a84141b7c504396cabad600e47a941 - -commit 0979e29356915261d69a9517a1e0aaade7c9fc75 -Author: dtucker@openbsd.org -Date: Wed Apr 27 11:08:55 2022 +0000 - - upstream: Add authfd path to debug output. ok markus@ - - OpenBSD-Commit-ID: f735a17d1a6f2bee63bfc609d76ef8db8c090890 - -commit 67b7c784769c74fd4d6b147d91e17e1ac1a8a96d -Author: dtucker@openbsd.org -Date: Tue Apr 26 07:41:44 2022 +0000 - - upstream: Check sshauthopt_new() for NULL. bz#3425, from - - tessgauthier at microsoft.com. ok djm@ - - OpenBSD-Commit-ID: af0315bc3e44aa406daa7e0ae7c2d719a974483f - -commit d571314d14b919fbd7c84a61f9bf2065fc0a6841 -Author: millert@openbsd.org -Date: Wed Apr 20 16:00:25 2022 +0000 - - upstream: Remove unnecessary includes: openssl/hmac.h and - - openssl/evp.h. From Martin Vahlensieck. - - OpenBSD-Commit-ID: a6debb5fb0c8a44e43e8d5ca7cc70ad2f3ea31c3 - -commit da8dddf8cc1f2516ff894b8183e83a7c5ba3ef80 -Author: millert@openbsd.org -Date: Wed Apr 20 15:59:18 2022 +0000 - - upstream: Add missing includes of stdlib.h and stdint.h. We need - - stdlib.h for malloc(3) and stdint.h for SIZE_MAX. Unlike the other xmss - files, ssh-xmss.c does not include xmss_commons.h so ssh-xmss.c must include - those headers itself. From Martin Vahlensieck - - OpenBSD-Commit-ID: 70e28a9818cee3da1be2ef6503d4b396dd421e6b - -commit fe9d87a6800a7a33be08f4d5ab662a758055ced2 -Author: millert@openbsd.org -Date: Wed Apr 20 15:56:49 2022 +0000 - - upstream: Avoid an unnecessary xstrdup in rm_env() when matching - - patterns. Since match_pattern() doesn't modify its arguments (they are - const), there is no need to make an extra copy of the strings in - options->send_env. From Martin Vahlensieck - - OpenBSD-Commit-ID: 2c9db31e3f4d3403b49642c64ee048b2a0a39351 - -commit 7bf2eb958fbb551e7d61e75c176bb3200383285d -Author: Darren Tucker -Date: Tue Apr 26 23:30:59 2022 +1000 - - Add debian-riscv64 test target. - -commit 3913c935523902482974c4c503bcff20bd850a6a -Author: Darren Tucker -Date: Mon Apr 25 17:20:06 2022 +1000 - - Update OpenSSL and LibreSSL versions in tests. - -commit dcd8dca29bcdb193ff6be35b96fc55e6e30d37d9 -Author: Darren Tucker -Date: Sat Apr 23 20:40:28 2022 +1000 - - Include stdlib.h for free() prototype. - - ... which is used inside the CUSTOM_SYS_AUTH_GET_LASTLOGIN_MSG block. - -commit 4cc05de568e1c3edd7834ff3bd9d8214eb34861b -Author: Darren Tucker -Date: Sat Apr 23 20:17:26 2022 +1000 - - Cache timezone data in capsicum sandbox. - - From emaste at freebsd.org, originally part of FreeBSD commit r339216 - / fc3c19a9 with autoconf bits added by me. - -commit c31404426d212e2964ff9e5e58e1d0fce3d83f27 -Author: dtucker@openbsd.org -Date: Thu Apr 21 01:36:46 2022 +0000 - - upstream: It looks like we can't completely avoid - - waiting for processes to exit so retrieve the pid via controlmaster and - use that. - - OpenBSD-Regress-ID: 8246f00f22b14e49d2ff1744c94897ead33d457b - -commit d19b21afab5c8e2f3df6bd8aee9766bdad3d8c58 -Author: dtucker@openbsd.org -Date: Wed Apr 20 13:25:55 2022 +0000 - - upstream: Use ssh -f and ControlPersist .. - - to start up test forwards and ssh -O stop to shut them down intead of - sleep loops. This speeds up the test by an order of magnitude. - - OpenBSD-Regress-ID: eb3db5f805100919b092a3b2579c611fba3e83e7 - -commit 5f76286a126721fa005de6edf3d1c7a265555f19 -Author: dtucker@openbsd.org -Date: Wed Apr 20 05:24:13 2022 +0000 - - upstream: Simplify forward-control test. - - Since we no longer need to support SSH1 we don't need to run shell - commands on the other end of the connection and can use ssh -N instead. - This also makes the test less racy. - - OpenBSD-Regress-ID: 32e94ce272820cc398f30b848b2b0f080d10302c - -commit 687bbf23572d8bdf25cbbcdf8ac583514e1ba710 -Author: djm@openbsd.org -Date: Thu Mar 31 03:07:33 2022 +0000 - - upstream: regression test for sftp cp command - - OpenBSD-Regress-ID: c96bea9edde3a384b254785e7f9b2b24a81cdf82 - -commit f1233f19a6a9fe58f52946f50df4772f5b136761 -Author: dtucker@openbsd.org -Date: Wed Apr 20 01:13:47 2022 +0000 - - upstream: Import regenerated moduli - - OpenBSD-Commit-ID: f9a0726d957cf10692a231996a1f34e7f9cdfeb0 - -commit fec014785de198b9a325d1b94e324bb958c5fe7b -Author: djm@openbsd.org -Date: Wed Apr 20 04:19:11 2022 +0000 - - upstream: Try to continue running local I/O for channels in state - - OPEN during SSH transport rekeying. The most visible benefit is that it - should make ~-escapes work in the client (e.g. to exit) if the connection - happened to have stalled during a rekey event. Based work by and ok dtucker@ - - OpenBSD-Commit-ID: a66e8f254e92edd4ce09c9f750883ec8f1ea5f45 - -commit e68154b0d4f0f5085a050ea896955da1b1be6e30 -Author: dtucker@openbsd.org -Date: Wed Apr 20 01:13:47 2022 +0000 - - upstream: Import regenerated moduli - - OpenBSD-Commit-ID: f9a0726d957cf10692a231996a1f34e7f9cdfeb0 - -commit 69928b106d8f0fa15b88cf3850d992ed81c44ae0 -Author: tj@openbsd.org -Date: Sat Apr 16 00:22:31 2022 +0000 - - upstream: list the correct version number - - for when usage of the sftp protocol became default and fix a typo - from ed maste - - OpenBSD-Commit-ID: 24e1795ed2283fdeacf16413c2f07503bcdebb31 - -commit 21042a05c0b304c16f655efeec97438249d2e2cc -Author: dtucker@openbsd.org -Date: Tue Apr 12 05:09:49 2022 +0000 - - upstream: Correct path for system known hosts file in description - - of IgnoreUserKnownHosts. Patch from Martin Vahlensieck via tech@ - - OpenBSD-Commit-ID: 9b7784f054fa5aa4d63cb36bd563889477127215 - -commit 53f4aff60a7c1a08a23917bd47496f8901c471f5 -Author: Darren Tucker -Date: Sat Apr 16 14:33:20 2022 +1000 - - Resync moduli.5 with upstream. - - 1.18: remove duplicate publication year; carsten dot kunze at arcor dot de - 1.19: ssh-keygen's -G/-T have been replaced with -M generate/screen. - -commit d2b888762b9844eb0d8eb59909cdf5af5159f810 -Author: Darren Tucker -Date: Sat Apr 16 14:31:13 2022 +1000 - - Retire fbsd6 test VM. - - It's long since out of support, relatively slow (it's i686) and the - compiler has trouble with PIE. - -commit cd1f70009860a154b51230d367c55ea5f9a4504e -Author: djm@openbsd.org -Date: Mon Apr 11 22:52:08 2022 +0000 - - upstream: clear io_want/io_ready flags at start of poll() cycle; - - avoids plausible spin during rekeying if channel io_want flags are reused - across cycles. ok markus@ deraadt@ - - OpenBSD-Commit-ID: 91034f855b7c73cd2591657c49ac30f10322b967 - -commit aa1920302778273f7f94c2091319aba199068ca0 -Author: dtucker@openbsd.org -Date: Fri Apr 8 05:43:39 2022 +0000 - - upstream: Note that curve25519-sha256 was later published in - - RFC8731. ok djm@ - - OpenBSD-Commit-ID: 2ac2b5d642d4cf5918eaec8653cad9a4460b2743 - -commit 4673fa8f2be983f2f88d5afd754adb1a2a39ec9e -Author: djm@openbsd.org -Date: Fri Apr 8 04:40:40 2022 +0000 - - upstream: two defensive changes from Tobias Stoeckmann via GHPR287 - - enforce stricter invarient for sshbuf_set_parent() - never allow - a buffer to have a previously-set parent changed. - - In sshbuf_reset(), if the reallocation fails, then zero the entire - buffer and not the (potentially smaller) default initial alloc size. - - OpenBSD-Commit-ID: 14583203aa5d50ad38d2e209ae10abaf8955e6a9 - -commit 26eef015e2d2254375e13afaaf753b78932b1bf5 -Author: Damien Miller -Date: Mon Apr 11 16:07:09 2022 +1000 - - Revert "update build-aux files to match autoconf-2.71" - - This reverts commit 0a8ca39fac6ad19096b6c263436f8b2dd51606f2. - - It turns out that the checked-in copies of these files are actually newer - than autoconf-2.71's copies, so this was effectively a downgrade. - Spotted by Bo Anderson via github - -commit 0a8ca39fac6ad19096b6c263436f8b2dd51606f2 -Author: Damien Miller -Date: Fri Apr 8 14:48:58 2022 +1000 - - update build-aux files to match autoconf-2.71 - - i.e. config.guess, config.sub and install-sh - -commit 94eb6858efecc1b4f02d8a6bd35e149f55c814c8 -Author: Damien Miller -Date: Wed Apr 6 10:47:48 2022 +1000 - - update version numbers for release - -commit 8e4a8eadf4fe74e65e6492f34250f8cf7d67e8da -Author: djm@openbsd.org -Date: Mon Apr 4 22:45:25 2022 +0000 - - upstream: openssh-9.0 - - OpenBSD-Commit-ID: 0dfb461188f4513ec024c1534da8c1ce14c20b64 - -commit a9f23ea2e3227f406880c2634d066f6f50fa5eaa -Author: naddy@openbsd.org -Date: Thu Mar 31 17:58:44 2022 +0000 - - upstream: ssh: document sntrup761x25519-sha512@openssh.com as - - default KEX - - OpenBSD-Commit-ID: 12545bfa10bcbf552d04d9d9520d0f4e98b0e171 - -commit 9ec2713d122af79d66ebb9c1d6d9ae8621a8945f -Author: naddy@openbsd.org -Date: Thu Mar 31 17:27:27 2022 +0000 - - upstream: man pages: add missing commas between subordinate and - - main clauses - - jmc@ dislikes a comma before "then" in a conditional, so leave those - untouched. - - ok jmc@ - - OpenBSD-Commit-ID: 9520801729bebcb3c9fe43ad7f9776ab4dd05ea3 - -commit 3741df98ffaaff92b474ee70d8ef276b5882f85a -Author: Darren Tucker -Date: Mon Apr 4 23:52:11 2022 +1000 - - Disable security key on fbsd6 test host. - -commit 32c12236f27ae83bfe6d2983b67c9bc67a83a417 -Author: Darren Tucker -Date: Mon Apr 4 15:16:51 2022 +1000 - - Specify TEST_SHELL=bash on AIX. - - The system shells cause the agent-restrict test to fail due to some - quoting so explicitly specify bash until we can get configure to - autmatically work around that. - -commit 90452c8b69d065b7c7c285ff78b81418a75bcd76 -Author: Darren Tucker -Date: Fri Apr 1 23:38:44 2022 +1100 - - Only return events from ppoll that were requested. - - If the underlying system's select() returns bits that were not in the - request set, our ppoll() implementation can return revents for events - not requested, which can apparently cause a hang. Only return revents - for activity in the requested event set. bz#3416, analysis and fix by - yaroslav.kuzmin at vmssoftware com, ok djm@ - -commit 6c49eb5fabc56f4865164ed818aa5112d09c31a8 -Author: Darren Tucker -Date: Fri Apr 1 23:21:40 2022 +1100 - - Only run regression tests on slow VMs. - -commit f67e47903977b42cb6abcd5565a61bd7293e4dc3 -Author: Darren Tucker -Date: Fri Apr 1 23:21:06 2022 +1100 - - Increase test timeout to allow slow VMs to finish - -commit 02488c1b54065ddc4f25835dbd2618b2a2fe21f5 -Author: Darren Tucker -Date: Fri Apr 1 16:27:38 2022 +1100 - - Use bash or ksh if available for SH in Makefile. - -commit 34c7018c316af4773e432066de28d0ef9d0888cd -Author: Darren Tucker -Date: Fri Apr 1 14:56:54 2022 +1100 - - Set Makefile SHELL as determined by configure. - - This should improve compatibility for users with non-POSIX shells. If - using Makefile.in directly (eg make -f Makefile.in distprep) then SHELL - will need to be specified on the command line (along with MANFMT in that - particular case). ok djm@ - -commit 5b054d76402faab38c48377efd112426469553a0 -Author: Darren Tucker -Date: Fri Apr 1 13:16:47 2022 +1100 - - Skip slow tests on (very) slow test targets. - -commit b275818065b31a865142c48c2acf6a7c1655c542 -Author: Damien Miller -Date: Thu Mar 31 14:11:36 2022 +1100 - - depend - -commit 3fa539c3ffaabd6211995512d33e29150f88c5c5 -Author: djm@openbsd.org -Date: Thu Mar 31 03:07:03 2022 +0000 - - upstream: add a sftp client "cp" command that supports server-side - - copying of files. Useful for this task and for testing the copy-data - extension. Patch from Mike Frysinger; ok dtucker@ - - OpenBSD-Commit-ID: 1bb1b950af0d49f0d5425b1f267e197aa1b57444 - -commit 7988bfc4b701c4b3fe9b36c8561a3d1c5d4c9a74 -Author: djm@openbsd.org -Date: Thu Mar 31 03:05:49 2022 +0000 - - upstream: add support for the "corp-data" protocol extension to - - allow server-side copies to be performed without having to go via the client. - Patch by Mike Frysinger, ok dtucker@ - - OpenBSD-Commit-ID: 00aa510940fedd66dab1843b58682de4eb7156d5 - -commit 32dc1c29a4ac9c592ddfef0a4895eb36c1f567ba -Author: djm@openbsd.org -Date: Wed Mar 30 21:13:23 2022 +0000 - - upstream: select post-quantum KEX - - sntrup761x25519-sha512@openssh.com as the default; ok markus@ - - OpenBSD-Commit-ID: f02d99cbfce22dffec2e2ab1b60905fbddf48fb9 - -commit d6556de1db0822c76ba2745cf5c097d9472adf7c -Author: djm@openbsd.org -Date: Wed Mar 30 21:10:25 2022 +0000 - - upstream: fix poll() spin when a channel's output fd closes without - - data in the channel buffer. Introduce more exact packing of channel fds into - the pollfd array. fixes bz3405 and bz3411; ok deraadt@ markus@ - - OpenBSD-Commit-ID: 06740737849c9047785622ad5d472cb6a3907d10 - -commit 8a74a96d25ca4d32fbf298f6c0ac5a148501777d -Author: djm@openbsd.org -Date: Wed Mar 30 04:33:09 2022 +0000 - - upstream: ssh is almost out of getopt() characters; note the - - remaining remaining available ones in a comment - - OpenBSD-Commit-ID: 48d38cef59d6bc8e84c6c066f6d601875d3253fd - -commit 6d4fc51adb9d8a42f67b5474f02f877422379de6 -Author: djm@openbsd.org -Date: Wed Mar 30 04:27:51 2022 +0000 - - upstream: avoid NULL deref via ssh-keygen -Y find-principals. - - bz3409, reported by Mateusz Adamowski - - OpenBSD-Commit-ID: a3b2c02438052ee858e0ee18e5a288586b5df2c5 - -commit e937514920335b92b543fd9be79cd6481d1eb0b6 -Author: Darren Tucker -Date: Mon Mar 28 17:51:03 2022 +1100 - - Add AIX 5.1 test target. - -commit 4bbe815ba974b4fd89cc3fc3e3ef1be847a0befe -Author: Darren Tucker -Date: Sat Mar 26 22:01:31 2022 +1100 - - Drop leading "v" from release version identifier. - - It's present in the git tags but not in the release tarball names. - Also drop extra "/" from URL path. - -commit f5cdd3b3c275dffaebfca91df782dca29975e9ac -Author: Darren Tucker -Date: Sat Mar 26 16:28:04 2022 +1100 - - Use tarballs when testing LibreSSL releases. - - This means they'll still work when the combination of -portable and - openbsd github repos no longer match. - -commit 24dc37d198f35a7cf71bf4d5384363c7ef4209d4 -Author: Darren Tucker -Date: Sat Mar 26 15:02:45 2022 +1100 - - Remove now-unused passwd variable. - -commit 5b467ceef2c356f0a77f5e8ab4eb0fac367e4d24 -Author: Darren Tucker -Date: Sat Mar 26 13:15:44 2022 +1100 - - Missing semicolon. - -commit 2923d026e55998133c0f6e5186dca2a3c0fa5ff5 -Author: Darren Tucker -Date: Sat Mar 26 12:49:50 2022 +1100 - - Factor out platform-specific locked account check. - - Also fixes an incorrect free on platforms with both libiaf and shadow - passwords (probably only Unixware). Prompted by github PR#284, - originally from @c3h2_ctf and stoeckmann@. - -commit d23efe4b12886ffe416be10bc0a7da6ca8aa72d1 -Author: Darren Tucker -Date: Sat Mar 26 08:13:46 2022 +1100 - - Add OpenWRT mips and mipsel test targets. - -commit 16ea8b85838dd7a4dbeba4e51ac4f43fd68b1e5b -Author: djm@openbsd.org -Date: Sun Mar 20 08:52:17 2022 +0000 - - upstream: don't leak argument list; bz3404, reported by Balu - - Gajjala ok dtucker@ - - OpenBSD-Commit-ID: fddc32d74e5dd5cff1a49ddd6297b0867eae56a6 - -commit a72bde294fe0518c9a44ba63864093a1ef2425e3 -Author: djm@openbsd.org -Date: Sun Mar 20 08:51:21 2022 +0000 - - upstream: make addargs() and replacearg() a little more robust and - - improve error reporting - - make freeargs(NULL) a noop like the other free functions - - ok dtucker as part of bz3403 - - OpenBSD-Commit-ID: 15f86da83176978b4d1d288caa24c766dfa2983d - -commit 731087d2619fa7f01e675b23f57af10d745e8af2 -Author: djm@openbsd.org -Date: Fri Mar 18 04:04:11 2022 +0000 - - upstream: don't try to resolve ListenAddress directives in the sshd - - re-exec path - we're never going to use the result and if the operation fails - then it can prevent connections from being accepted. Reported by Aaron - Poffenberger; with / ok dtucker@ - - OpenBSD-Commit-ID: 44c53a43909a328e2f5ab26070fdef3594eded60 - -commit 1c83c082128694ddd11ac05fdf31d70312ff1763 -Author: djm@openbsd.org -Date: Fri Mar 18 02:50:21 2022 +0000 - - upstream: remove blank line - - OpenBSD-Commit-ID: d5e0182965b2fbfb03ad5f256d1a1ce5706bcddf - -commit 807be68684da7a1fe969c399ddce2fafb7997dcb -Author: djm@openbsd.org -Date: Fri Mar 18 02:32:22 2022 +0000 - - upstream: helpful comment - - OpenBSD-Commit-ID: e3315a45cb04e7feeb614d76ec80a9fe4ca0e8c7 - -commit a0b5816f8f1f645acdf74f7bc11b34455ec30bac -Author: djm@openbsd.org -Date: Fri Mar 18 02:31:25 2022 +0000 - - upstream: ssh-keygen -Y check-novalidate requires namespace or SEGV - - will ensue. Patch from Mateusz Adamowski via GHPR#307 - - OpenBSD-Commit-ID: 99e8ec38f9feb38bce6de240335be34aedeba5fd - -commit 5a252d54a63be30d5ba4be76210942d754a531c0 -Author: djm@openbsd.org -Date: Tue Mar 15 05:27:37 2022 +0000 - - upstream: improve DEBUG_CHANNEL_POLL debugging message - - OpenBSD-Commit-ID: 2275eb7bc4707d019b1a0194b9c92c0b78da848f - -commit ce324cf58ba2840e31afeb996935800780c8fa4b -Author: cheloha@openbsd.org -Date: Sun Mar 13 23:27:54 2022 +0000 - - upstream: ssh: xstrdup(): use memcpy(3) - - Copying the given string into the buffer with strlcpy(3) confers no - benefit in this context because we have already determined the - string's length with strlen(3) in order to allocate that buffer. - - Thread: https://marc.info/?l=openbsd-tech&m=164687525802691&w=2 - - ok dtucker@ millert@ - - OpenBSD-Commit-ID: f8bfc082e36e2d2dc4e1feece02fe274155ca11a - -commit 2893c5e764557f48f9d6a929e224ed49c59545db -Author: Darren Tucker -Date: Fri Mar 11 18:43:58 2022 +1100 - - Resync fmt_scaled. with OpenBSD. - - Fixes underflow reported in bz#3401. - -commit 5ae31a0fdd27855af29f48ff027491629fff5979 -Author: Darren Tucker -Date: Wed Mar 9 09:41:56 2022 +1100 - - Provide killpg implementation. - - Based on github PR#301 for Tandem NonStop. - -commit c41c84b439f4cd74d4fe44298a4b4037ddd7d2ae -Author: Darren Tucker -Date: Wed Mar 9 09:29:30 2022 +1100 - - Check for missing ftruncate prototype. - - From github PR#301 in conjunction with rsbeckerca. - -commit 8cf5275452a950869cb90eeac7d220b01f77b12e -Author: Darren Tucker -Date: Tue Mar 8 20:04:06 2022 +1100 - - Default to not using sandbox when cross compiling. - - On most systems poll(2) does not work when the number of FDs is reduced - with setrlimit, so assume it doesn't when cross compiling and we can't - run the test. bz#3398. - -commit 379b30120da53d7c84aa8299c26b18c51c2a0dac -Author: djm@openbsd.org -Date: Tue Mar 1 01:59:19 2022 +0000 - - upstream: pack pollfd array before server_accept_loop() ppoll() - - call, and terminate sshd if ppoll() returns errno==EINVAL - - avoids spin in ppoll when MaxStartups > RLIMIT_NOFILE, reported by - Daniel Micay - - feedback/ok deraadt - - OpenBSD-Commit-ID: dbab1c24993ac977ec24d83283b8b7528f7c2c15 - -commit eceafbe0bdbbd9bd2f3cf024ccb350666a9934dd -Author: naddy@openbsd.org -Date: Sun Feb 27 01:33:59 2022 +0000 - - upstream: include rejected signature algorithm in error message and - - not the (useless) key type; ok djm@ - - OpenBSD-Commit-ID: d0c0f552a4d9161203e07e95d58a76eb602a76ff - -commit f2f3269423618a83157e18902385e720f9776007 -Author: dtucker@openbsd.org -Date: Fri Feb 25 09:46:24 2022 +0000 - - upstream: Remove the char * casts from arguments to do_lstat, - - do_readdir and do_stat paths since the underlying functions now take a const - char *. Patch from vapier at gentoo.org. - - OpenBSD-Commit-ID: 9e4d964dbfb0ed683a2a2900711b88e7f1c0297b - -commit 4a66dac052c5ff5047161853f36904607649e4f9 -Author: djm@openbsd.org -Date: Fri Feb 25 02:09:27 2022 +0000 - - upstream: save an unneccessary alloc/free, based on patch from - - Martin Vahlensieck; ok dtucker@ - - OpenBSD-Commit-ID: 90ffbf1f837e509742f2c31a1fbf2c0fd376fd5f - -commit 6f117cb151efe138ac57bdd8e26165f350328f5f -Author: Darren Tucker -Date: Tue Mar 1 09:02:06 2022 +1100 - - Remove unused ivbits argument from chacha_keysetup - -commit 15974235dd528aeab0ec67fb92a0a1d733f62be2 -Author: Darren Tucker -Date: Tue Mar 1 09:00:20 2022 +1100 - - Add OPENBSD ORIGINAL marker. - -commit f2ff669347d320532e7c1b63cdf5c62f46e73150 -Author: Darren Tucker -Date: Mon Feb 28 22:21:36 2022 +1100 - - No unused param warnings for clang-12 and gcc-11. - - These have too many false positives in -Werror tests on the github CI - since we often provide empty stub functions for functionality not needed - for particular configurations. - -commit 96558ecd87adac62efa9a2b5479f686ab86b0be1 -Author: Darren Tucker -Date: Sat Feb 26 14:10:41 2022 +1100 - - Add debian-i386 test target. - -commit 284b6e5394652d519e31782e3b3cdfd7b21d1a81 -Author: Darren Tucker -Date: Sat Feb 26 14:06:14 2022 +1100 - - Allow ppoll_time64 in seccomp sandbox. - - Should fix sandbox violations on (some? at least i386 and armhf) 32bit - Linux platforms. Patch from chutzpahu at gentoo.org and cjwatson at - debian.org via bz#3396. - -commit 0132056efabc5edb85c3c7105d2fb6dee41843c6 -Author: Darren Tucker -Date: Fri Feb 25 19:47:48 2022 +1100 - - Improve handling of _getshort and _getlong. - - If the system native ones are exactly as required then use them, - otherwise use the local versions mapped to another name to prevent - name collisions. - -commit 8e206e0dd6b9f757b07979e48f53ad5bf9b7b52b -Author: Darren Tucker -Date: Fri Feb 25 15:14:22 2022 +1100 - - Constify utimes in compat library to match specs. - - Patch from vapier at chromium.org. - -commit 1b2920e3b63db2eddebeec7330ffe8b723055573 -Author: Darren Tucker -Date: Fri Feb 25 13:50:56 2022 +1100 - - ANSIfy getshort and getlong. - - These functions appear to have come from OpenBSD's lib/libc/net/res_comp.c - which made this change in 2005. - -commit 54a86f4f6e1c43a2ca2be23ef799ab8910d4af70 -Author: Darren Tucker -Date: Fri Feb 25 13:23:04 2022 +1100 - - Use PICFLAG instead of hard coding -fPIC. - -commit 3016ba47035ac3561aabd48e2be70167fe157d6a -Author: Darren Tucker -Date: Fri Feb 25 11:37:11 2022 +1100 - - Add tests for latest releases of {Libre,Open}SSL. - -commit f107467179428a0e3ea9e4aa9738ac12ff02822d -Author: Colin Watson -Date: Thu Feb 24 16:04:18 2022 +0000 - - Improve detection of -fzero-call-used-regs=all support - - GCC doesn't tell us whether this option is supported unless it runs into - the situation where it would need to emit corresponding code. - -commit 3383b2cac0e9275bc93c4b4760e6e048f537e1d6 -Author: djm@openbsd.org -Date: Wed Feb 23 21:21:49 2022 +0000 - - upstream: free(3) wants stdlib.h - - OpenBSD-Commit-ID: 227a8c70a95b4428c49e46863c9ef4bd318a3b8a - -commit a4537e79ab4ac6db4493c5158744b9ebde5efcb0 -Author: djm@openbsd.org -Date: Wed Feb 23 21:21:16 2022 +0000 - - upstream: put back the scp manpage changes for SFTP mode too - - OpenBSD-Commit-ID: 05dc53921f927e1b5e5694e1f3aa314549f2e768 - -commit 449bcb8403adfb9724805d02a51aea76046de185 -Author: deraadt@openbsd.org -Date: Wed Feb 23 19:01:00 2022 +0000 - - upstream: and we go back to testing sftp-scp after the 8.9 - - release... - - OpenBSD-Commit-ID: a80440168258adca543a4607b871327a279c569c - -commit 166456cedad3962b83b848b1e9caf80794831f0f -Author: Damien Miller -Date: Wed Feb 23 22:31:11 2022 +1100 - - makedepend - -commit 32ebaa0dbca5d0bb86e384e72bebc153f48413e4 -Author: djm@openbsd.org -Date: Wed Feb 23 11:18:13 2022 +0000 - - upstream: avoid integer overflow of auth attempts (harmless, caught - - by monitor) - - OpenBSD-Commit-ID: 488ad570b003b21e0cd9e7a00349cfc1003b4d86 - -commit 6e0258c64c901753df695e06498b26f9f4812ea6 -Author: djm@openbsd.org -Date: Wed Feb 23 11:17:10 2022 +0000 - - upstream: randomise the password used in fakepw - - OpenBSD-Commit-ID: 34e159f73b1fbf0a924a9c042d8d61edde293947 - -commit bf114d6f0a9df0b8369823d9a0daa6c72b0c4cc9 -Author: djm@openbsd.org -Date: Wed Feb 23 11:15:57 2022 +0000 - - upstream: use asprintf to construct .rhosts paths - - OpenBSD-Commit-ID: 8286e8d3d2c6ff916ff13d041d1713073f738a8b - -commit c07e154fbdc7285e9ec54e78d8a31f7325d43537 -Author: djm@openbsd.org -Date: Wed Feb 23 11:07:09 2022 +0000 - - upstream: openssh-8.9 - - OpenBSD-Commit-ID: 5c5f791c87c483cdab6d9266b43acdd9ca7bde0e - -commit bc16667b4a1c3cad7029304853c143a32ae04bd4 -Author: Darren Tucker -Date: Tue Feb 22 15:29:22 2022 +1100 - - Extend select+rlimit sanbox test to include poll. - - POSIX specifies that poll() shall fail if "nfds argument is greater - than {OPEN_MAX}". The setrlimit sandbox sets this to effectively zero - so this causes poll() to fail in the preauth privsep process. - - This is likely the underlying cause for the previously observed similar - behaviour of select() on plaforms where it is implement in userspace on - top of poll(). - -commit 6520c488de95366be031d49287ed243620399e23 -Author: Darren Tucker -Date: Tue Feb 22 13:08:59 2022 +1100 - - Add Alpine Linux test VM. - -commit a4b325a3fc82d11e0f5d61f62e7fde29415f7afb -Author: Darren Tucker -Date: Tue Feb 22 12:27:07 2022 +1100 - - Include sys/param.h if present. - - Needed for howmany() on MUSL systems such as Alpine. - -commit 5a102e9cb287a43bd7dfe594b775a89a8e94697c -Author: Darren Tucker -Date: Tue Feb 22 12:25:52 2022 +1100 - - Only include sys/poll.h if we don't have poll.h. - - Prevents warnings on MUSL based systems such as Alpine. - -commit 7c0d4ce911d5c58b6166b2db754a4e91f352adf5 -Author: Damien Miller -Date: Tue Feb 22 11:14:51 2022 +1100 - - disable agent-restrict test on minix3 - - Minix seems to have a platform-wide limit on the number of - select(2) syscalls that can be concurrently issued. This test - seems to exceed this limit. - - Refer to: - - https://github.com/Stichting-MINIX-Research-Foundation/minix/blob/R3.3.0/minix/servers/vfs/select.c#L114 - https://github.com/Stichting-MINIX-Research-Foundation/minix/blob/R3.3.0/minix/servers/vfs/select.c#L30-L31 - -commit 81d33d8e3cf7ea5ce3a5653c6102b623e019428a -Author: Darren Tucker -Date: Mon Feb 21 21:27:20 2022 +1100 - - Skip agent-getpeereid when running as root. - -commit fbd772570a25436a33924d91c164d2b24021f010 -Author: dtucker@openbsd.org -Date: Sun Feb 20 03:47:26 2022 +0000 - - upstream: Aproximate realpath on the expected output by deduping - - leading slashes. Fixes test failure when user's home dir is / which is - possible in some portable configurations. - - OpenBSD-Regress-ID: 53b8c53734f8893806961475c7106397f98d9f63 - -commit 336685d223a59f893faeedf0a562e053fd84058e -Author: Darren Tucker -Date: Sun Feb 20 13:30:52 2022 +1100 - - Really move DSA to end of list. - - In commit ad16a84e syncing from OpenBSD, RSA was accidentally moved to - the end of the list instead of DSA. Spotted by andrew at fyfe.gb.net. - -commit 63bf4f49ed2fdf2da6f97136c9df0c8168546eb3 -Author: Darren Tucker -Date: Fri Feb 18 12:12:21 2022 +1100 - - Add test configs for MUSL C library. - -commit f7fc6a43f1173e8b2c38770bf6cee485a562d03b -Author: Damien Miller -Date: Thu Feb 17 22:54:19 2022 +1100 - - minix needs BROKEN_POLL too; chokes on /dev/null - -commit 667fec5d4fe4406745750a32f69b5d2e1a75e94b -Author: djm@openbsd.org -Date: Thu Feb 17 10:58:27 2022 +0000 - - upstream: check for EINTR/EAGAIN failures in the rfd fast-path; caught - - by dtucker's minix3 vm :) ok dtucker@ - - OpenBSD-Commit-ID: 2e2c895a3e82ef347aa6694394a76a438be91361 - -commit 41417dbda9fb55a0af49a8236e3ef9d50d862644 -Author: Darren Tucker -Date: Thu Feb 17 22:05:29 2022 +1100 - - Comment hurd test, the VM is currently broken. - -commit b2aee35a1f0dc798339b3fcf96136da71b7e3f6d -Author: Damien Miller -Date: Thu Feb 17 21:15:16 2022 +1100 - - find sk-dummy.so when build_dir != src_dir - - spotted by Corinna Vinschen; feedback & ok dtucker@ - -commit 62a2d4e50b2e89f2ef04576931895d5139a5d037 -Author: Damien Miller -Date: Wed Feb 16 16:26:17 2022 +1100 - - update versions in preparation for 8.9 release - -commit dd6d3dded721ac653ea73c017325e5bfeeec837f -Author: djm@openbsd.org -Date: Tue Feb 15 05:13:36 2022 +0000 - - upstream: document the unbound/host-bound options to - - PubkeyAuthentication; spotted by HARUYAMA Seigo - - OpenBSD-Commit-ID: 298f681b66a9ecd498f0700082c7a6c46e948981 - -commit df93529dd727fdf2fb290700cd4f1adb0c3c084b -Author: Darren Tucker -Date: Mon Feb 14 14:19:40 2022 +1100 - - Test if sshd accidentally acquires controlling tty - - When SSHD_ACQUIRES_CTTY is defined, test for the problematic behaviour - in the STREAMS code before activating the workaround. ok djm@ - -commit 766176cfdbfd7ec38bb6118dde6e4daa0df34888 -Author: Darren Tucker -Date: Sat Feb 12 10:24:56 2022 +1100 - - Add cygwin-release test config. - - This tests the flags used to build the cygwin release binaries. - -commit b30698662b862f5397116d23688aac0764e0886e -Author: Darren Tucker -Date: Fri Feb 11 21:00:35 2022 +1100 - - Move SSHD_ACQUIRES_CTTY workaround into compat. - - On some (most? all?) SysV based systems with STREAMS based ptys, - sshd could acquire a controlling terminal during pty setup when - it pushed the "ptem" module, due to what is probably a bug in - the STREAMS driver that's old enough to vote. Because it was the - privileged sshd's controlling terminal, it was not available for - the user's session, which ended up without one. This is known to - affect at least Solaris <=10, derivatives such as OpenIndiana and - several other SysV systems. See bz#245 for the backstory. - - In the we past worked around that by not calling setsid in the - privileged sshd child, which meant it was not a session or process - group leader. This solved controlling terminal problem because sshd - was not eligble to acquire one, but had other side effects such as - not cleaning up helper subprocesses in the SIGALRM handler since it - was not PG leader. Recent cleanups in the signal handler uncovered - this, resulting in the LoginGraceTime timer not cleaning up privsep - unprivileged processes. - - This change moves the workaround into the STREAMS pty allocation code, - by allocating a sacrificial pty to act as sshd's controlling terminal - before allocating user ptys, so those are still available for users' - sessions. - - On the down side: - - this will waste a pty per ssh connection on affected platforms. - - On the up side: - - it makes the process group behaviour consistent between platforms. - - - it puts the workaround nearest the code that actually causes the - problem and competely out of the mainline code. - - - the workaround is only activated if you use the STREAMS code. If, - say, Solaris 11 has the bug but also a working openpty() it doesn't - matter that we defined SSHD_ACQUIRES_CTTY. - - - the workaround is only activated when the fist pty is allocated, - ie in the post-auth privsep monitor. This means there's no risk - of fd leaks to the unprivileged processes, and there's no effect on - sessions that do not allocate a pty. - - Based on analysis and work by djm@, ok djm@ - -commit cd00b48cf10f3565936a418c1e6d7e48b5c36140 -Author: Darren Tucker -Date: Fri Feb 11 20:09:32 2022 +1100 - - Simplify handling of --with-ssl-dir. - - ok djm@ - -commit ea13fc830fc0e0dce2459f1fab2ec5099f73bdf0 -Author: Darren Tucker -Date: Fri Feb 11 13:39:29 2022 +1100 - - Stop testing OpenBSD HEAD on 6.9 and 7.0. - - HEAD is not guaranteed to work on previous stable branches, and at the - moment is broken due to libfido API changes. - -commit 50b9e4a4514697ffb9592200e722de6b427cb9ff -Author: dtucker@openbsd.org -Date: Fri Feb 11 00:43:56 2022 +0000 - - upstream: Always initialize delim before passing to hpdelim2 which - - might not set it. Found by the Valgrind tests on github, ok deraadt@ - - OpenBSD-Commit-ID: c830c0db185ca43beff3f41c19943c724b4f636d - -commit 6ee53064f476cf163acd5521da45b11b7c57321b -Author: Darren Tucker -Date: Fri Feb 11 10:03:06 2022 +1100 - - Fix helper include path and remove excess code. - - Looks like test_hpdelim.c was imported twice into the same file. - Spotted by kevin.brott at gmail com and chris at cataclysmal org. - -commit 9fa63a19f68bc87452d3cf5c577cafad2921b7a4 -Author: Darren Tucker -Date: Thu Feb 10 23:27:02 2022 +1100 - - Put poll.h inside ifdef. - -commit 3ac00dfeb54b252c15dcbf1971582e9e3b946de6 -Author: Darren Tucker -Date: Thu Feb 10 22:17:31 2022 +1100 - - We now support POLLPRI so actually define it. - -commit 25bd659cc72268f2858c5415740c442ee950049f -Author: dtucker@openbsd.org -Date: Sun Feb 6 22:58:33 2022 +0000 - - upstream: Add test for empty hostname with port. - - OpenBSD-Regress-ID: e19e89d3c432b68997667efea44cf015bbe2a7e3 - -commit a29af853cff41c0635f0378c00fe91bf9c91dea4 -Author: dtucker@openbsd.org -Date: Fri Feb 4 07:53:44 2022 +0000 - - upstream: Add unit tests for hpdelim. - - OpenBSD-Regress-ID: be97b85c19895e6a1ce13c639765a3b48fd95018 - -commit 9699151b039ecc5fad9ac6c6c02e9afdbd26f15f -Author: djm@openbsd.org -Date: Thu Feb 10 04:12:38 2022 +0000 - - upstream: revert for imminent OpenSSH release, which wil ship with - - scp in RCP mode. - - > revision 1.106 - > date: 2021/10/15 14:46:46; author: deraadt; state: Exp; lines: +13 -9; commitid: w5n9B2RE38tFfggl; - > openbsd 7.0 release shipped with the (hopefully last) scp that uses RCP - > protocol for copying. Let's get back to testing the SFTP protocol. - - This will be put back once the OpenSSH release is done. - - OpenBSD-Commit-ID: 0c725481a78210aceecff1537322c0b2df03e768 - -commit 45279abceb37c3cbfac8ba36dde8b2c8cdd63d32 -Author: dtucker@openbsd.org -Date: Tue Feb 8 08:59:12 2022 +0000 - - upstream: Switch hpdelim interface to accept only ":" as delimiter. - - Historicallly, hpdelim accepted ":" or "/" as a port delimiter between - hosts (or addresses) and ports. These days most of the uses for "/" - are no longer accepted, so there are several places where it checks the - delimiter to disallow it. Make hpdelim accept only ":" and use hpdelim2 - in the other cases. ok djm@ - - OpenBSD-Commit-ID: 7e6420bd1be87590b6840973f5ad5305804e3102 - -commit a1bcbf04a7c2d81944141db7ecd0ba292d175a66 -Author: pedro martelletto -Date: Mon Feb 7 09:09:59 2022 +0100 - - fix typos in previous - -commit 56192518e329b39f063487bc2dc4d796f791eca0 -Author: Damien Miller -Date: Mon Feb 7 12:53:47 2022 +1100 - - compat code for fido_assert_set_clientdata() - -commit d6b5aa08fdcf9b527f8b8f932432941d5b76b7ab -Author: djm@openbsd.org -Date: Mon Feb 7 01:25:12 2022 +0000 - - upstream: use libfido2 1.8.0+ fido_assert_set_clientdata() instead - - of manually hashing data outselves. Saves a fair bit of code and makes life - easier for some -portable platforms. - - OpenBSD-Commit-ID: 351dfaaa5ab1ee928c0e623041fca28078cff0e0 - -commit 86cc93fd3c26b2e0c7663c6394995fb04ebfbf3b -Author: jsg@openbsd.org -Date: Sun Feb 6 00:29:03 2022 +0000 - - upstream: remove please from manual pages ok jmc@ sthen@ millert@ - - OpenBSD-Commit-ID: 6543acb00f4f38a23472538e1685c013ca1a99aa - -commit ad16a84e64a8cf1c69c63de3fb9008320a37009c -Author: dtucker@openbsd.org -Date: Fri Feb 4 02:49:17 2022 +0000 - - upstream: Since they are deprecated, move DSA to the end of the - - default list of public keys so that they will be tried last. From github - PR#295 from "ProBackup-nl", ok djm@ - - OpenBSD-Commit-ID: 7e5d575cf4971d4e2de92e0b6d6efaba53598bf0 - -commit 253de42753de85dde266e061b6fec12ca6589f7d -Author: Damien Miller -Date: Wed Feb 2 16:52:07 2022 +1100 - - portable-specific string array constification - - from Mike Frysinger - -commit dfdcc2220cf359c492d5d34eb723370e8bd8a19e -Author: djm@openbsd.org -Date: Tue Feb 1 23:37:15 2022 +0000 - - upstream: test 'ssh-keygen -Y find-principals' with wildcard - - principals; from Fabian Stelzer - - OpenBSD-Regress-ID: fbe4da5f0032e7ab496527a5bf0010fd700f8f40 - -commit 968e508967ef42480cebad8cf3172465883baa77 -Author: dtucker@openbsd.org -Date: Fri Jan 21 02:54:41 2022 +0000 - - upstream: Enable all supported ciphers and macs in the server - - before trying to benchmark them. Increase the data file size to get more - signal. - - OpenBSD-Regress-ID: dc3697d9f7defdfc51c608782c8e750128e46eb6 - -commit 15b7199a1fd37eff4c695e09d573f3db9f4274b7 -Author: djm@openbsd.org -Date: Tue Feb 1 23:34:47 2022 +0000 - - upstream: allow 'ssh-keygen -Y find-principals' to match wildcard - - principals in allowed_signers files; from Fabian Stelzer - - OpenBSD-Commit-ID: 1e970b9c025b80717dddff5018fe5e6f470c5098 - -commit 541667fe6dc26d7881e55f0bb3a4baa6f3171645 -Author: djm@openbsd.org -Date: Tue Feb 1 23:32:51 2022 +0000 - - upstream: mark const string array contents const too, i.e. static - - const char *array => static const char * const array from Mike Frysinger - - OpenBSD-Commit-ID: a664e31ea6a795d7c81153274a5f47b22bdc9bc1 - -commit 8cfa73f8a2bde4c98773f33f974c650bdb40dd3c -Author: djm@openbsd.org -Date: Tue Feb 1 23:11:11 2022 +0000 - - upstream: better match legacy scp behaviour: show un-expanded paths - - in error messages. Spotted by and ok tb@ - - OpenBSD-Commit-ID: 866c8ffac5bd7d38ecbfc3357c8adfa58af637b7 - -commit 4e62c13ab419b4b224c8bc6a761e91fcf048012d -Author: dtucker@openbsd.org -Date: Tue Feb 1 07:57:32 2022 +0000 - - upstream: Remove explicit kill of privsep preauth child's PID in - - SIGALRM handler. It's no longer needed since the child will get terminated by - the SIGTERM to the process group that cleans up any auth helpers, it - simplifies the signal handler and removes the risk of a race when updating - the PID. Based on analysis by HerrSpace in github PR#289, ok djm@ - - OpenBSD-Commit-ID: 2be1ffa28b4051ad9e33bb4371e2ec8a31d6d663 - -commit 2a7ccd2ec4022917b745af7186f514f365b7ebe9 -Author: guenther@openbsd.org -Date: Fri Jan 28 06:18:42 2022 +0000 - - upstream: When it's the possessive of 'it', it's spelled "its", - - without the apostrophe. - - OpenBSD-Commit-ID: fb6ab9c65bd31de831da1eb4631ddac018c5fae7 - -commit 8a0848cdd3b25c049332cd56034186b7853ae754 -Author: Alex James -Date: Sun Jan 30 16:13:36 2022 -0600 - - sandbox-seccomp-filter: allow gettid - - Some allocators (such as Scudo) use gettid while tracing allocations [1]. - Allow gettid in preauth to prevent sshd from crashing with Scudo. - - [1]: https://github.com/llvm/llvm-project/blob/llvmorg-13.0.0/compiler-rt/lib/gwp_asan/common.cpp#L46 - -commit b30d32159dc3c7052f4bfdf36357996c905af739 -Author: djm@openbsd.org -Date: Sat Jan 22 00:49:34 2022 +0000 - - upstream: add a ssh_packet_process_read() function that reads from - - a fd directly into the transport input buffer. - - Use this in the client and server mainloops to avoid unnecessary - copying. It also lets us use a more greedy read size without penalty. - - Yields a 2-3% performance gain on cipher-speed.sh (in a fairly - unscientific test tbf) - - feedback dtucker@ ok markus@ - - OpenBSD-Commit-ID: df4112125bf79d8e38e79a77113e1b373078e632 - -commit a1a8efeaaa9cccb15cdc0a2bd7c347a149a3a7e3 -Author: djm@openbsd.org -Date: Sat Jan 22 00:45:31 2022 +0000 - - upstream: Use sshbuf_read() to read directly into the channel input - - buffer rather than into a stack buffer that needs to be copied again; - Improves performance by about 1% on cipher-speed.sh feedback dtucker@ ok - markus@ - - OpenBSD-Commit-ID: bf5e6e3c821ac3546dc8241d8a94e70d47716572 - -commit 29a76994e21623a1f84d68ebb9dc5a3c909fa3a7 -Author: Damien Miller -Date: Tue Jan 25 11:52:34 2022 +1100 - - depend - -commit 754e0d5c7712296a7a3a83ace863812604c7bc4f -Author: djm@openbsd.org -Date: Sat Jan 22 00:43:43 2022 +0000 - - upstream: Add a sshbuf_read() that attempts to read(2) directly in - - to a sshbuf; ok markus@ - - OpenBSD-Commit-ID: 2d8f249040a4279f3bc23c018947384de8d4a45b - -commit c7964fb9829d9ae2ece8b51a76e4a02e8449338d -Author: djm@openbsd.org -Date: Fri Jan 21 07:04:19 2022 +0000 - - upstream: add a helper for writing an error message to the - - stderr_buf and setting quit_pending; no functional change but saves a bunch - of boilerplate - - OpenBSD-Commit-ID: 0747657cad6b9eabd514a6732adad537568e232d - -commit d23b4f7fdb1bd87e2cd7a9ae7c198ae99d347916 -Author: djm@openbsd.org -Date: Fri Jan 21 06:58:06 2022 +0000 - - upstream: correct comment and use local variable instead of long - - indirection; spotted by dtucker@ - - OpenBSD-Commit-ID: 5f65f5f69db2b7d80a0a81b08f390a63f8845965 - -commit d069b020a02b6e3935080204ee44d233e8158ebb -Author: deraadt@openbsd.org -Date: Fri Jan 21 00:53:40 2022 +0000 - - upstream: When poll(2) returns -1, for some error conditions - - pfd[].revents is not cleared. There are subtle errors in various programs. - In this particular case, the program should error out. ok djm millert - - OpenBSD-Commit-ID: 00f839b16861f7fb2adcf122e95e8a82fa6a375c - -commit e204b34337a965feb439826157c191919fd9ecf8 -Author: Damien Miller -Date: Sat Jan 22 11:38:21 2022 +1100 - - restore tty force-read hack - - This portable-specific hack fixes a hang on exit for ttyful sessions - on Linux and some SysVish Unix variants. It was accidentally disabled - in commit 5c79952dfe1a (a precursor to the mainloop poll(2) conversion). - - Spotted by John in bz3383 - -commit 68085066b6bad43643b43f5957fcc5fd34782ccd -Author: Corinna Vinschen -Date: Fri Jan 21 03:22:56 2022 +1100 - - Fix signedness bug in Cygwin code - - The Cygwin-specific pattern match code has a bug. It checks - the size_t value returned by mbstowcs for being < 0. The right - thing to do is to check against (size_t) -1. Fix that. - - Signed-off-by: Corinna Vinschen - -commit 2e5cfed513e84444483baf1d8b31c40072b05103 -Author: Darren Tucker -Date: Thu Jan 20 13:26:27 2022 +1100 - - Improve compatibility of early exit trap handling. - - Dash (as used by the github runners) has some differences in its trap - builtin: - - it doesn't have -p (which is fine, that's not in posix). - - it doesn't work in a subshell (which turns out to be in compliance - with posix, which means bash isn't). - - it doesn't work in a pipeline, ie "trap|cat" produces no output. - -commit 3fe6800b6027add478e648934cbb29d684e51943 -Author: Darren Tucker -Date: Thu Jan 20 00:49:57 2022 +1100 - - Move more tests out of valgrind-1 runner. - -commit 20da6ed136dd76e6a0b229ca3036ef9c7c7ef798 -Author: Darren Tucker -Date: Wed Jan 19 15:37:39 2022 +1100 - - Invoke EXIT handler early when using Valgrind. - - When using Valgrind, we need to wait for all invoked programs to - complete before checking their valgrind logs. Some tests, notably - agent-restrict, set an EXIT trap handler to clean up things like - ssh-agent, but those do not get invoked until test-exec.sh exits. - This causes the Valgrind wait to deadlock, so if present invoke - the EXIT handler before checking the Valgrind logs. - -commit ad2e0580c87b0714cf166bca9d926a95ddeee1c8 -Author: Darren Tucker -Date: Tue Jan 18 12:55:21 2022 +1100 - - Remove line leftover from upstream sync. - -commit d1051c0f11a6b749027e26bbeb61b07df4b67e15 -Author: djm@openbsd.org -Date: Mon Jan 17 22:56:04 2022 +0000 - - upstream: when decompressing zlib compressed packets, use - - Z_SYNC_FLUSH instead of Z_PARTIAL_FLUSH as the latter is not actually - specified as a valid mode for inflate(). There should be no practical change - in behaviour as the compression side ensures a flush that should make all - data available to the receiver in all cases. - - repoted by lamm AT ibm.com via bz3372; ok markus - - OpenBSD-Commit-ID: 67cfc1fa8261feae6d2cc0c554711c97867cc81b - -commit d5981b1883746b1ae178a46229c26b53af99e37a -Author: djm@openbsd.org -Date: Mon Jan 17 21:41:04 2022 +0000 - - upstream: make most of the sftp errors more idiomatic, following - - the general form of "[local/remote] operation path: error message"; ok markus - - OpenBSD-Commit-ID: 61364cd5f3a9fecaf8d63b4c38a42c0c91f8b571 - -commit ac7c9ec894ed0825d04ef69c55babb49bab1d32e -Author: djm@openbsd.org -Date: Mon Jan 17 21:39:51 2022 +0000 - - upstream: when transferring multiple files in SFTP mode, create the - - destination directory if it doesn't already exist to match olde-scp(1) - behaviour. noticed by deraadt@ ok markus@ - - OpenBSD-Commit-ID: cf44dfa231d4112f697c24ff39d7ecf2e6311407 - -commit 39d17e189f8e72c34c722579d8d4e701fa5132da -Author: djm@openbsd.org -Date: Fri Jan 14 03:43:48 2022 +0000 - - upstream: allow pin-required FIDO keys to be added to ssh-agent(1). - - ssh-askpass will be used to request the PIN at authentication time. - - From Pedro Martelletto, ok djm - - OpenBSD-Commit-ID: de8189fcd35b45f632484864523c1655550e2950 - -commit 52423f64e13db2bdc31a51b32e999cb1bfcf1263 -Author: djm@openbsd.org -Date: Fri Jan 14 03:35:10 2022 +0000 - - upstream: ssh-sk: free a resident key's user id - - From Pedro Martelletto; ok dtucker & me - - OpenBSD-Commit-ID: 47be40d602b7a6458c4c71114df9b53d149fc2e9 - -commit 014e2f147a2788bfb3cc58d1b170dcf2bf2ee493 -Author: djm@openbsd.org -Date: Fri Jan 14 03:34:00 2022 +0000 - - upstream: sshsk_load_resident: don't preallocate resp - - resp is allocated by client_converse(), at which point we lose - the original pointer. - - From Pedro Martelletto; ok dtucker & me - - OpenBSD-Commit-ID: 1f1b5ea3282017d6584dfed4f8370dc1db1f44b1 - -commit c88265f207dfe0e8bdbaf9f0eda63ed6b33781cf -Author: djm@openbsd.org -Date: Fri Jan 14 03:32:52 2022 +0000 - - upstream: sshsk_sign: trim call to sshkey_fingerprint() - - the resulting fingerprint doesn't appear to be used for anything, - and we end up leaking it. - - from Pedro Martelletto; ok dtucker & me - - OpenBSD-Commit-ID: 5625cf6c68f082bc2cbbd348e69a3ed731d2f9b7 - -commit 1cd1b2eac39661b849d5a4b4b56363e22bb5f61e -Author: djm@openbsd.org -Date: Fri Jan 14 03:31:52 2022 +0000 - - upstream: use status error message to communicate ~user expansion - - failures; provides better experience for scp in sftp mode, where ~user paths - are more likely to be used; spotted jsg, feedback jsg & deraadt ok jsg & - markus - - (forgot to include this file in previous commit) - - OpenBSD-Commit-ID: d37cc4c8c861ce48cd6ea9899e96aaac3476847b - -commit a1d42a6ce0398da3833bedf374ef2571af7fea50 -Author: Damien Miller -Date: Fri Jan 14 13:49:32 2022 +1100 - - fix edge case in poll(2) wrapper - - Correct handling of select(2) exceptfds. These should only be consulted - for POLLPRI flagged pfds and not unconditionally converted to POLLERR. - - with and ok dtucker@ - -commit 976b9588b4b5babcaceec4767a241c11a67a5ccb -Author: Darren Tucker -Date: Fri Jan 14 13:46:35 2022 +1100 - - Wrap OpenSSL includes in unit tests in ifdef. - - Fixes unit test on systems that do not have OpenSSL headers installed. - -commit c171879374b2e8b07157503f5639ed0bce59ce89 -Author: Darren Tucker -Date: Thu Jan 13 15:53:33 2022 +1100 - - Remove sort wrapper. - - agent-restrict now takes care of this itself. - -commit 9cc2654403f1a686bb26c07a6ac790edf334cef5 -Author: dtucker@openbsd.org -Date: Thu Jan 13 04:53:16 2022 +0000 - - upstream: Set LC_ALL in both local and remote shells so that sorted - - output matches regardless of what the user's shell sets it to. ok djm@ - - OpenBSD-Regress-ID: 4e97dd69a68b05872033175a4c2315345d01837f - -commit 7a75f748cb2dd2f771bf70ea72698aa027996ab1 -Author: dtucker@openbsd.org -Date: Thu Jan 13 04:22:10 2022 +0000 - - upstream: Avoid %'s in commands (not used in OpenBSD, but used in - - -portable's Valgrind test) being interpretted as printf format strings. - - OpenBSD-Regress-ID: dc8655db27ac4acd2c386c4681bf42a10d80b043 - -commit 6c435bd4994d71442192001483a1cdb846e5ffcd -Author: Darren Tucker -Date: Wed Jan 12 16:58:13 2022 +1100 - - Stop on first test failure to minimize logs. - -commit 4bc2ba6095620a4484b708ece12842afd8c7685b -Author: dtucker@openbsd.org -Date: Wed Jan 12 07:18:37 2022 +0000 - - upstream: Use egrep when searching for an anchored string. - - OpenBSD-Regress-ID: dd114a2ac27ac4b06f9e4a586d3f6320c54aeeb4 - -commit 6bf2efa2679da1e8e60731f41677b2081dedae2c -Author: Darren Tucker -Date: Wed Jan 12 18:25:06 2022 +1100 - - Add "rev" command replacement if needed. - -commit 72bcd7993dadaf967bb3d8564ee31cbf38132b5d -Author: dtucker@openbsd.org -Date: Wed Jan 12 03:30:32 2022 +0000 - - upstream: Don't log NULL hostname in restricted agent code, - - printf("%s", NULL) is not safe on all platforms. with & ok djm - - OpenBSD-Commit-ID: faf10cdae4adde00cdd668cd1f6e05d0a0e32a02 - -commit acabefe3f8fb58c867c99fed9bbf84dfa1771727 -Author: djm@openbsd.org -Date: Tue Jan 11 22:33:16 2022 +0000 - - upstream: remove hardcoded domain and use window.location.host, so this - - can be run anywhere - - OpenBSD-Regress-ID: 2ac2ade3b6227d9c547351d3ccdfe671e62b7f92 - -commit 96da0946e44f34adc0397eb7caa6ec35a3e79891 -Author: dtucker@openbsd.org -Date: Tue Jan 11 02:56:19 2022 +0000 - - upstream: "void" functions should not return anything. From Tim Rice - - via -portable. - - OpenBSD-Commit-ID: ce6616304f4c9881b46413e616b226c306830e2a - -commit a882a09722c9f086c9edb65d0c4022fd965ec1ed -Author: djm@openbsd.org -Date: Tue Jan 11 01:26:47 2022 +0000 - - upstream: suppress "Connection to xxx closed" messages at LogLevel >= - - error bz3378; ok dtucker@ - - OpenBSD-Commit-ID: d5bf457d5d2eb927b81d0663f45248a31028265c - -commit 61a1a6af22e17fc94999a5d1294f27346e6c4668 -Author: Damien Miller -Date: Wed Jan 12 08:57:49 2022 +1100 - - OS X poll(2) is broken; use compat replacement - - Darwin's poll(2) implementation is broken. For character-special - devices like /dev/null, it returns POLLNVAL when polled with - POLLIN. - - Apparently this is Apple bug 3710161, which is AFAIK not public, - but a websearch will find other OSS projects rediscovering it - periodically since it was first identified in 2005 (!!) - -commit 613a6545fc5a9542753b503cbe5906538a640b60 -Author: Darren Tucker -Date: Tue Jan 11 20:56:01 2022 +1100 - - libhardended_malloc.so moved into out dir. - -commit 61761340be5e11046556623f8f5412b236cefa95 -Author: Tim Rice -Date: Mon Jan 10 11:07:04 2022 -0800 - - Make USL compilers happy - UX:acomp: ERROR: "sftp-server.c", line 567: void function cannot return value - -commit 3ef403f351e80a59b6f7e9d43cb82c181855483c -Author: Darren Tucker -Date: Mon Jan 10 21:07:38 2022 +1100 - - Add wrapper for "sort" to set LC_ALL=C. - - Found by djm, this should make sorts stable and reduce test flakiness. - -commit bd69e29f5716090181dbe0b8272eb7eab1a383bb -Author: dtucker@openbsd.org -Date: Sat Jan 8 07:55:26 2022 +0000 - - upstream: Remove errant "set -x" left over from debugging. - - OpenBSD-Regress-ID: cd989268e034264cec5df97be7581549032c87dc - -commit 1a7c88e26fd673813dc5f61c4ac278564845e004 -Author: dtucker@openbsd.org -Date: Sat Jan 8 07:01:13 2022 +0000 - - upstream: Enable all supported hostkey algorithms (but no others). - - Allows hostbased test to pass when built without OpenSSL. - - OpenBSD-Regress-ID: 5ddd677a68b672517e1e78460dc6ca2ccc0a9562 - -commit 12b457c2a42ff271e7967d9bedd068cebb048db9 -Author: djm@openbsd.org -Date: Sat Jan 8 07:37:32 2022 +0000 - - upstream: use status error message to communicate ~user expansion - - failures; provides better experience for scp in sftp mode, where ~user paths - are more likely to be used; spotted jsg, feedback jsg & deraadt ok jsg & - markus - - OpenBSD-Commit-ID: fc610ce00ca0cdc2ecdabbd49ce7cb82033f905f - -commit 63670d4e9030bcee490d5a9cce561373ac5b3b23 -Author: djm@openbsd.org -Date: Sat Jan 8 07:36:11 2022 +0000 - - upstream: fix some corner-case bugs in scp sftp-mode handling of - - ~-prefixed paths; spotted by jsg; feedback jsg & deraadt, ok jsg & markus - - OpenBSD-Commit-ID: d1697dbaaa9f0f5649d69be897eab25c7d37c222 - -commit e14940bbec57fc7d3ce0644dbefa35f5a8ec97d0 -Author: djm@openbsd.org -Date: Sat Jan 8 07:34:57 2022 +0000 - - upstream: more idiomatic error messages; spotted by jsg & deraadt - - ok jsg & markus - - OpenBSD-Commit-ID: 43618c692f3951747b4151c477c7df22afe2bcc8 - -commit 9acddcd5918c623f7ebf454520ffe946a8f15e90 -Author: djm@openbsd.org -Date: Sat Jan 8 07:33:54 2022 +0000 - - upstream: add a variant of send_status() that allows overriding the - - default, generic error message. feedback/ok markus & jsg - - OpenBSD-Commit-ID: 81f251e975d759994131b717ee7c0b439659c40f - -commit 961411337719d4cd78f1ab33e4ac549f3fa22f50 -Author: djm@openbsd.org -Date: Sat Jan 8 07:32:45 2022 +0000 - - upstream: refactor tilde_expand_filename() and make it handle ~user - - paths with no trailing slash; feedback/ok markus and jsg - - OpenBSD-Commit-ID: a2ab365598a902f0f14ba6a4f8fb2d07a9b5d51d - -commit dc38236ab6827dec575064cac65c8e7035768773 -Author: dtucker@openbsd.org -Date: Thu Jan 6 22:14:25 2022 +0000 - - upstream: Don't explicitly set HostbasedAuthentication in - - sshd_config. It defaults to "no", and not explicitly setting it allows us to - enable it for the (optional) hostbased test. - - OpenBSD-Regress-ID: aa8e3548eb5793721641d26e56c29f363b767c0c - -commit e12d912ddf1c873cb72e5de9a197afbe0b6622d2 -Author: dtucker@openbsd.org -Date: Thu Jan 6 21:46:56 2022 +0000 - - upstream: Add test for hostbased auth. It requires some external - - setup (see comments at the top) and thus is disabled unless - TEST_SSH_HOSTBASED_AUTH and SUDO are set. - - OpenBSD-Regress-ID: 3ec8ba3750c5b595fc63e7845d13483065a4827a - -commit a48533a8da6a0f4f05ecd055dc8048047e53569e -Author: Damien Miller -Date: Fri Jan 7 09:24:26 2022 +1100 - - depend - -commit d9dbb5d9a0326e252d3c7bc13beb9c2434f59409 -Author: djm@openbsd.org -Date: Thu Jan 6 22:06:51 2022 +0000 - - upstream: allow hostbased auth to select RSA keys when only - - RSA/SHA2 are configured (this is the default case); ok markus@ - - OpenBSD-Commit-ID: 411c18c7bde40c60cc6dfb7017968577b4d4a827 - -commit fdb1d58d0d3888b042e5a500f6ce524486aaf782 -Author: djm@openbsd.org -Date: Thu Jan 6 22:05:42 2022 +0000 - - upstream: add a helper function to match a key type to a list of - - signature algorithms. RSA keys can make signatures with multiple algorithms, - so some special handling is required. ok markus@ - - OpenBSD-Commit-ID: 03b41b2bda06fa4cd9c84cef6095033b9e49b6ff - -commit 11e8c4309a5086a45fbbbc87d0af5323c6152914 -Author: djm@openbsd.org -Date: Thu Jan 6 22:04:20 2022 +0000 - - upstream: log some details on hostkeys that ssh loads for - - hostbased authn ok markus@ - - OpenBSD-Commit-ID: da17061fa1f0e58cb31b88478a40643e18233e38 - -commit c6706f661739514a34125aa3136532a958929510 -Author: djm@openbsd.org -Date: Thu Jan 6 22:03:59 2022 +0000 - - upstream: log signature algorithm during verification by monitor; - - ok markus - - OpenBSD-Commit-ID: 02b92bb42c4d4bf05a051702a56eb915151d9ecc - -commit 8832402bd500d1661ccc80a476fd563335ef6cdc -Author: djm@openbsd.org -Date: Thu Jan 6 22:02:52 2022 +0000 - - upstream: piece of UpdateHostkeys client strictification: when - - updating known_hosts with new keys, ignore NULL keys (forgot to include in - prior commit) - - OpenBSD-Commit-ID: 49d2eda6379490e1ceec40c3b670b973f63dea08 - -commit c2d9ced1da0276961d86690b3bd7ebdaca7fdbf7 -Author: djm@openbsd.org -Date: Thu Jan 6 22:01:14 2022 +0000 - - upstream: include rejected signature algorithm in error message - - and not the (useless) key type; ok markus - - OpenBSD-Commit-ID: 4180b5ec7ab347b43f84e00b1972515296dab023 - -commit 7aa7b096cf2bafe2777085abdeed5ce00581f641 -Author: djm@openbsd.org -Date: Thu Jan 6 22:00:18 2022 +0000 - - upstream: make ssh-keysign use the requested signature algorithm - - and not the default for the keytype. Part of unbreaking hostbased auth for - RSA/SHA2 keys. ok markus@ - - OpenBSD-Commit-ID: b5639a14462948970da3a8020dc06f9a80ecccdc - -commit 291721bc7c840d113a49518f3fca70e86248b8e8 -Author: djm@openbsd.org -Date: Thu Jan 6 21:57:28 2022 +0000 - - upstream: stricter UpdateHostkey signature verification logic on - - the client- side. Require RSA/SHA2 signatures for RSA hostkeys except when - RSA/SHA1 was explicitly negotiated during initial KEX; bz3375 - - ok markus@ - - OpenBSD-Commit-ID: 46e75e8dfa2c813781805b842580dcfbd888cf29 - -commit 0fa33683223c76289470a954404047bc762be84c -Author: djm@openbsd.org -Date: Thu Jan 6 21:55:23 2022 +0000 - - upstream: Fix signature algorithm selection logic for - - UpdateHostkeys on the server side. The previous code tried to prefer RSA/SHA2 - for hostkey proofs of RSA keys, but missed some cases. This will use RSA/SHA2 - signatures for RSA keys if the client proposed these algorithms in initial - KEX. bz3375 - - Mostly by Dmitry Belyavskiy with some tweaks by me. - - ok markus@ - - OpenBSD-Commit-ID: c17ba0c3236340d2c6a248158ebed042ac6a8029 - -commit 17877bc81db3846e6e7d4cfb124d966bb9c9296b -Author: djm@openbsd.org -Date: Thu Jan 6 21:48:38 2022 +0000 - - upstream: convert ssh, sshd mainloops from select() to poll(); - - feedback & ok deraadt@ and markus@ has been in snaps for a few months - - OpenBSD-Commit-ID: a77e16a667d5b194dcdb3b76308b8bba7fa7239c - -commit 5c79952dfe1aa36105c93b3f383ce9be04dee384 -Author: djm@openbsd.org -Date: Thu Jan 6 21:46:23 2022 +0000 - - upstream: prepare for conversion of ssh, sshd mainloop from - - select() to poll() by moving FD_SET construction out of channel handlers into - separate functions. ok markus - - OpenBSD-Commit-ID: 937fbf2a4de12b19fb9d5168424e206124807027 - -commit 24c5187edfef4651a625b7d5d692c8c7e794f71f -Author: djm@openbsd.org -Date: Wed Jan 5 21:54:37 2022 +0000 - - upstream: add a comment so I don't make this mistake again - - OpenBSD-Commit-ID: 69c7f2362f9de913bb29b6318580c5a1b52c921e - -commit 7369900441929058263a17f56aa67e05ff7ec628 -Author: djm@openbsd.org -Date: Wed Jan 5 21:50:00 2022 +0000 - - upstream: fix cut-and-pasto in error message - - OpenBSD-Commit-ID: 4cc5c619e4b456cd2e9bb760d17e3a9c84659198 - -commit 294c11b1c7d56d3fb61e329603a782315ed70c62 -Author: djm@openbsd.org -Date: Wed Jan 5 08:25:05 2022 +0000 - - upstream: select all RSA hostkey algorithms for UpdateHostkeys tests, - - not just RSA-SHA1 - - OpenBSD-Regress-ID: b40e62b65863f2702a0c10aca583b2fe76772bd8 - -commit 2ea1108c30e3edb6f872dfc1e6da10b041ddf2c0 -Author: djm@openbsd.org -Date: Wed Jan 5 04:56:15 2022 +0000 - - upstream: regress test both sshsig message hash algorithms, possible - - now because the algorithm is controllable via the CLI - - OpenBSD-Regress-ID: 0196fa87acc3544b2b4fd98de844a571cb09a39f - -commit 2327c306b5d4a2b7e71178e5a4d139af9902c2b0 -Author: djm@openbsd.org -Date: Wed Jan 5 04:50:11 2022 +0000 - - upstream: allow selection of hash at sshsig signing time; code - - already supported either sha512 (default) or sha256, but plumbing wasn't - there mostly by Linus Nordberg - - OpenBSD-Commit-ID: 1b536404b9da74a84b3a1c8d0b05fd564cdc96cd - -commit 56e941d0a00d6d8bae88317717d5e1b7395c9529 -Author: djm@openbsd.org -Date: Wed Jan 5 04:27:54 2022 +0000 - - upstream: add missing -O option to usage() for ssh-keygen -Y sign; - - from Linus Nordberg - - OpenBSD-Commit-ID: 4e78feb4aa830727ab76bb2e3d940440ae1d7af0 - -commit 141a14ec9b0924709c98df2dd8013bde5d8d12c7 -Author: djm@openbsd.org -Date: Wed Jan 5 04:27:01 2022 +0000 - - upstream: move sig_process_opts() to before sig_sign(); no - - functional code change - - OpenBSD-Commit-ID: da02d61f5464f72b4e8b299f83e93c3b657932f9 - -commit 37a14249ec993599a9051731e4fb0ac5e976aec1 -Author: djm@openbsd.org -Date: Wed Jan 5 04:10:39 2022 +0000 - - upstream: regression test for find-principals NULL deref; from Fabian - - Stelzer - - OpenBSD-Regress-ID: f845a8632a5a7d5ae26978004c93e796270fd3e5 - -commit eb1f042142fdaba93f6c9560cf6c91ae25f6884a -Author: djm@openbsd.org -Date: Wed Jan 5 04:02:42 2022 +0000 - - upstream: NULL deref when using find-principals when matching an - - allowed_signers line that contains a namespace restriction, but no - restriction specified on the command-line; report and fix from Fabian Stelzer - - OpenBSD-Commit-ID: 4a201b86afb668c908d1a559c6af456a61f4b145 - -commit 8f3b18030579f395eca2181da31a5f945af12a59 -Author: dtucker@openbsd.org -Date: Tue Jan 4 08:38:53 2022 +0000 - - upstream: Log command invocation while debugging. - - This will aid in manually reproducing failing commands. - - OpenBSD-Regress-ID: b4aba8d5ac5675ceebeeeefa3261ce344e67333a - -commit bbf285164df535f0d38c36237f007551bbdae27f -Author: Darren Tucker -Date: Sun Dec 26 10:31:15 2021 +1100 - - Always save config.h as build artifact. - - Should allow better comparison between failing and succeeding test - platforms. - -commit 03bd4ed0db699687c5cd83405d26f81d2dc28d22 -Author: Darren Tucker -Date: Sat Dec 25 16:42:51 2021 +1100 - - Add OpenBSD 7.0 target. Retire 6.8. - -commit c45a752f0de611afd87755c2887c8a24816d08ee -Author: jsg@openbsd.org -Date: Sat Jan 1 05:55:06 2022 +0000 - - upstream: spelling - - OpenBSD-Commit-ID: c63e43087a64d0727af13409c708938e05147b62 - -commit c672f83a89a756564db0d3af9934ba0e1cf8fa3e -Author: djm@openbsd.org -Date: Tue Jan 4 07:20:33 2022 +0000 - - upstream: unbreak test: was picking up system ssh-add instead of the - - one supposedly being tested. Spotted by dtucker and using his VM zoo (which - includes some systems old enough to lack ed25519 key support) - - OpenBSD-Regress-ID: 7976eb3df11cc2ca3af91030a6a8c0cef1590bb5 - -commit a23698c3082ffe661abed14b020eac9b0c25eb9f -Author: djm@openbsd.org -Date: Sat Jan 1 04:18:06 2022 +0000 - - upstream: fix memleak in process_extension(); oss-fuzz issue #42719 - - OpenBSD-Commit-ID: d8d49f840162fb7b8949e3a5adb8107444b6de1e - -commit cb885178f36b83d0f14cfe9f345d2068103feed0 -Author: jsg@openbsd.org -Date: Sat Jan 1 01:55:30 2022 +0000 - - upstream: spelling ok dtucker@ - - OpenBSD-Commit-ID: bfc7ba74c22c928de2e257328b3f1274a3dfdf19 - -commit 6b977f8080a32c5b3cbb9edb634b9d5789fb79be -Author: djm@openbsd.org -Date: Sun Dec 26 23:34:41 2021 +0000 - - upstream: split method list search functionality from - - authmethod_lookup() into a separate authmethod_byname(), for cases where we - don't need to check whether a method is enabled, etc. - - use this to fix the "none" authentication method regression reported - by Nam Nguyen via bugs@ - - ok deraadt@ - - OpenBSD-Commit-ID: 8cd188dc3a83aa8abe5b7693e762975cd8ea8a17 - -commit 0074aa2c8d605ee7587279a22cdad4270b4ddd07 -Author: jmc@openbsd.org -Date: Wed Dec 22 06:56:41 2021 +0000 - - upstream: sort -H and -h in SYNOPSIS/usage(); tweak the -H text; - - ok djm - - OpenBSD-Commit-ID: 90721643e41e9e09deb5b776aaa0443456ab0965 - -commit 1c9853a68b2319f2e5f929179735e8fbb9988a67 -Author: Darren Tucker -Date: Wed Dec 22 19:33:10 2021 +1100 - - Use SHA.*_HMAC_BLOCK_SIZE if needed. - - If the platform has a native SHA2, does not define SHA.*_BLOCK_LENGTH - but does define SHA.*_HMAC_BLOCK_SIZE (eg Solaris) then use the latter. - Should fix --without-openssl build on Solaris. - -commit 715c892f0a5295b391ae92c26ef4d6a86ea96e8e -Author: Damien Miller -Date: Wed Dec 22 09:02:50 2021 +1100 - - remove sys/param.h in -portable, after upstream - -commit 7a7c69d8b4022b1e5c0afb169c416af8ce70f3e8 -Author: Damien Miller -Date: Mon Dec 20 13:05:20 2021 +1100 - - add agent-restrict.sh file, missed in last commit - -commit f539136ca51a4976644db5d0be8158cc1914c72a -Author: djm@openbsd.org -Date: Sun Dec 19 22:20:12 2021 +0000 - - upstream: regression test for destination restrictions in ssh-agent - - OpenBSD-Regress-ID: 3c799d91e736b1753b4a42d80c42fc40de5ad33d - -commit 6e4980eb8ef94c04874a79dd380c3f568e8416d6 -Author: anton@openbsd.org -Date: Sat Dec 18 06:53:59 2021 +0000 - - upstream: Make use of ntests variable, pointed out by clang 13. - - OpenBSD-Regress-ID: 4241a3d21bdfa1630ed429b6d4fee51038d1be72 - -commit 3eead8158393b697f663ec4301e3c7b6f24580b1 -Author: deraadt@openbsd.org -Date: Tue Dec 14 21:25:27 2021 +0000 - - upstream: sys/param.h cleanup, mostly using MINIMUM() and - - ok dtucker - - OpenBSD-Regress-ID: 172a4c45d3bcf92fa6cdf6c4b9db3f1b3abe4db0 - -commit 266678e19eb0e86fdf865b431b6e172e7a95bf48 -Author: djm@openbsd.org -Date: Sun Dec 19 22:15:42 2021 +0000 - - upstream: document host-bound publickey authentication - - OpenBSD-Commit-ID: ea6ed91779a81f06d961e30ecc49316b3d71961b - -commit 3d00024b3b156aa9bbd05d105f1deb9cb088f6f7 -Author: djm@openbsd.org -Date: Sun Dec 19 22:15:21 2021 +0000 - - upstream: document agent protocol extensions - - OpenBSD-Commit-ID: 09e8bb391bbaf24c409b75a4af44e0cac65405a7 - -commit c385abf76511451bcba78568167b1cd9e90587d5 -Author: djm@openbsd.org -Date: Sun Dec 19 22:14:47 2021 +0000 - - upstream: PubkeyAuthentication=yes|no|unbound|host-bound - - Allow control over which pubkey methods are used. Added out of - concern that some hardware devices may have difficulty signing - the longer pubkey authentication challenges. This provides a - way for them to disable the extension. It's also handy for - testing. - - feedback / ok markus@ - - OpenBSD-Commit-ID: ee52580db95c355cf6d563ba89974c210e603b1a - -commit 34b1e9cc7654f41cd4c5b1cc290b999dcf6579bb -Author: djm@openbsd.org -Date: Sun Dec 19 22:14:12 2021 +0000 - - upstream: document destination-constrained keys - - feedback / ok markus@ - - OpenBSD-Commit-ID: cd8c526c77268f6d91c06adbee66b014d22d672e - -commit a6d7677c4abcfba268053e5867f2acabe3aa371b -Author: djm@openbsd.org -Date: Sun Dec 19 22:13:55 2021 +0000 - - upstream: Use hostkey parsed from hostbound userauth request - - Require host-bound userauth requests for forwarded SSH connections. - - The hostkey parsed from the host-bound userauth request is now checked - against the most recently bound session ID / hostkey on the agent socket - and the signature refused if they do not match. - - ok markus@ - - OpenBSD-Commit-ID: d69877c9a3bd8d1189a5dbdeceefa432044dae02 - -commit baaff0ff4357cc5a079621ba6e2d7e247b765061 -Author: djm@openbsd.org -Date: Sun Dec 19 22:13:33 2021 +0000 - - upstream: agent support for parsing hostkey-bound signatures - - Allow parse_userauth_request() to work with blobs from - publickey-hostbound-v00@openssh.com userauth attempts. - - Extract hostkey from these blobs. - - ok markus@ - - OpenBSD-Commit-ID: 81c064255634c1109477dc65c3e983581d336df8 - -commit 3e16365a79cdeb2d758cf1da6051b1c5266ceed7 -Author: djm@openbsd.org -Date: Sun Dec 19 22:13:12 2021 +0000 - - upstream: EXT_INFO negotiation of hostbound pubkey auth - - the EXT_INFO packet gets a new publickey-hostbound@openssh.com to - advertise the hostbound public key method. - - Client side support to parse this feature flag and set the kex->flags - indicator if the expected version is offered (currently "0"). - - ok markus@ - - OpenBSD-Commit-ID: 4cdb2ca5017ec1ed7a9d33bda95c1d6a97b583b0 - -commit 94ae0c6f0e35903b695e033bf4beacea1d376bb1 -Author: djm@openbsd.org -Date: Sun Dec 19 22:12:54 2021 +0000 - - upstream: client side of host-bound pubkey authentication - - Add kex->flags member to enable the publickey-hostbound-v00@openssh.com - authentication method. - - Use the new hostbound method in client if the kex->flags flag was set, - and include the inital KEX hostkey in the userauth request. - - Note: nothing in kex.c actually sets the new flag yet - - ok markus@ - - OpenBSD-Commit-ID: 5a6fce8c6c8a77a80ee1526dc467d91036a5910d - -commit 288fd0218dbfdcb05d9fbd1885904bed9b6d42e6 -Author: djm@openbsd.org -Date: Sun Dec 19 22:12:30 2021 +0000 - - upstream: sshd side of hostbound public key auth - - This is identical to the standard "publickey" method, but it also includes - the initial server hostkey in the message signed by the client. - - feedback / ok markus@ - - OpenBSD-Commit-ID: 7ea01bb7238a560c1bfb426fda0c10a8aac07862 - -commit dbb339f015c33d63484261d140c84ad875a9e548 -Author: djm@openbsd.org -Date: Sun Dec 19 22:12:07 2021 +0000 - - upstream: prepare for multiple names for authmethods - - allow authentication methods to have one additional name beyond their - primary name. - - allow lookup by this synonym - - Use primary name for authentication decisions, e.g. for - PermitRootLogin=publickey - - Pass actual invoked name to the authmethods, so they can tell whether they - were requested via the their primary name or synonym. - - ok markus@ - - OpenBSD-Commit-ID: 9e613fcb44b8168823195602ed3d09ffd7994559 - -commit 39f00dcf44915f20684160f0a88d3ef8a3278351 -Author: djm@openbsd.org -Date: Sun Dec 19 22:11:39 2021 +0000 - - upstream: ssh-agent side of destination constraints - - Gives ssh-agent the ability to parse restrict-destination-v00@openssh.com - constraints and to apply them to keys. - - Check constraints against the hostkeys recorded for a SocketEntry when - attempting a signature, adding, listing or deleting keys. Note that - the "delete all keys" request will remove constrained keys regardless of - location. - - feedback Jann Horn & markus@ - ok markus@ - - OpenBSD-Commit-ID: 84a7fb81106c2d609a6ac17469436df16d196319 - -commit ce943912df812c573a33d00bf9e5435b7fcca3f7 -Author: djm@openbsd.org -Date: Sun Dec 19 22:11:06 2021 +0000 - - upstream: ssh-add side of destination constraints - - Have ssh-add accept a list of "destination constraints" that allow - restricting where keys may be used in conjunction with a ssh-agent/ssh - that supports session ID/hostkey binding. - - Constraints are specified as either "[user@]host-pattern" or - "host-pattern>[user@]host-pattern". - - The first form permits a key to be used to authenticate as the - specified user to the specified host. - - The second form permits a key that has previously been permitted - for use at a host to be available via a forwarded agent to an - additional host. - - For example, constraining a key with "user1@host_a" and - "host_a>host_b". Would permit authentication as "user1" at - "host_a", and allow the key to be available on an agent forwarded - to "host_a" only for authentication to "host_b". The key would not - be visible on agent forwarded to other hosts or usable for - authentication there. - - Internally, destination constraints use host keys to identify hosts. - The host patterns are used to obtain lists of host keys for that - destination that are communicated to the agent. The user/hostkeys are - encoded using a new restrict-destination-v00@openssh.com key - constraint. - - host keys are looked up in the default client user/system known_hosts - files. It is possible to override this set on the command-line. - - feedback Jann Horn & markus@ - ok markus@ - - OpenBSD-Commit-ID: 6b52cd2b637f3d29ef543f0ce532a2bce6d86af5 - -commit 5e950d765727ee0b20fc3d2cbb0c790b21ac2425 -Author: djm@openbsd.org -Date: Sun Dec 19 22:10:24 2021 +0000 - - upstream: ssh-add side of destination constraints - - Have ssh-add accept a list of "destination constraints" that allow - restricting where keys may be used in conjunction with a ssh-agent/ssh - that supports session ID/hostkey binding. - - Constraints are specified as either "[user@]host-pattern" or - "host-pattern>[user@]host-pattern". - - The first form permits a key to be used to authenticate as the - specified user to the specified host. - - The second form permits a key that has previously been permitted - for use at a host to be available via a forwarded agent to an - additional host. - - For example, constraining a key with "user1@host_a" and - "host_a>host_b". Would permit authentication as "user1" at - "host_a", and allow the key to be available on an agent forwarded - to "host_a" only for authentication to "host_b". The key would not - be visible on agent forwarded to other hosts or usable for - authentication there. - - Internally, destination constraints use host keys to identify hosts. - The host patterns are used to obtain lists of host keys for that - destination that are communicated to the agent. The user/hostkeys are - encoded using a new restrict-destination-v00@openssh.com key - constraint. - - host keys are looked up in the default client user/system known_hosts - files. It is possible to override this set on the command-line. - - feedback Jann Horn & markus@ - ok markus@ - - OpenBSD-Commit-ID: ef47fa9ec0e3c2a82e30d37ef616e245df73163e - -commit 4c1e3ce85e183a9d0c955c88589fed18e4d6a058 -Author: djm@openbsd.org -Date: Sun Dec 19 22:09:23 2021 +0000 - - upstream: ssh-agent side of binding - - record session ID/hostkey/forwarding status for each active socket. - - Attempt to parse data-to-be-signed at signature request time and extract - session ID from the blob if it is a pubkey userauth request. - - ok markus@ - - OpenBSD-Commit-ID: a80fd41e292b18b67508362129e9fed549abd318 - -commit e9497ecf73f3c16667288bce48d4e3d7e746fea1 -Author: djm@openbsd.org -Date: Sun Dec 19 22:08:48 2021 +0000 - - upstream: ssh client side of binding - - send session ID, hostkey, signature and a flag indicating whether the - agent connection is being forwarded to ssh agent each time a connection - is opened via a new "session-bind@openssh.com" agent extension. - - ok markus@ - - OpenBSD-Commit-ID: 2f154844fe13167d3ab063f830d7455fcaa99135 - -commit b42c61d6840d16ef392ed0f365e8c000734669aa -Author: djm@openbsd.org -Date: Sun Dec 19 22:08:06 2021 +0000 - - upstream: Record session ID, host key and sig at intital KEX - - These will be used later for agent session ID / hostkey binding - - ok markus@ - - OpenBSD-Commit-ID: a9af29e33772b18e3e867c6fa8ab35e1694a81fe - -commit 26ca33d186473d58a32d812e19273ce078b6ffff -Author: djm@openbsd.org -Date: Tue Dec 7 22:06:45 2021 +0000 - - upstream: better error message for FIDO keys when we can't match - - them to a token - - OpenBSD-Commit-ID: 58255c2a1980088f4ed144db67d879ada2607650 - -commit adb0ea006d7668190f0c42aafe3a2864d352e34a -Author: Darren Tucker -Date: Wed Dec 15 10:50:33 2021 +1100 - - Correct value for IPTOS_DSCP_LE. - - It needs to allow for the preceeding two ECN bits. From daisuke.higashi - at gmail.com via OpenSSH bz#3373, ok claudio@, job@, djm@. - -commit 3dafd3fe220bd9046f11fcf5191a79ec8800819f -Author: Darren Tucker -Date: Fri Dec 10 11:57:30 2021 +1100 - - Increase timeout for test step. - -commit 5aefb05cd5b843e975b191d6ebb7ddf8de35c112 -Author: Darren Tucker -Date: Fri Dec 10 10:27:27 2021 +1100 - - Update the list of tests that don't work on Minix. - - While there, remove CC (configure will now find clang) and make the test - list easier to update via cut and paste. - -commit 1c09bb1b2e207d091cec299c49416c23d24a1b31 -Author: Darren Tucker -Date: Fri Dec 10 10:12:57 2021 +1100 - - Add minix host tuple. - - Define SETEUID_BREAKS_SETUID for it which should make privsep work. - -commit a2188579032cf080213a78255373263466cb90cc -Author: jsg@openbsd.org -Date: Sun Dec 5 12:28:27 2021 +0000 - - upstream: fix unintended sizeof pointer in debug path ok markus@ - - OpenBSD-Commit-ID: b9c0481ffc0cd801e0840e342e6a282a85aac93c - -commit da40355234068c82f1a36196f2d18dd2d81aaafd -Author: naddy@openbsd.org -Date: Sat Dec 4 00:05:39 2021 +0000 - - upstream: RSA/SHA-1 is not used by default anymore on the server - - OpenBSD-Commit-ID: 64abef6cfc3e53088225f6b8a1dcd86d52dc8353 - -commit e9c71498a083a8b502aa831ea931ce294228eda0 -Author: djm@openbsd.org -Date: Thu Dec 2 23:45:36 2021 +0000 - - upstream: hash full host:port when asked to hash output, fixes hashes - - for non- default ports. bz3367 ok dtucker@ - - OpenBSD-Commit-ID: 096021cc847da7318ac408742f2d0813ebe9aa73 - -commit b5601202145a03106012c22cb8980bcac2949f0b -Author: djm@openbsd.org -Date: Thu Dec 2 23:23:13 2021 +0000 - - upstream: improve the testing of credentials against inserted FIDO - - keys a little more: ask the token whether a particular key belongs to it in - cases where the token support on-token user- verification (e.g. biometrics) - rather than just assuming that it will accept it. - - Will reduce spurious "Confirm user presence" notifications for key - handles that relate to FIDO keys that are not currently inserted in at - least some cases. - - Motivated by bz3366; by Pedro Martelletto - - OpenBSD-Commit-ID: ffac7f3215842397800e1ae2e20229671a55a63d - -commit ca709e27c41c90f4565b17282c48dca7756e083c -Author: djm@openbsd.org -Date: Thu Dec 2 22:40:05 2021 +0000 - - upstream: move check_sk_options() up so we can use it earlier - - OpenBSD-Commit-ID: 67fe98ba1c846d22035279782c4664c1865763b4 - -commit b711bc01a7ec76bb6a285730990cbce9b8ca5773 -Author: dtucker@openbsd.org -Date: Thu Dec 2 22:35:05 2021 +0000 - - upstream: ssh-rsa is no longer in the default for - - PubkeyAcceptedAlgorithms. - - OpenBSD-Commit-ID: 34a9e1bc30966fdcc922934ae00f09f2596cd73c - -commit dc91ceea33cd4a9f05be953e8d8062f732db5c8a -Author: djm@openbsd.org -Date: Thu Dec 2 02:44:44 2021 +0000 - - upstream: don't put the tty into raw mode when SessionType=none, avoids - - ^c being unable to kill such a session. bz3360; ok dtucker@ - - OpenBSD-Commit-ID: 83960c433052303b643b4c380ae2f799ac896f65 - -commit e6e7d2654a13ba10141da7b42ea683ea4eeb1f38 -Author: Damien Miller -Date: Mon Nov 29 14:11:03 2021 +1100 - - previous commit broke bcrypt_pbkdf() - - Accidentally reverted part of the conversion to use SHA512 from SUPERCOP - instead of OpenBSD-style libc SHA512. - -commit c0459588b8d00b73e506c6095958ecfe62a4a7ba -Author: Darren Tucker -Date: Mon Nov 29 14:03:19 2021 +1100 - - Fix typo in Neils' name. - -commit 158bf854e2a22cf09064305f4a4e442670562685 -Author: Damien Miller -Date: Mon Nov 29 12:30:22 2021 +1100 - - sync bcrypt-related files with OpenBSD - - The main change is that Niels Provos kindly agreed to rescind the - BSD license advertising clause, shifting them to the 3-term BSD - license. - - This was the last thing in OpenSSH that used the advertising clause. - -commit e8976d92a42883ff6b8991438f07df60c2c0d82d -Author: Damien Miller -Date: Mon Nov 29 12:29:29 2021 +1100 - - depend - -commit 8249afeec013e557fe7491a72ca3285de03e25b1 -Author: djm@openbsd.org -Date: Sun Nov 28 07:21:26 2021 +0000 - - upstream: sshsig: return "key not found" when searching empty files - - rather than "internal error" - - OpenBSD-Commit-ID: e2ccae554c78d7a7cd33fc5d217f35be7e2507ed - -commit 9e3227d4dbb5ad9c9091b4c14982cab4bba87b4d -Author: djm@openbsd.org -Date: Sun Nov 28 07:15:10 2021 +0000 - - upstream: ssh-keygen -Y match-principals doesn't accept any -O - - options at present, so don't say otherwise in SYNOPSIS; spotted jmc@ - - OpenBSD-Commit-ID: 9cc43a18f4091010741930b48b3db2f2e4f1d35c - -commit 56db1f4a4cf5039fc3b42e84c4b16291fdff32b1 -Author: djm@openbsd.org -Date: Sun Nov 28 07:14:29 2021 +0000 - - upstream: fix indenting in last commit - - OpenBSD-Commit-ID: 8b9ba989815d0dec1fdf5427a4a4b58eb9cac4d2 - -commit 50bea24a9a9bdebad327c76e700def3261f5694e -Author: djm@openbsd.org -Date: Sun Nov 28 07:10:18 2021 +0000 - - upstream: missing initialisation for oerrno - - OpenBSD-Commit-ID: 05d646bba238080259bec821c831a6f0b48d2a95 - -commit 5a0f4619041d09cd29f3a08da41db5040372bdd1 -Author: Darren Tucker -Date: Sun Nov 28 15:31:37 2021 +1100 - - Correct ifdef to activate poll() only if needed. - -commit d4035c81a71237f690edd7eda32bef7d63fd9528 -Author: djm@openbsd.org -Date: Sat Nov 27 07:23:35 2021 +0000 - - upstream: whitespac e - - OpenBSD-Regress-ID: b9511d41568056bda489e13524390167889908f8 - -commit a443491e6782ef0f5a8bb87a5536c8ee4ff233a1 -Author: djm@openbsd.org -Date: Sat Nov 27 07:20:58 2021 +0000 - - upstream: regression test for match-principals. Mostly by Fabian - - Stelzer - - OpenBSD-Regress-ID: ced0bec89af90935103438986bbbc4ad1df9cfa7 - -commit 78230b3ec8cbabc1e7de68732dc5cbd4837c6675 -Author: djm@openbsd.org -Date: Sat Nov 27 07:14:46 2021 +0000 - - upstream: Add ssh-keygen -Y match-principals operation to perform - - matching of principals names against an allowed signers file. - - Requested by and mostly written by Fabian Stelzer, towards a TOFU - model for SSH signatures in git. Some tweaks by me. - - "doesn't bother me" deraadt@ - - OpenBSD-Commit-ID: 8d1b71f5a4127bc5e10a880c8ea6053394465247 - -commit 15db86611baaafb24c40632784dabf82e3ddb1a7 -Author: djm@openbsd.org -Date: Thu Nov 25 23:02:24 2021 +0000 - - upstream: debug("func: ...") -> debug_f("...") - - OpenBSD-Commit-ID: d58494dc05c985326a895adfbe16fbd5bcc54347 - -commit b7ffbb17e37f59249c31f1ff59d6c5d80888f689 -Author: Darren Tucker -Date: Fri Nov 19 18:53:46 2021 +1100 - - Allow for fd = -1 in compat ppoll overflow check. - - Fixes tests on at least FreeBSD 6, possibly others. - -commit 04b172da5b96a51b0d55c905b423ababff9f4e0b -Author: Darren Tucker -Date: Fri Nov 19 16:01:51 2021 +1100 - - Don't auto-enable Capsicum sandbox on FreeBSD 9/10. - - Since we changed from select() to ppoll() tests have been failing. - This seems to be because FreeBSD 10 (and presumably 9) do not allow - ppoll() in the privsep process and sshd will fail with "Not permitted in - capability mode". Setting CAP_EVENT on the FDs doesn't help, but weirdly, - poll() works without that. Those versions are EOL so this situation is - unlikely to change. - -commit a823f39986e7b879f26412e64c15630e1cfa0dc5 -Author: djm@openbsd.org -Date: Thu Nov 18 03:53:48 2021 +0000 - - upstream: regression test for ssh-keygen -Y find-principals fix; from - - Fabian Stelzer ok djm markus - - OpenBSD-Regress-ID: 34fe4088854c1a2eb4c0c51cc4676ba24096bac4 - -commit 199c4df66c0e39dd5c3333b162af274678c0501d -Author: djm@openbsd.org -Date: Thu Nov 18 21:32:11 2021 +0000 - - upstream: less confusing debug message; bz#3365 - - OpenBSD-Commit-ID: 836268d3642c2cdc84d39b98d65837f5241e4a50 - -commit 97f9b6e61316c97a32dad94b7a37daa9b5f6b836 -Author: djm@openbsd.org -Date: Thu Nov 18 21:11:01 2021 +0000 - - upstream: avoid xmalloc(0) for PKCS#11 keyid for ECDSA keys (we - - already did this for RSA keys). Avoids fatal errors for PKCS#11 libraries - that return empty keyid, e.g. Microchip ATECC608B "cryptoauthlib"; bz#3364 - - OpenBSD-Commit-ID: 054d4dc1d6a99a2e6f8eebc48207b534057c154d - -commit c74aa0eb73bd1edf79947d92d9c618fc3424c4a6 -Author: djm@openbsd.org -Date: Thu Nov 18 03:50:41 2021 +0000 - - upstream: ssh-keygen -Y find-principals was verifying key validity - - when using ca certs but not with simple key lifetimes within the allowed - signers file. - - Since it returns the first keys principal it finds this could - result in a principal with an expired key even though a valid - one is just below. - - patch from Fabian Stelzer; feedback/ok djm markus - - OpenBSD-Commit-ID: b108ed0a76b813226baf683ab468dc1cc79e0905 - -commit d902d728dfd81622454260e23bc09d5e5a9a795e -Author: Darren Tucker -Date: Thu Nov 18 23:44:07 2021 +1100 - - Correct calculation of tv_nsec in poll(). - -commit 21dd5a9a3fb35e8299a1fbcf8d506f1f6b752b85 -Author: Darren Tucker -Date: Thu Nov 18 23:11:37 2021 +1100 - - Add compat implementation of ppoll using pselect. - -commit b544ce1ad4afb7ee2b09f714aa63efffc73fa93a -Author: Darren Tucker -Date: Thu Nov 18 23:05:34 2021 +1100 - - Put poll.h inside ifdef HAVE_POLL_H. - -commit 875408270c5a7dd69ed5449e5d85bd7120c88f70 -Author: djm@openbsd.org -Date: Thu Nov 18 03:31:44 2021 +0000 - - upstream: check for POLLHUP wherever we check for POLLIN - - OpenBSD-Commit-ID: 6aa6f3ec6b17c3bd9bfec672a917f003a76d93e5 - -commit 36b5e37030d35bbaa18ba56825b1af55971d18a0 -Author: djm@openbsd.org -Date: Thu Nov 18 03:07:59 2021 +0000 - - upstream: fd leak in sshd listen loop error path; from Gleb - - Smirnoff - - OpenBSD-Commit-ID: a7a2be27a690a74bf2381bc16cea38e265657412 - -commit b99498d0c93f1edd04857b318308a66b28316bd8 -Author: djm@openbsd.org -Date: Thu Nov 18 03:07:20 2021 +0000 - - upstream: check for POLLHUP as well as POLLIN in sshd listen loop; - - ok deraadt millert - - OpenBSD-Commit-ID: a4f1244c5a9c2b08dac4f3b1dc22e9d1dc60c587 - -commit 1f3055d788e8cf80851eb1728b535d57eb0dba6a -Author: djm@openbsd.org -Date: Thu Nov 18 03:06:03 2021 +0000 - - upstream: check for POLLHUP as well as POLLIN, handle transient IO - - errors as well as half-close on the output side; ok deraadt millert - - OpenBSD-Commit-ID: de5c5b9939a37476d256328cbb96305bdecf511e - -commit 9778a15fa6dbdac6a95bf15865c2688b4bd6944e -Author: Damien Miller -Date: Thu Nov 18 10:16:55 2021 +1100 - - adjust seccomp filter for select->poll conversion - - Needed to add ppoll syscall but also to relax the fallback rlimit - sandbox. Linux poll() fails with EINVAL if npfds > RLIMIT_NOFILE, - so we have to allow a single fd in the rlimit. - -commit fcd8d895bbb849c64f0aed934e3303d37f696f5d -Author: Damien Miller -Date: Thu Nov 18 10:16:44 2021 +1100 - - update depends - -commit 76292787a1e93e668f10e36b4bf59ce0ae28e156 -Author: Damien Miller -Date: Thu Nov 18 09:26:20 2021 +1100 - - compat for timespecsub() and friends - -commit fd7e7de4ddb4399c7e929b44f2bbfc118eddfcf8 -Author: djm@openbsd.org -Date: Wed Nov 17 21:06:39 2021 +0000 - - upstream: set num_listen_socks to 0 on close-all instead of -1, - - which interferes with the new poll()-based listen loop; spotted and debugged - by anton@+deraadt@ - - OpenBSD-Commit-ID: f7ab8ab124f615a2e0c45fee14c38d2f2abbabbd - -commit fd9343579afac30a971f06643a669733d9acb407 -Author: deraadt@openbsd.org -Date: Sun Nov 14 18:47:43 2021 +0000 - - upstream: use ppoll() instead of pselect() with djm - - OpenBSD-Commit-ID: 980f87c9564d5d2ad55722b7a6f44f21284cd215 - -commit 092d29b232ef1a19609a5316ed7e4d896bb2e696 -Author: deraadt@openbsd.org -Date: Sun Nov 14 06:15:36 2021 +0000 - - upstream: match .events with .fd better - - OpenBSD-Commit-ID: 77eef212ca0add905949532af390164489c5984b - -commit 8d642c9a90fa4ed5a3effd785fb3591e14de00cd -Author: deraadt@openbsd.org -Date: Sun Nov 14 03:25:10 2021 +0000 - - upstream: convert select() to poll() ok djm - - OpenBSD-Commit-ID: b53e4940ff10dd24f8d16e8db8ef1970015d7ead - -commit 6582a31c388968f4073af2bd8621880735c3d42b -Author: deraadt@openbsd.org -Date: Sat Nov 13 21:14:13 2021 +0000 - - upstream: replace select() with ppoll(), including converting - - timeval's to timespec's to make things easier. back and forth and ok; djm - - OpenBSD-Commit-ID: 89d3b23c60875da919e7820f9de6213286ffbec9 - -commit 7c025c005550c86a40200a2bcdd355d09413d61a -Author: deraadt@openbsd.org -Date: Sat Nov 13 17:26:13 2021 +0000 - - upstream: It really looks like pledge "stdio dns" is possible - - earlier. Discussed with mestre - - OpenBSD-Commit-ID: 610873de63a593e0ac7bbbcb7a0f2894d36f4c01 - -commit 06acb04c20ee483fe4757bd12aec870cc4bb1076 -Author: deraadt@openbsd.org -Date: Fri Nov 12 05:23:49 2021 +0000 - - upstream: aggressively pre-fill the pollfd array with fd=-1 - - OpenBSD-Commit-ID: c2a525de8f83c1a04405bd79122c424140552a5b - -commit 7eec76793dec06e8f06b6cf71f9473141c69d109 -Author: deraadt@openbsd.org -Date: Thu Nov 11 15:32:32 2021 +0000 - - upstream: Convert from select() to ppoll(). Along the way, I - - observed that the select() code was using exceptfds incorrectly.. ok millert - - OpenBSD-Commit-ID: 548e05bfc31b2af02319eb3d051286d4128dec96 - -commit e665ed2d0c24fe11d5470ce72fa1e187377d3fc4 -Author: Darren Tucker -Date: Fri Nov 12 22:55:27 2021 +1100 - - Switch from LibreSSL 3.4.0 to 3.4.1. - - The LibreSSL 3.4.0 release has an OPENBSD_BRANCH that points to - "master" and that branch no longer has the files LibreSSL expects - and thus it will no longer build, breaking the test. - -commit 21b6b5a06c8c53c548d25e6074c5240e88e2ef34 -Author: djm@openbsd.org -Date: Wed Nov 10 06:29:25 2021 +0000 - - upstream: add the sntrup761x25519-sha512@openssh.com hybrid - - ECDH/x25519 + Streamlined NTRU Prime post-quantum KEX to the default - KEXAlgorithms list (after the ECDH methods but before the prime-group DH - ones). - - ok markus@ - - OpenBSD-Commit-ID: 22b77e27a04e497a10e22f138107579652854210 - -commit 239da797cbf07a640d7b1ea02d3f99ace3ef792d -Author: djm@openbsd.org -Date: Wed Nov 10 06:25:08 2021 +0000 - - upstream: fix ssh-keysign for KEX algorithms that use SHA384/512 - - exchange hashes; feedback/ok markus@ - - OpenBSD-Commit-ID: 09a8fda1c081f5de1e3128df64f28b7bdadee239 - -commit 6997a592ecb1013df0c6d7f8df3e6517827aef11 -Author: djm@openbsd.org -Date: Mon Nov 8 21:32:49 2021 +0000 - - upstream: improve error message when trying to expand a ~user path - - for a user that doesn't exist; better matches what the shell does - - ok deraadt@ - - OpenBSD-Commit-ID: 1ddefa3c3a78b69ce13d1b8f67bc9f2cefd23ad6 - -commit 10b899a15c88eb40eb5f73cd0fa84ef0966f79c9 -Author: Darren Tucker -Date: Wed Nov 10 12:34:25 2021 +1100 - - Don't trust closefrom() on Linux. - - glibc's closefrom implementation does not work in a chroot when the kernel - does not have close_range. It tries to read from /proc/self/fd and when - that fails dies with an assertion of sorts. Instead, call close_range - ourselves from our compat code and fall back if that fails. bz#3349, - with william.wilson at canonical.com and fweimer at redhat.com. - -commit eb1f63195a9a38b519536a5b398d9939261ec081 -Author: dtucker@openbsd.org -Date: Sat Nov 6 10:13:39 2021 +0000 - - upstream: Plug a couple of minor mem leaks. From beldmit at - - gmail.com via github PR#283, ok markus@ - - OpenBSD-Commit-ID: ec1fa7d305d46226861c3ca6fb9c9beb2ada2892 - -commit e4f501bf1d3b53f1cc23d9521fd7c5163307b760 -Author: djm@openbsd.org -Date: Fri Nov 5 03:10:58 2021 +0000 - - upstream: move cert_filter_principals() to earlier in the file for - - reuse; no code change - - OpenBSD-Commit-ID: 598fa9528b656b2f38bcc3cf5b6f3869a8c115cf - -commit 59c60f96fee321c7f38f00372826d37f289534af -Author: deraadt@openbsd.org -Date: Wed Nov 3 22:00:56 2021 +0000 - - upstream: Many downstreams expect ssh to compile as non-C99... - - OpenBSD-Commit-ID: e6aa3e08bda68e5fb838fc8a49b1d2dfc38ee783 - -commit 7a78fe63b0b28ef7231913dfefe9d08f9bc41c61 -Author: Darren Tucker -Date: Sat Nov 6 21:07:03 2021 +1100 - - Skip getline() on HP-UX 10.x. - - HP-UX 10.x has a getline() implementation in libc that does not behave - as we expect so don't use it. With correction from Thorsten Glaser and - typo fix from Larkin Nickle. - -commit 343ae252ebb35c6ecae26b447bf1551a7666720e -Author: Damien Miller -Date: Wed Nov 3 12:08:21 2021 +1100 - - basic SECURITY.md (refers people to the website) - -commit ed45a0168638319e0a710633f6085b96b9cec656 -Author: djm@openbsd.org -Date: Tue Nov 2 22:57:27 2021 +0000 - - upstream: crank SSH_SK_VERSION_MAJOR to match recent change in - - usr/bin/ssh - - OpenBSD-Regress-ID: 113d181c7e3305e138db9b688cdb8b0a0019e552 - -commit f3c34df860c4c1ebddacb973954e58167d9dbade -Author: djm@openbsd.org -Date: Tue Nov 2 22:56:40 2021 +0000 - - upstream: Better handle FIDO keys on tokens that provide user - - verification (UV) on the device itself, including biometric keys. - - Query the token during key creation to determine whether it supports - on-token UV and, if so, clear the SSH_SK_USER_VERIFICATION_REQD flag - in the key so that ssh(1) doesn't automatically prompty for PIN later. - - When making signatures with the key, query the token's capabilities - again and check whether the token is able (right now) to perform user- - verification without a PIN. If it is then the PIN prompt is bypassed - and user verification delegated to the token. If not (e.g. the token - is biometric capable, but no biometric are enrolled), then fall back - to user verification via the usual PIN prompt. - - Work by Pedro Martelletto; ok myself and markus@ - - NB. cranks SSH_SK_VERSION_MAJOR - - OpenBSD-Commit-ID: e318a8c258d9833a0b7eb0236cdb68b5143b2f27 - -commit 0328a081f38c09d2d4d650e94461a47fb5eef536 -Author: djm@openbsd.org -Date: Fri Oct 29 03:03:06 2021 +0000 - - upstream: sshsig: add tests for signing key validity and - - find-principals - - - adds generic find-principals tests (this command had none before) - - tests certs with a timeboxed validity both with and without a - restriced lifetime for the CA - - test for a revoked CA cert - - by Fabian Stelzer - - OpenBSD-Regress-ID: 9704b2c6df5b8ccfbdf2c06c5431f5f8cad280c9 - -commit ccd358e1e25e25c13f0825996283cbf7a1647a3b -Author: djm@openbsd.org -Date: Fri Oct 29 02:48:19 2021 +0000 - - upstream: avoid signedness warning; spotted in -portable - - OpenBSD-Regress-ID: 4cacc126086487c0ea7f3d86b42dec458cf0d0c6 - -commit 2741f52beb11490d7033a25e56ed0496f0c78006 -Author: djm@openbsd.org -Date: Fri Oct 29 03:20:46 2021 +0000 - - upstream: ssh-keygen: make verify-time argument parsing optional - - From Fabian Stelzer - - OpenBSD-Commit-ID: 1ff35e4c366a45a073663df90381be6a8ef4d370 - -commit a1217d363b88b32cfe54c4f02c6c1cf4bdefdd23 -Author: Damien Miller -Date: Fri Oct 29 13:48:34 2021 +1100 - - unbreak fuzz harness for recent changes - -commit 68e522ed8183587c9367fa3842c5b75f64f3d12b -Author: Darren Tucker -Date: Fri Oct 29 13:32:24 2021 +1100 - - Use -Wbitwise-instead-of-logical if supported. - -commit be28b23012aa3fa323be7ec84863cf238927c078 -Author: Damien Miller -Date: Thu Oct 28 16:24:53 2021 +1100 - - use -Wmisleading-indentation cflag if available - - ok dtucker@ - -commit 2e6f5f24dd2f9217f4ab8b737ed428d5d5278f91 -Author: Damien Miller -Date: Thu Oct 28 16:24:44 2021 +1100 - - depend - -commit a5ab4882348d26addc9830a44e053238dfa2cb58 -Author: Damien Miller -Date: Thu May 6 10:08:30 2021 +1000 - - remove built-in support for md5crypt() - - Users of MD5-hashed password should arrange for ./configure to link - against libxcrypt or similar. Though it would be better to avoid use - of MD5 password hashing entirely, it's arguably worse than DEScrypt. - - feedback and ok dtucker@ - -commit c5de1fffa6328b8246b87da28fa9df05813f76a3 -Author: djm@openbsd.org -Date: Thu Oct 28 02:55:30 2021 +0000 - - upstream: increment SSH_SK_VERSION_MAJOR to match last change - - OpenBSD-Regress-ID: 17873814d1cbda97f49c8528d7b5ac9cadf6ddc0 - -commit 0001d04e55802d5bd9d6dece1081a99aa4ba2828 -Author: djm@openbsd.org -Date: Thu Oct 28 02:54:18 2021 +0000 - - upstream: When downloading resident keys from a FIDO token, pass - - back the user ID that was used when the key was created and append it to the - filename the key is written to (if it is not the default). - - Avoids keys being clobbered if the user created multiple - resident keys with the same application string but different - user IDs. - - feedback Pedro Martelletto; ok markus - - NB. increments SSH_SK_VERSION_MAJOR - - OpenBSD-Commit-ID: dbd658b5950f583106d945641a634bc6562dd3a3 - -commit d4bed5445646e605c383a4374fa962e23bf9e3a3 -Author: deraadt@openbsd.org -Date: Sun Oct 24 21:24:17 2021 +0000 - - upstream: For open/openat, if the flags parameter does not contain - - O_CREAT, the 3rd (variadic) mode_t parameter is irrelevant. Many developers - in the past have passed mode_t (0, 044, 0644, or such), which might lead - future people to copy this broken idiom, and perhaps even believe this - parameter has some meaning or implication or application. Delete them all. - This comes out of a conversation where tb@ noticed that a strange (but - intentional) pledge behaviour is to always knock-out high-bits from mode_t on - a number of system calls as a safety factor, and his bewilderment that this - appeared to be happening against valid modes (at least visually), but no - sorry, they are all irrelevant junk. They could all be 0xdeafbeef. ok - millert - - OpenBSD-Commit-ID: 503d11633497115688c0c6952686524f01f53121 - -commit d575cf44895104e0fcb0629920fb645207218129 -Author: Darren Tucker -Date: Fri Oct 22 23:27:41 2021 +1100 - - kitchensink test target now needs krb5. - -commit 4ae39cada214e955bcfd3448ff28f0ed18886706 -Author: Darren Tucker -Date: Fri Oct 22 22:54:33 2021 +1100 - - Test both MIT KRB5 and Heimdal. - -commit 22b2681d88619e5247dc53c9f112058a7e248d48 -Author: dtucker@openbsd.org -Date: Fri Oct 22 10:51:57 2021 +0000 - - upstream: Plug mem addrinfo mem leaks. - - Prevent mem leaks in the (unlikely) event that getaddrinfo returns - no addresses. ALso, remove an unneeded NULL check in addr_ntop. From - khaleesicodes via github PR#281, ok deraadt@ - - OpenBSD-Commit-ID: e8a5afc686376637c355c5f7e122dc4b080b9c1a - -commit 27c8c343b610263f83ac2328735feeb881c6c92f -Author: dtucker@openbsd.org -Date: Fri Oct 22 09:22:04 2021 +0000 - - upstream: Remove unnecessary semicolons - - ... in case statements. From khaleesicodes via github PR#280. - - OpenBSD-Commit-ID: e1e89360b65775cff83e77ce040b342015caf4ed - -commit e7eb73b8d1fe1008d92433ea949491ce654bfaba -Author: dtucker@openbsd.org -Date: Fri Oct 22 09:19:34 2021 +0000 - - upstream: Fix typos in comments. - - From khaleesicodes via github PR#280. - - OpenBSD-Commit-ID: 26fdd83652c40f098bf7c685e8ebb9eb72cc45fc - -commit 052a9d8494175e24312daa6c132665e58c17fe6e -Author: deraadt@openbsd.org -Date: Fri Oct 15 14:46:46 2021 +0000 - - upstream: switch scp(1) back to sftp protocol. - - openbsd 7.0 release shipped with the (hopefully last) scp that uses RCP - protocol for copying. Let's get back to testing the SFTP protocol. - - OpenBSD-Commit-ID: 9eaa35d95fd547b78b0a043b3f518e135f151f30 - -commit a07664646bf6d293f5bbd45a5de54f3c36bb85da -Author: Darren Tucker -Date: Fri Oct 22 14:00:05 2021 +1100 - - Source configs script so setup_ci can use settings - -commit 34df52c201c6b47e5a46b50c215e4d98a8bf6587 -Author: Darren Tucker -Date: Fri Oct 22 09:42:14 2021 +1100 - - Install libedit and pam based on config flags. - -commit 8c626cc563e8d21d844d06f9971a9ee01de6aa2a -Author: Darren Tucker -Date: Thu Oct 21 16:53:39 2021 +1100 - - Don't use 'here string", it's not POSIX. - -commit 086a4b5977472aefa3de918b88efad0faf83b2b1 -Author: Darren Tucker -Date: Thu Oct 21 15:33:27 2021 +1100 - - Remove -Werror from compiler package to install. - -commit 5a7a4687507d057f9b5e7497f3d3f82e64753c02 -Author: Darren Tucker -Date: Thu Oct 21 15:00:53 2021 +1100 - - Build with -Werror on most recent gcc and clang. - -commit 4d2cbdb525d673acf941d48a7044fcf03125611a -Author: Darren Tucker -Date: Fri Oct 15 12:59:06 2021 +1100 - - Include string.h and stdio.h for strerror. - -commit fff13aaa262b7b3ec83ed21e29674cbf331780a7 -Author: Darren Tucker -Date: Fri Oct 15 12:43:36 2021 +1100 - - Include error reason if trace disabling fails. - -commit d4b38144c02f3faa5271e5fb35df93507e06f1b4 -Author: Darren Tucker -Date: Tue Oct 12 22:55:51 2021 +1100 - - Add tcmalloc test target. - -commit 002d65b0a30063c6e49bf8a53e709d8d5a0d45c1 -Author: dtucker@openbsd.org -Date: Sat Oct 9 10:52:42 2021 +0000 - - upstream: Document that CASignatureAlgorithms, ExposeAuthInfo and - - PubkeyAuthOptions can be used in a Match block. Patch from eehakkin via - github PR#277. - - OpenBSD-Commit-ID: c0a63f5f52e918645967ac022b28392da4b866aa - -commit 40bd3709dddaae3a1b6113748bec3faa6a607531 -Author: Darren Tucker -Date: Thu Oct 7 15:55:49 2021 +1100 - - Skip SK unit tests when built without security-key - -commit 482f73be10f10b93f818df19fcc8a912c0c371fc -Author: Darren Tucker -Date: Thu Oct 7 15:55:04 2021 +1100 - - Include relevant env vars on command line. - - Makes it easier to reproduce a build by cut/pasting the configure line. - -commit ef5916b8acd9b1d2f39fad4951dae03b00dbe390 -Author: Darren Tucker -Date: Thu Oct 7 14:28:02 2021 +1100 - - Only enable sk-* key types if ENABLE_SK is defined - -commit 52d4232b493a9858fe616e28a8bbcc89afa2ad4d -Author: Darren Tucker -Date: Wed Oct 6 18:14:37 2021 +1100 - - Disable security key on minix3. - - The test doesn't work so disable. - -commit 7cd062c3a29669b8d7dc2a97e6575f4dcb7d35a2 -Author: Darren Tucker -Date: Wed Oct 6 17:45:28 2021 +1100 - - Add USE_LIBC_SHA2 for (at least) NetBSD 9. - -commit 639c440f6c3c2a8216a5eb9455ef13bf4204089c -Author: Darren Tucker -Date: Wed Oct 6 17:09:31 2021 +1100 - - Define OPENSSL_NO_SHA including OpenSSL from test. - - We don't use SHA256 from OpenSSL in the sk-dummy module and the - definitions can conflict with system sha2.h (eg on NetBSD) so define - OPENSSL_NO_SHA so we don't attempt to redefine them. - -commit 8f4be526a338d06624f146fa26007bb9dd3a4f7b -Author: Darren Tucker -Date: Wed Oct 6 15:40:58 2021 +1100 - - Disable security key on NetBSD4 test. - - sk-dummy used for the security key test includes both sha2.h and OpenSSL - causing the definitions conflict so disable security key support on this - platform. - -commit 3b353ae58aa07a1cbbeb1da3ace21fc0dcccd66a -Author: Damien Miller -Date: Wed Oct 6 15:07:01 2021 +1100 - - clean regress/misc/sk-dummy in cleandir target - -commit 57680a2ab43518c5ccbd8242c40482106cde6ac1 -Author: dtucker@openbsd.org -Date: Sat Oct 2 03:17:01 2021 +0000 - - upstream: Dynamically allocate encoded HashKnownHosts and free as - - appropriate. Saves 1k of static storage and prevents snprintf "possible - truncation" warnings from newer compilers (although in this case it's false - positive since the actual sizes are limited by the output size of the SHA1). - ok djm@ - - OpenBSD-Commit-ID: e254ae723f7e3dce352c7d5abc4b6d87faf61bf4 - -commit e3e62deb549fde215b777d95276c304f84bf00c6 -Author: djm@openbsd.org -Date: Wed Oct 6 03:35:13 2021 +0000 - - upstream: use libc SHA256 functions; make this work when compiled - - !WITH_OPENSSL - - OpenBSD-Regress-ID: fda0764c1097cd42f979ace29b07eb3481259890 - -commit 12937d867019469ebce83c2ff614cdc6688fc2d8 -Author: dtucker@openbsd.org -Date: Fri Oct 1 05:20:20 2021 +0000 - - upstream: Add test for ssh hashed known_hosts handling. - - OpenBSD-Regress-ID: bcef3b3cd5a1ad9899327b4b2183de2541aaf9cf - -commit 5a37cc118f464416d08cd0291a9b1611d8de9943 -Author: Damien Miller -Date: Wed Oct 6 13:16:21 2021 +1100 - - fix broken OPENSSL_HAS_ECC test - - spotted by dtucker - -commit 16a25414f303cd6790eb967aeb962040e32c9c7a -Author: Damien Miller -Date: Fri Oct 1 22:40:06 2021 +1000 - - make sk-dummy.so work without libcrypto installed - -commit dee22129bbc61e25b1003adfa2bc584c5406ef2d -Author: Damien Miller -Date: Fri Oct 1 16:35:49 2021 +1000 - - make OPENSSL_HAS_ECC checks more thorough - - ok dtucker - -commit 872595572b6c9a584ed754165e8b7c4c9e7e1d61 -Author: Damien Miller -Date: Fri Oct 1 16:35:05 2021 +1000 - - fix FIDO key support for !OPENSSL_HAS_ECC case - - ok dtucker - -commit 489741dc68366940d369ac670b210b4834a6c272 -Author: Damien Miller -Date: Fri Oct 1 14:51:37 2021 +1000 - - enable security key support for --without-openssl - -commit c978565c8589acfe4ea37ab5099d39c84158c713 -Author: Damien Miller -Date: Fri Oct 1 13:27:50 2021 +1000 - - need stdlib.h for free(3) - -commit 76a398edfb51951b2d65d522d7b02c72304db300 -Author: dtucker@openbsd.org -Date: Thu Sep 30 05:26:26 2021 +0000 - - upstream: Fix up whitespace left by previous - - change removing privsep. No other changes. - - OpenBSD-Regress-ID: 87adec225d8afaee4d6a91b2b71203f52bf14b15 - -commit ddcb53b7a7b29be65d57562302b2d5f41733e8dd -Author: dtucker@openbsd.org -Date: Thu Sep 30 05:20:08 2021 +0000 - - upstream: Remove references to privsep. - - This removes several do..while loops but does not change the - indentation of the now-shallower loops, which will be done in a separate - whitespace-only commit to keep changes of style and substance separate. - - OpenBSD-Regress-ID: 4bed1a0249df7b4a87c965066ce689e79472a8f7 - -commit ece2fbe486164860de8df3f8b943cccca3085eff -Author: dtucker@openbsd.org -Date: Thu Sep 30 04:22:50 2021 +0000 - - upstream: Use "skip" instead of "fatal" - - if SUDO isn't set for the *-command tests. This means running "make tests" - without SUDO set will perform all of the tests that it can instead of - failing on the ones it cannot run. - - OpenBSD-Regress-ID: bd4dbbb02f34b2e8c890558ad4a696248def763a - -commit bb754b470c360e787a99fb4e88e2668198e97b41 -Author: djm@openbsd.org -Date: Fri Oct 1 04:50:36 2021 +0000 - - upstream: unbreak FIDO sk-ed25519 key enrollment for OPENSSL=no builds; - - ok dtucker@ - - OpenBSD-Commit-ID: 6323a5241728626cbb2bf0452cf6a5bcbd7ff709 - -commit 207648d7a6415dc915260ca75850404dbf9f0a0b -Author: Darren Tucker -Date: Wed Sep 29 20:03:58 2021 +1000 - - Include stdlib.h for arc4random_uniform prototype. - -commit 696aadc854582c164d5fc04933d2f3e212dc0e06 -Author: Darren Tucker -Date: Wed Sep 29 20:00:30 2021 +1000 - - Look for clang after cc and gcc. - -commit a3c6375555026d85dbf811fab566b9f76f196144 -Author: Darren Tucker -Date: Wed Sep 29 19:30:59 2021 +1000 - - Use backticks instead of $(..) for portability. - - Older shells (eg /bin/sh on Solaris 10) don't support $() syntax. - -commit 958aaa0387133d51f84fe9c8f30bca03025f2867 -Author: Darren Tucker -Date: Wed Sep 29 18:53:32 2021 +1000 - - Skip file-based tests by default on Mac OS. - - The file-based tests need OpenSSL so skip them. - -commit 55c8bdf6e9afb0f9fa8e4f10c25c7f0081b48fd0 -Author: Darren Tucker -Date: Wed Sep 29 18:42:47 2021 +1000 - - Build without OpenSSL on Mac OS. - - Modern versions don't ship enough libcrypto to build against. - -commit c9172193ea975415facf0afb356d87df21535f88 -Author: Darren Tucker -Date: Wed Sep 29 18:33:38 2021 +1000 - - Remove TEST_SSH_ECC. - - Convert the only remaining user of it to runtime detection using ssh -Q. - -commit 5e6d28b7874b0deae95d2c68947c45212d32e599 -Author: Darren Tucker -Date: Wed Sep 29 17:48:09 2021 +1000 - - Split c89 test openssl setting out. - -commit c4ac7f98e230e83c015678dc958b1ffe828564ad -Author: Darren Tucker -Date: Wed Sep 29 17:40:50 2021 +1000 - - Expand TEST_SHELL consistently with other vars. - -commit cfe5f7b0eb7621bfb0a756222de0431315c2ab8b -Author: Darren Tucker -Date: Wed Sep 29 17:26:50 2021 +1000 - - Replace `pwd` with make variable in regress cmd. - -commit 899be59da5fbc3372444bd0fbe74af48313bed33 -Author: Darren Tucker -Date: Wed Sep 29 17:14:33 2021 +1000 - - Get BUILDDIR from autoconf. - - Use this to replace `pwd`s in regress test command line. - -commit c8d92d3d4f7d560146f2f936156ec4dac3fc5811 -Author: Darren Tucker -Date: Wed Sep 29 13:28:56 2021 +1000 - - Add make clean step to tests. - -commit 360fb41ef8359619ab90b0d131c914494e55d3dd -Author: Darren Tucker -Date: Wed Sep 29 11:36:13 2021 +1000 - - Test all available clang and gcc versions. - -commit 4fb49899d7da22952d35a4bc4c9bdb2311087893 -Author: djm@openbsd.org -Date: Wed Sep 29 01:32:21 2021 +0000 - - upstream: Test certificate hostkeys held in ssh-agent too. Would have - - caught regression fixed in sshd r1.575 - - ok markus@ - - OpenBSD-Regress-ID: 1f164d7bd89f83762db823eec4ddf2d2556145ed - -commit ce4854e12e749a05646e5775e9deb8cfaf49a755 -Author: djm@openbsd.org -Date: Wed Sep 29 01:33:32 2021 +0000 - - upstream: add some debug output showing how many key file/command lines - - were processed. Useful to see whether a file or command actually has keys - present - - OpenBSD-Commit-ID: 0bd9ff94e84e03a22df8e6c12f6074a95d27f23c - -commit 15abdd523501c349b703d9a27e2bb4252ad921ef -Author: dtucker@openbsd.org -Date: Tue Sep 28 11:14:50 2021 +0000 - - upstream: Make prototype for rijndaelEncrypt match function - - including the bounds. Fixes error in portable where GCC>=11 takes notice of - the bounds. ok deraadt@ - - OpenBSD-Commit-ID: cdd2f05fd1549e1786a70871e513cf9e9cf099a6 - -commit d1d29ea1d1ef1a1a54b209f062ec1dcc8399cf03 -Author: dtucker@openbsd.org -Date: Tue Sep 28 11:10:05 2021 +0000 - - upstream: Import regenerated moduli. - - OpenBSD-Commit-ID: 4bec5db13b736b64b06a0fca704cbecc2874c8e1 - -commit 39f2111b1d5f00206446257377dcce58cc72369f -Author: Darren Tucker -Date: Wed Sep 29 10:53:55 2021 +1000 - - Add new compiler hardening flags. - - Add -fzero-call-used-regs and -ftrivial-auto-var-init to the list of - compiler hardening flags that configure checks for. These are supported - by clang and gcc, and make ROP gadgets less useful and mitigate - stack-based infoleaks respectively. ok djm@ - -commit bf944e3794eff5413f2df1ef37cddf96918c6bde -Author: Damien Miller -Date: Mon Sep 27 00:03:19 2021 +1000 - - initgroups needs grp.h - -commit 8c5b5655149bd76ea21026d7fe73ab387dbc3bc7 -Author: djm@openbsd.org -Date: Sun Sep 26 14:01:11 2021 +0000 - - upstream: openssh-8.8 - - OpenBSD-Commit-ID: 12357794602ac979eb7312a1fb190c453f492ec4 - -commit f3cbe43e28fe71427d41cfe3a17125b972710455 -Author: djm@openbsd.org -Date: Sun Sep 26 14:01:03 2021 +0000 - - upstream: need initgroups() before setresgid(); reported by anton@, - - ok deraadt@ - - OpenBSD-Commit-ID: 6aa003ee658b316960d94078f2a16edbc25087ce - -commit 8acaff41f7518be40774c626334157b1b1c5583c -Author: Damien Miller -Date: Sun Sep 26 22:16:36 2021 +1000 - - update version numbers for release - -commit d39039ddc0010baa91c70a0fa0753a2699bbf435 -Author: kn@openbsd.org -Date: Sat Sep 25 09:40:33 2021 +0000 - - upstream: RSA/SHA-1 is not used by default anymore - - OK dtucker deraadt djm - - OpenBSD-Commit-ID: 055c51a221c3f099dd75c95362f902da1b8678c6 - -commit 9b2ee74e3aa8c461eb5552a6ebf260449bb06f7e -Author: Darren Tucker -Date: Fri Sep 24 11:08:03 2021 +1000 - - Move the fgrep replacement to hostkey-rotate.sh. - - The fgrep replacement for buggy greps doesn't work in the sftp-glob test - so move it to just where we know it's needed. - -commit f7039541570d4b66d76e6f574544db176d8d5c02 -Author: Darren Tucker -Date: Fri Sep 24 08:04:14 2021 +1000 - - Replacement function for buggy fgrep. - - GNU (f)grep <=2.18, as shipped by FreeBSD<=12 and NetBSD<=9 will - occasionally fail to find ssh host keys in the hostkey-rotate test. - If we have those versions, use awk instead. - -commit f6a660e5bf28a01962af87568e118a2d2e79eaa0 -Author: David Manouchehri -Date: Thu Sep 23 17:03:18 2021 -0400 - - Don't prompt for yes/no questions. - -commit 7ed1a3117c09f8c3f1add35aad77d3ebe1b85b4d -Author: djm@openbsd.org -Date: Mon Sep 20 06:53:56 2021 +0000 - - upstream: fix missing -s in SYNOPSYS and usage() as well as a - - capitalisation mistake; spotted by jmc@ - - OpenBSD-Commit-ID: 0ed8ee085c7503c60578941d8b45f3a61d4c9710 - -commit 8c07170135dde82a26886b600a8bf6fb290b633d -Author: dtucker@openbsd.org -Date: Mon Sep 20 04:02:13 2021 +0000 - - upstream: Fix "Allocated port" debug message - - for unix domain sockets. From peder.stray at gmail.com via github PR#272, - ok deraadt@ - - OpenBSD-Commit-ID: 8d5ef3fbdcdd29ebb0792b5022a4942db03f017e - -commit 277d3c6adfb128b4129db08e3d65195d94b55fe7 -Author: djm@openbsd.org -Date: Mon Sep 20 01:55:42 2021 +0000 - - upstream: Switch scp back to use the old protocol by default, ahead of - - release. We'll wait a little longer for people to pick up sftp-server(8) that - supports the extension that scp needs for ~user paths to continue working in - SFTP protocol mode. Discussed with deraadt@ - - OpenBSD-Commit-ID: f281f603a705fba317ff076e7b11bcf2df941871 - -commit ace19b34cc15bea3482be90450c1ed0cd0dd0669 -Author: djm@openbsd.org -Date: Sat Sep 18 02:03:25 2021 +0000 - - upstream: better error message for ~user failures when the - - sftp-server lacks the expand-path extension; ok deraadt@ - - OpenBSD-Commit-ID: 9c1d965d389411f7e86f0a445158bf09b8f9e4bc - -commit 6b1238ba971ee722a310d95037b498ede5539c03 -Author: djm@openbsd.org -Date: Thu Sep 16 15:22:22 2021 +0000 - - upstream: make some more scp-in-SFTP mode better match Unix idioms - - suggested by deraadt@ - - OpenBSD-Commit-ID: 0f2439404ed4cf0b0be8bf49a1ee734836e1ac87 - -commit e694f8ac4409931e67d08ac44ed251b20b10a957 -Author: djm@openbsd.org -Date: Thu Sep 16 15:11:19 2021 +0000 - - upstream: allow log_stderr==2 to prefix log messages with argv[0] - - use this to make scp's SFTP mode error messages more scp-like - - prompted by and ok deraadt@ - - OpenBSD-Commit-ID: 0e821dbde423fc2280e47414bdc22aaa5b4e0733 - -commit 8a7a06ee505cb833e613f74a07392e9296286c30 -Author: Darren Tucker -Date: Fri Sep 17 13:03:31 2021 +1000 - - Test against LibreSSL 3.2.6, 3.3.4, 3.4.0. - -commit c25c84074a47f700dd6534995b4af4b456927150 -Author: djm@openbsd.org -Date: Thu Sep 16 05:36:03 2021 +0000 - - upstream: missing space character in ssh -G output broke the - - t-sshcfgparse regression test; spotted by anton@ - - OpenBSD-Commit-ID: bcc36fae2f233caac4baa8e58482da4aa350eed0 - -commit a4bee1934bf5e5575fea486628f4123d6a29dff8 -Author: djm@openbsd.org -Date: Wed Sep 15 06:56:01 2021 +0000 - - upstream: allow CanonicalizePermittedCNAMEs=none in ssh_config; ok - - markus@ - - OpenBSD-Commit-ID: 668a82ba8e56d731b26ffc5703213bfe071df623 - -commit d0fffc88c8fe90c1815c6f4097bc8cbcabc0f3dd -Author: mbuhl@openbsd.org -Date: Tue Sep 14 11:04:21 2021 +0000 - - upstream: put back the mux_ctx memleak fix for SSH_CHANNEL_MUX_CLIENT - - OK mfriedl@ - - OpenBSD-Commit-ID: 1aba1da828956cacaadb81a637338734697d9798 - -commit 19b3d846f06697c85957ab79a63454f57f8e22d6 -Author: schwarze@openbsd.org -Date: Sat Sep 11 09:05:50 2021 +0000 - - upstream: Do not ignore SIGINT while waiting for input if editline(3) - - is not used. Instead, in non-interactive mode, exit sftp(1), like for other - serious errors. As pointed out by dtucker@, when compiled without editline(3) - support in portable OpenSSH, the el == NULL branch is also used for - interactive mode. In that case, discard the input line and provide a fresh - prompt to the user just like in the case where editline(3) is used. OK djm@ - - OpenBSD-Commit-ID: 7d06f4d3ebba62115527fafacf38370d09dfb393 - -commit ba61123eef9c6356d438c90c1199a57a0d7bcb0a -Author: djm@openbsd.org -Date: Sat Sep 11 00:40:24 2021 +0000 - - upstream: when using SFTP protocol, continue transferring files after a - - transfer error occurs. This matches original scp/rcp behaviour. ok dtucker@ - - OpenBSD-Commit-ID: dfe4558d71dd09707e9b5d6e7d2e53b793da69fa - -commit b0ec59a708b493c6f3940336b1a537bcb64dd2a7 -Author: dtucker@openbsd.org -Date: Fri Sep 10 11:38:38 2021 +0000 - - upstream: Document that non-interactive commands are run via the user's - - shell using the -c flag. ok jmc@ - - OpenBSD-Commit-ID: 4f0d912077732eead10423afd1acf4fc0ceec477 - -commit 66a658b5d9e009ea11f8a0ca6e69c7feb2d851ea -Author: dtucker@openbsd.org -Date: Fri Sep 10 10:26:02 2021 +0000 - - upstream: Document behaviour of arguments following non-interactive - - commands. Prompted by github PR#139 from EvanTheB, feedback & ok djm@ jmc@ - - OpenBSD-Commit-ID: fc758d1fe0471dfab4304fcad6cd4ecc3d79162a - -commit 1d47e28e407d1f95fdf8f799be23f48dcfa5206b -Author: dtucker@openbsd.org -Date: Fri Sep 10 07:11:11 2021 +0000 - - upstream: Clarify which file's attributes -p preserves, and that - - it's specifically the file mode bits. bz#3340 from calestyo at scientia.net, - ok djm@ jmc@ - - OpenBSD-Commit-ID: f09e6098ed1c4be00c730873049825f8ee7cb884 - -commit b344db7a413478e4c21e4cadba4a970ad3e6128a -Author: djm@openbsd.org -Date: Fri Sep 10 05:46:09 2021 +0000 - - upstream: openssh-7.4 was incorrectly listed twice; spotted by - - Dmitry Belyavskiy, ok dtucker@ - - OpenBSD-Commit-ID: 4b823ae448f6e899927ce7b04225ac9e489f58ef - -commit 9136d6239ad7a4a293e0418a49b69e70c76d58b8 -Author: jmc@openbsd.org -Date: Thu Sep 9 06:17:39 2021 +0000 - - upstream: - move CAVEATS to its correct order - use the term - - "legacy" protocol rather than "original", as the latter made the text - misleading - uppercase SCP - - ok djm - - OpenBSD-Commit-ID: 8479255746d5fa76a358ee59e7340fecf4245ff0 - -commit 2d678c5e3bdc2f5c99f7af5122e9d054925d560d -Author: David Carlier -Date: Wed Sep 8 19:49:54 2021 +0100 - - Disable tracing on FreeBSD using procctl. - - Placed at the start of platform_disable_tracing() to prevent declaration - after code errors from strict C89 compilers (in the unlikely event that - more than one method is enabled). - -commit 73050fa38fb36ae3326d768b574806352b97002d -Author: djm@openbsd.org -Date: Wed Sep 8 23:31:39 2021 +0000 - - upstream: Use the SFTP protocol by default. The original scp/rcp - - protocol remains available via the -O flag. - - Note that ~user/ prefixed paths in SFTP mode require a protocol extension - that was first shipped in OpenSSH 8.7. - - ok deraadt, after baking in snaps for a while without incident - - OpenBSD-Commit-ID: 23588976e28c281ff5988da0848cb821fec9213c - -commit c4565e69ffa2485cff715aa842ea7a350296bfb6 -Author: Darren Tucker -Date: Wed Sep 8 21:09:49 2021 +1000 - - Really fix test on OpenSSL 1.1.1 stable. - -commit 79f1bb5f56cef3ae9276207316345b8309248478 -Author: Darren Tucker -Date: Wed Sep 8 18:51:39 2021 +1000 - - Correct OpenSSL 1.1.1 stable identifier. - -commit b6255593ed5ccbe5e7d3d4b26b2ad31ad4afc232 -Author: Darren Tucker -Date: Wed Sep 8 18:39:44 2021 +1000 - - Increment nfds when coming from startup_pipe. - - If we have to increase nfds because startup_pipe[0] is above any of the - descriptors passed in the fd_sets, we also need to add 1 to nfds since - select takes highest FD number plus one. bz#3345 from yaroslav.kuzmin - at vmssoftware.com. - -commit a3e92a6794817df6012ac8546aea19652cc91b61 -Author: Darren Tucker -Date: Wed Sep 8 13:45:10 2021 +1000 - - Tests for OpenSSL 3.0.0 release & 1.1.1 branch. - -commit 4afe431da98ec1cf6a2933fe5658f4fd68dee9e2 -Author: djm@openbsd.org -Date: Wed Sep 8 03:23:44 2021 +0000 - - upstream: correct my mistake in previous fix; spotted by halex - - OpenBSD-Commit-ID: 3cc62d92e3f70006bf02468fc146bfc36fffa183 - -commit ca0e455b9331213ff9505a21b94c38e34faa2bba -Author: djm@openbsd.org -Date: Tue Sep 7 06:03:51 2021 +0000 - - upstream: avoid NULL deref in -Y find-principals. Report and fix - - from Carlo Marcelo Arenas Belón - MIME-Version: 1.0 - Content-Type: text/plain; charset=UTF-8 - Content-Transfer-Encoding: 8bit - - OpenBSD-Commit-ID: 6238486f8ecc888d6ccafcd9ad99e621bb41f1e0 - -commit 37616807f150fb46610bbd5031c31af4857ad1e9 -Author: millert@openbsd.org -Date: Mon Sep 6 00:36:01 2021 +0000 - - upstream: revision 1.381 neglected to remove - - sChallengeResponseAuthentication from the enum. Noticed by - christos@zoulas.com. OK dtucker@ - - OpenBSD-Commit-ID: b533283a4dd6d04a867da411a4c7a8fbc90e34ff - -commit 7acb3578cdfec0b3d34501408071f7a96c1684ea -Author: Darren Tucker -Date: Sun Sep 5 20:45:42 2021 +1000 - - Correct version_num for OpenSSL dev branch. - -commit 65bb01111320dfd0d25e21e1fd4d3f2b77532669 -Author: Darren Tucker -Date: Sun Sep 5 19:37:39 2021 +1000 - - Test against OpenSSL 3 branch as well as dev. - - Now that OpenSSL development has moved to 3.1, test against the most - recent version of the openssl-3.0 branch too. - -commit 864ed0d5e04a503b97202c776b7cf3f163f3eeaa -Author: Darren Tucker -Date: Sun Sep 5 19:33:22 2021 +1000 - - OpenSSL development is now 3.1.* - -commit a60209a586a928f92ab323bf23bd07f57093342e -Author: dtucker@openbsd.org -Date: Fri Sep 3 07:43:23 2021 +0000 - - upstream: Use .Cm instead of .Dq in StrictHostKeyChecking list for - - consistency. Patch from scop via github PR#257, ok jmc@ - - OpenBSD-Commit-ID: 3652a91564570779431802c31224fb4a9cf39872 - -commit 8d1d9eb6de37331e872700e9e399a3190cca1242 -Author: dtucker@openbsd.org -Date: Fri Sep 3 07:27:03 2021 +0000 - - upstream: Mention using ssh -i for specifying the public key file - - in the case where the private key is loaded into ssh-agent but is not present - locally. Based on patch from rafork via github PR#215, ok jmc@ - - OpenBSD-Commit-ID: 2282e83b0ff78d2efbe705883b67240745fa5bb2 - -commit eb4362e5e3aa7ac26138b11e44d8c191910aff64 -Author: dtucker@openbsd.org -Date: Fri Sep 3 05:25:50 2021 +0000 - - upstream: Refer to KEX "algorithms" instead of "methods" to match - - other references and improve consistency. Patch from scop via github PR#241, - ok djm@ - - OpenBSD-Commit-ID: 840bc94ff6861b28d8603c8e8c16499bfb65e32c - -commit b3318946ce5725da43c4bf7eeea1b73129c47d2a -Author: dtucker@openbsd.org -Date: Fri Sep 3 05:12:25 2021 +0000 - - upstream: Remove redundant attrib_clear in upload_dir_internal. - - The subsequent call to stat_to_attrib clears the struct as its first step - anyway. From pmeinhardt via github PR#220, ok djm@ - - OpenBSD-Commit-ID: f5234fc6d7425b607e179acb3383f21716f3029e - -commit 7cc3fe28896e653956a6a2eed0a25d551b83a029 -Author: dtucker@openbsd.org -Date: Fri Sep 3 04:11:13 2021 +0000 - - upstream: Add test for client termination status on signal. - - Based on patch from Alexxz via github PR#235 with some tweaks, to - match patch in bz#3281. - - OpenBSD-Regress-ID: d87c7446fb8b5f8b45894fbbd6875df326e729e2 - -commit 5428b0d239f6b516c81d1dd15aa9fe9e60af75d4 -Author: deraadt@openbsd.org -Date: Thu Sep 2 21:03:54 2021 +0000 - - upstream: sys/param.h is not needed for any visible reason - - OpenBSD-Commit-ID: 8bdea2d0c75692e4c5777670ac039d4b01c1f368 - -commit 1ff38f34b4c4545eb28106629cafa1e0496bc726 -Author: Shchelkunov Artem -Date: Wed Aug 11 18:07:58 2021 +0500 - - Fix memory leak in error path. - - *info is allocated via xstrdup but was leaked in the PAM_AUTH_ERR path. - From github PR#266. - -commit cb37e2f0c0ca4fef844ed7edc5d0e3b7d0e83f6a -Author: dtucker@openbsd.org -Date: Wed Sep 1 03:16:06 2021 +0000 - - upstream: Fix ssh-rsa fallback for old PuTTY interop tests. - - OpenBSD-Regress-ID: a19ac929da604843a5b5f0f48d2c0eb6e0773d37 - -commit 8b02ef0f28dc24cda8cbcd8b7eb02bda8f8bbe59 -Author: dtucker@openbsd.org -Date: Wed Sep 1 00:50:27 2021 +0000 - - upstream: Add a function to skip remaining tests. - - Many tests skip tests for various reasons but not in a consistent way and - don't always clean up, so add that and switch the tests that do that over. - - OpenBSD-Regress-ID: 72d2ec90a3ee8849486956a808811734281af735 - -commit d486845c07324c04240f1674ac513985bd356f66 -Author: dtucker@openbsd.org -Date: Tue Aug 31 07:13:59 2021 +0000 - - upstream: Specify path to PuTTY keys. - - Portable needs this and it makes no difference on OpenBSD, so resync - them. (Id sync only, Portable already had this.) - - OpenBSD-Regress-ID: 33f6f66744455886d148527af8368811e4264162 - -commit d22b299115e27606e846b23490746f69fdd4fb38 -Author: dtucker@openbsd.org -Date: Tue Aug 31 06:13:23 2021 +0000 - - upstream: Better compat tests with old PuTTY. - - When running PuTTY interop tests and using a PuTTY version older than - 0.76, re-enable the ssh-rsa host key algorithm (the 256 and 512 variants - of RSA were added some time between 0.73 and 0.76). - - OpenBSD-Regress-ID: e6138d6987aa705fa1e4f216db0bb386e1ff38e1 - -commit 87ad70d605c3e39c9b8aa275db27120d7cc09b77 -Author: Darren Tucker -Date: Tue Aug 31 17:04:50 2021 +1000 - - Resync PuTTY interop tests. - - Resync behaviour when REGRESS_INTEROP_PUTTY is not set with OpenBSD. - -commit e47b82a7bf51021afac218bf59a3be121827653d -Author: dtucker@openbsd.org -Date: Tue Aug 31 01:25:27 2021 +0000 - - upstream: Specify hostkeyalgorithms in SSHFP test. - - Specify host key algorithms in sshd's default set for the SSHFP test, - from djm@. Make the reason for when the test is skipped a bit clearer. - - OpenBSD-Regress-ID: 4f923dfc761480d5411de17ea6f0b30de3e32cea - -commit 7db3e0a9e8477c018757b59ee955f7372c0b55fb -Author: djm@openbsd.org -Date: Mon Aug 30 01:15:45 2021 +0000 - - upstream: adapt to RSA/SHA1 deprectation - - OpenBSD-Regress-ID: 952397c39a22722880e4de9d1c50bb1a14f907bb - -commit 2344750250247111a6c3c6a4fe84ed583a61cc11 -Author: djm@openbsd.org -Date: Sun Aug 29 23:53:10 2021 +0000 - - upstream: After years of forewarning, disable the RSA/SHA-1 - - signature algorithm by default. It is feasible to create colliding SHA1 - hashes, so we need to deprecate its use. - - RSA/SHA-256/512 remains available and will be transparently selected - instead of RSA/SHA1 for most SSH servers released in the last five+ - years. There is no need to regenerate RSA keys. - - The use of RSA/SHA1 can be re-enabled by adding "ssh-rsa" to the - PubkeyAcceptedAlgorithms directives on the client and server. - - ok dtucker deraadt - - OpenBSD-Commit-ID: 189bcc4789c7254e09e23734bdd5def8354ff1d5 - -commit 56c4455d3b54b7d481c77c82115c830b9c8ce328 -Author: djm@openbsd.org -Date: Sun Aug 29 23:44:07 2021 +0000 - - upstream: wrap at 80 columns - - OpenBSD-Commit-ID: 47ca2286d6b52a9747f34da16d742879e1a37bf0 - -commit 95401eea8503943449f712e5f3de52fc0bc612c5 -Author: Darren Tucker -Date: Fri Aug 20 18:14:13 2021 +1000 - - Replace shell function with ssh-keygen -A. - - Prevents the init script in the SysV package from trying (and failing) - to generate unsupported key types. Remove now-unused COMMENT_OUT_ECC. - ok tim@ - -commit d83ec9ed995a76ed1d5c65cf10b447222ec86131 -Author: Darren Tucker -Date: Fri Aug 20 15:39:05 2021 +1000 - - Remove obsolete Redhat PAM config and init script. - -commit e1a596186c81e65a34ce13076449712d3bf97eb4 -Author: Damien Miller -Date: Fri Aug 20 14:03:49 2021 +1000 - - depend - -commit 5450606c8f7f7a0d70211cea78bc2dab74ab35d1 -Author: Damien Miller -Date: Fri Aug 20 13:59:43 2021 +1000 - - update version numbers - -commit feee2384ab8d694c770b7750cfa76a512bdf8246 -Author: djm@openbsd.org -Date: Fri Aug 20 03:22:55 2021 +0000 - - upstream: openssh-8.7 - - OpenBSD-Commit-ID: 8769dff0fd76ae3193d77bf83b439adee0f300cd - -commit 9a2ed62173cc551b2b5f479460bb015b19499de8 -Author: Darren Tucker -Date: Fri Aug 20 10:48:13 2021 +1000 - - Also check pid in pselect_notify_setup. - - Spotted by djm@. - -commit deaadcb93ca15d4f38aa38fb340156077792ce87 -Author: Darren Tucker -Date: Fri Aug 20 08:39:33 2021 +1000 - - Prefix pselect functions to clarify debug messages - -commit 10e45654cff221ca60fd35ee069df67208fcf415 -Author: Darren Tucker -Date: Fri Aug 20 08:30:42 2021 +1000 - - Fix race in pselect replacement code. - - On the second and subsequent calls to pselect the notify_pipe was not - added to the select readset, opening up a race that om G. Christensen - discovered on multiprocessor Solaris <=9 systems. - - Also reinitialize notify_pipe if the pid changes. This will prevent a - parent and child from using the same FD, although this is not an issue - in the current structure it might be in future. - -commit 464ba22f1e38d25402e5ec79a9b8d34a32df5a3f -Author: Darren Tucker -Date: Wed Aug 18 12:51:30 2021 +1000 - - Check compiler for c99 declarations after code. - - The sntrup761 reference code contains c99-style declarations after code - so don't try to build that if the compiler doesn't support it. - -commit 7d878679a4b155a359d32104ff473f789501748d -Author: Darren Tucker -Date: Tue Aug 17 15:12:04 2021 +1000 - - Remove trailing backslash on regress-unit-binaries - -commit b71b2508f17c68c5d9dbbe537686d81cedb9a781 -Author: Darren Tucker -Date: Tue Aug 17 07:59:27 2021 +1000 - - Put stdint.h inside HAVE_STDINT_H. - - From Tom G. Christensen. - -commit 6a24567a29bd7b4ab64e1afad859ea845cbc6b8c -Author: Darren Tucker -Date: Mon Aug 16 14:13:02 2021 +1000 - - Improve github test driver script. - - - use a trap to always output any failed regress logs (since the script - sets -e, the existing log output is never invoked). - - pass LTESTS and SKIP_LTESTS when re-running with sshd options (eg. - UsePAM). - -commit b467cf13705f59ed348b620722ac098fe31879b7 -Author: Darren Tucker -Date: Mon Aug 16 11:32:23 2021 +1000 - - Remove deprecated ubuntu-16.04 test targets. - - Github has deprecated ubuntu-16.04 and it will be removed on 20 - September. - -commit 20e6eefcdf78394f05e453d456c1212ffaa6b6a4 -Author: Darren Tucker -Date: Sun Aug 15 23:25:26 2021 +1000 - - Skip agent ptrace test on hurd. - -commit 7c9115bbbf958fbf85259a061c1122e2d046aabf -Author: Darren Tucker -Date: Sun Aug 15 19:37:22 2021 +1000 - - Add hurd test target. - -commit 7909a566f6c6a78fcd30708dc49f4e4f9bb80ce3 -Author: Darren Tucker -Date: Sun Aug 15 12:45:10 2021 +1000 - - Skip scp3 tests on all dfly58 and 60 configs. - -commit e65198e52cb03534e8c846d1bca74c310b1526de -Author: Tim Rice -Date: Sat Aug 14 13:08:07 2021 -0700 - - openbsd-compat/openbsd-compat.h: put bsd-signal.h before bsd-misc.h - to get sigset_t from signal.h needed for the pselect replacement. - -commit e50635640f79920d9375e0155cb3f4adb870eee5 -Author: Darren Tucker -Date: Fri Aug 13 13:21:00 2021 +1000 - - Test OpenSSH from OpenBSD head on 6.8 and 6.9. - -commit e0ba38861c490c680117b7fe0a1d61a181cd00e7 -Author: Darren Tucker -Date: Fri Aug 13 13:00:14 2021 +1000 - - Skip scp3 test on dragonfly 58 and 60. - - The tests hang, so skip until we figure them out. - -commit dcce2a2bcf007bf817a2fb0dce3db83fa9201e92 -Author: djm@openbsd.org -Date: Thu Aug 12 23:59:25 2021 +0000 - - upstream: mention that CASignatureAlgorithms accepts +/- similarly to - - the other algorithm list directives; ok jmc bz#3335 - - OpenBSD-Commit-ID: 0d46b53995817052c78e2dce9dbd133963b073d9 - -commit 090a82486e5d7a8f7f16613d67e66a673a40367f -Author: schwarze@openbsd.org -Date: Thu Aug 12 09:59:00 2021 +0000 - - upstream: In the editline(3) branch of the sftp(1) event loop, - - handle SIGINT rather than ignoring it, such that the user can use Ctrl-C to - discard the currently edited command line and get a fresh prompt, just like - in ftp(1), bc(1), and in shells. - - It is critical to not use ssl_signal() for this particular case - because that function unconditionally sets SA_RESTART, but here we - need the signal to interrupt the read(2) in the el_gets(3) event loop. - - OK dtucker@ deraadt@ - - OpenBSD-Commit-ID: 8025115a773f52e9bb562eaab37ea2e021cc7299 - -commit e1371e4f58404d6411d9f95eb774b444cea06a26 -Author: naddy@openbsd.org -Date: Wed Aug 11 14:07:54 2021 +0000 - - upstream: scp: tweak man page and error message for -3 by default - - Now that the -3 option is enabled by default, flip the documentation - and error message logic from "requires -3" to "blocked by -R". - - ok djm@ - - OpenBSD-Commit-ID: a872592118444fb3acda5267b2a8c3d4c4252020 - -commit 49f46f6d77328a3d10a758522b670a3e8c2235e7 -Author: naddy@openbsd.org -Date: Wed Aug 11 14:05:19 2021 +0000 - - upstream: scp: do not spawn ssh with two -s flags for - - remote-to-remote copies - - Do not add another "-s" to the argument vector every time an SFTP - connection is initiated. Instead, introduce a subsystem flag to - do_cmd() and add "-s" when the flag is set. - - ok djm@ - - OpenBSD-Commit-ID: 25df69759f323661d31b2e1e790faa22e27966c1 - -commit 2a2cd00783e1da45ee730b7f453408af1358ef5b -Author: djm@openbsd.org -Date: Wed Aug 11 08:55:04 2021 +0000 - - upstream: test -Oprint-pubkey - - OpenBSD-Regress-ID: 3d51afb6d1f287975fb6fddd7a2c00a3bc5094e0 - -commit b9f4635ea5bc33ed5ebbacf332d79bae463b0f54 -Author: djm@openbsd.org -Date: Wed Aug 11 08:54:17 2021 +0000 - - upstream: when verifying sshsig signatures, support an option - - (-Oprint-pubkey) to dump the full public key to stdout; based on patch from - Fabian Stelzer; ok markus@ - - OpenBSD-Commit-ID: 0598000e5b9adfb45d42afa76ff80daaa12fc3e2 - -commit 750c1a45ba4e8ad63793d49418a0780e77947b9b -Author: djm@openbsd.org -Date: Wed Aug 11 05:21:32 2021 +0000 - - upstream: oops, missed one more %p - - OpenBSD-Commit-ID: e7e62818d1564cc5cd9086eaf7a51cbd1a9701eb - -commit b5aa27b69ab2e1c13ac2b5ad3f8f7d389bad7489 -Author: djm@openbsd.org -Date: Wed Aug 11 05:20:17 2021 +0000 - - upstream: remove a bunch of %p in format strings; leftovers of - - debuggings past. prompted by Michael Forney, ok dtucker@ - - OpenBSD-Commit-ID: 4853a0d6c9cecaba9ecfcc19066e52d3a8dcb2ac - -commit 419aa01123db5ff5dbc68b2376ef23b222862338 -Author: Darren Tucker -Date: Wed Aug 11 09:21:09 2021 +1000 - - Add includes.h to compat tests. - - On platforms where closefrom returns void (eg glibc>=2.34) the prototype - for closefrom in its compat tests would cause compile errors. Remove - this and have the tests pull in the compat headers in the same way as - the main code. bz#3336. - -commit 931f592f26239154eea3eb35a086585897b1a185 -Author: djm@openbsd.org -Date: Tue Aug 10 03:35:45 2021 +0000 - - upstream: adapt to scp -M flag change; make scp3.sh test SFTP mode too - - OpenBSD-Regress-ID: 43fea26704a0f0b962b53c1fabcb68179638f9c0 - -commit 391ca67fb978252c48d20c910553f803f988bd37 -Author: djm@openbsd.org -Date: Tue Aug 10 03:33:34 2021 +0000 - - upstream: Prepare for a future where scp(1) uses the SFTP protocol by - - default. Replace recently added -M option to select the protocol with -O - (olde) and -s (SFTP) flags, and label the -s flag with a clear warning that - it will be removed in the near future (so no, don't use it in scripts!). - - prompted by/feedback from deraadt@ - - OpenBSD-Commit-ID: 92ad72cc6f0023c9be9e316d8b30eb6d8d749cfc - -commit bfdd4b722f124a4fa9173d20dd64dd0fc69856be -Author: djm@openbsd.org -Date: Mon Aug 9 23:56:36 2021 +0000 - - upstream: make scp -3 the default for remote-to-remote copies. It - - provides a much better and more intuitive user experience and doesn't require - exposing credentials to the source host. - - thanks naddy@ for catching the missing argument in usage() - - "Yes please!" - markus@ - "makes a lot of sense" - deraadt@ - "the right thing to do" - dtucker@ - - OpenBSD-Commit-ID: d0d2af5f0965c5192ba5b2fa461c9f9b130e5dd9 - -commit 2f7a3b51cef689ad9e93d0c6c17db5a194eb5555 -Author: djm@openbsd.org -Date: Mon Aug 9 23:49:31 2021 +0000 - - upstream: make scp in SFTP mode try to use relative paths as much - - as possible. Previosuly, it would try to make relative and ~/-rooted paths - absolute before requesting transfers. - - prompted by and much discussion deraadt@ - ok markus@ - - OpenBSD-Commit-ID: 46639d382ea99546a4914b545fa7b00fa1be5566 - -commit 2ab864010e0a93c5dd95116fb5ceaf430e2fc23c -Author: djm@openbsd.org -Date: Mon Aug 9 23:47:44 2021 +0000 - - upstream: SFTP protocol extension to allow the server to expand - - ~-prefixed paths, in particular ~user ones. Allows scp in sftp mode to accept - these paths, like scp in rcp mode does. - - prompted by and much discussion deraadt@ - ok markus@ - - OpenBSD-Commit-ID: 7d794def9e4de348e1e777f6030fc9bafdfff392 - -commit 41b019ac067f1d1f7d99914d0ffee4d2a547c3d8 -Author: djm@openbsd.org -Date: Mon Aug 9 23:44:32 2021 +0000 - - upstream: when scp is in SFTP mode, try to deal better with ~ - - prefixed paths. ~user paths aren't supported, but ~/ paths will be accepted - and prefixed with the SFTP server starting directory (more to come) - - prompted by and discussed with deraadt@ - ok markus@ - - OpenBSD-Commit-ID: 263a071f14555c045fd03132a8fb6cbd983df00d - -commit b4b3f3da6cdceb3fd168b5fab69d11fba73bd0ae -Author: djm@openbsd.org -Date: Mon Aug 9 07:21:01 2021 +0000 - - upstream: on fatal errors, make scp wait for ssh connection before - - exiting avoids LogLevel=verbose (or greater) messages from ssh appearing - after scp has returned exited and control has returned to the shell; ok - markus@ - - (this was originally committed as r1.223 along with unrelated stuff that - I rolled back in r1.224) - - OpenBSD-Commit-ID: 1261fd667ad918484889ed3d7aec074f3956a74b - -commit 2ae7771749e0b4cecb107f9d4860bec16c3f4245 -Author: djm@openbsd.org -Date: Mon Aug 9 07:19:12 2021 +0000 - - upstream: rever r1.223 - I accidentally committed unrelated changes - - OpenBSD-Commit-ID: fb73f3865b2647a27dd94db73d6589506a9625f9 - -commit 986abe94d481a1e82a01747360bd767b96b41eda -Author: djm@openbsd.org -Date: Mon Aug 9 07:16:09 2021 +0000 - - upstream: show only the final path component in the progress meter; - - more useful with long paths (that may truncate) and better matches - traditional scp behaviour; spotted by naddy@ ok deraadt@ - - OpenBSD-Commit-ID: 26b544d0074f03ebb8a3ebce42317d8d7ee291a3 - -commit 2b67932bb3176dee4fd447af4368789e04a82b93 -Author: djm@openbsd.org -Date: Mon Aug 9 07:13:54 2021 +0000 - - upstream: on fatal errors, make scp wait for ssh connection before - - exiting avoids LogLevel=verbose (or greater) messages from ssh appearing - after scp has returned exited and control has returned to the shell; ok - markus@ - - OpenBSD-Commit-ID: ef9dab5ef5ae54a6a4c3b15d380568e94263456c diff -ruN openssh-9.4p1/channels.c openssh-9.4p1+x509-14.2.1/channels.c --- openssh-9.4p1/channels.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/channels.c 2023-08-20 10:07:01.000000000 +0300 @@ -17,6 +17,7 @@ * Copyright (c) 1999, 2000, 2001, 2002 Markus Friedl. All rights reserved. * Copyright (c) 1999 Dug Song. All rights reserved. * Copyright (c) 1999 Theo de Raadt. All rights reserved. + * Copyright (c) 2015-2023 Roumen Petrov. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -57,9 +58,6 @@ #include #include #include -#ifdef HAVE_POLL_H -#include -#endif #include #ifdef HAVE_STDINT_H # include @@ -82,13 +80,30 @@ #include "channels.h" #include "compat.h" #include "canohost.h" -#include "sshkey.h" #include "authfd.h" #include "pathnames.h" #include "match.h" -/* XXX remove once we're satisfied there's no lurking bugs */ -/* #define DEBUG_CHANNEL_POLL 1 */ +/* read buffer size */ +/* NOTE keep synchronised with port-net.c */ +#if defined(HAVE_CYGWIN) && !defined(CHAN_RBUF) +# define CHAN_RBUF (64*1024) +#endif +#ifndef CHAN_RBUF +# define CHAN_RBUF (4*1024) +#endif +/* 64к 32к 16к 8к 4к +orig: 3.635 3.657 1(*) 0.688 0.615 ++buf: 3.710 3.672' 0.996 0.689 0.611 +Relative time for sftp 64M download where (*) is original basis +and ' is basis only for direct read into buffer. +Deviation: +orig: 0.184 0.523 0.330 0.162 0.046 ++buf: 0.783 0.252 0.307 0.175 0.135 +*/ +#if 0 +# define USE_DIRECT_READ +#endif /* -- agent forwarding */ #define NUM_SOCKS 10 @@ -104,9 +119,11 @@ /* Maximum number of fake X11 displays to try. */ #define MAX_DISPLAYS 1000 -/* Per-channel callback for pre/post IO actions */ +/* Per-channel callback for pre/post select() actions */ typedef void chan_fn(struct ssh *, Channel *c); +extern int channel_close_fd(struct ssh *, Channel *, int); + /* * Data structure for storing which hosts are permitted for forward requests. * The local sides of any remote forwards are stored in this array to prevent @@ -154,7 +171,7 @@ /* Used to record timeouts per channel type */ struct ssh_channel_timeout { char *type_pattern; - int timeout_secs; + long timeout_secs; }; /* Master structure for channels state */ @@ -172,11 +189,17 @@ u_int channels_alloc; /* - * 'channel_pre*' are called just before IO to add any bits - * relevant to channels in the c->io_want bitmasks. + * Maximum file descriptor value used in any of the channels. This is + * updated in channel_new. + */ + int channel_max_fd; + + /* + * 'channel_pre*' are called just before select() to add any bits + * relevant to channels in the select bitmasks. * * 'channel_post*': perform any appropriate operations for - * channels which have c->io_ready events pending. + * channels which have events pending. */ chan_fn **channel_pre; chan_fn **channel_post; @@ -252,12 +275,12 @@ Channel *c; if (id < 0 || (u_int)id >= ssh->chanctxt->channels_alloc) { - logit_f("%d: bad id", id); + debug_f("%d: bad id", id); return NULL; } c = ssh->chanctxt->channels[id]; if (c == NULL) { - logit_f("%d: bad id: channel free", id); + debug_f("%d: bad id: channel free", id); return NULL; } return c; @@ -312,11 +335,11 @@ */ void channel_add_timeout(struct ssh *ssh, const char *type_pattern, - int timeout_secs) + long timeout_secs) { struct ssh_channels *sc = ssh->chanctxt; - debug2_f("channel type \"%s\" timeout %d seconds", + debug2_f("channel type \"%s\" timeout %ld seconds", type_pattern, timeout_secs); sc->timeouts = xrecallocarray(sc->timeouts, sc->ntimeouts, sc->ntimeouts + 1, sizeof(*sc->timeouts)); @@ -340,7 +363,7 @@ sc->ntimeouts = 0; } -static int +static long lookup_timeout(struct ssh *ssh, const char *type) { struct ssh_channels *sc = ssh->chanctxt; @@ -367,12 +390,11 @@ if ((c = channel_by_id(ssh, id)) == NULL) fatal_f("missing channel %d", id); - if (c->xctype != NULL) - free(c->xctype); + free(c->xctype); c->xctype = xstrdup(xctype); /* Type has changed, so look up inactivity deadline again */ c->inactive_deadline = lookup_timeout(ssh, c->xctype); - debug2_f("labeled channel %d as %s (inactive timeout %u)", id, xctype, + debug2_f("labeled channel %d as %s (inactive timeout %ld)", id, c->xctype, c->inactive_deadline); } @@ -384,7 +406,12 @@ channel_register_fds(struct ssh *ssh, Channel *c, int rfd, int wfd, int efd, int extusage, int nonblock, int is_tty) { - int val; + struct ssh_channels *sc = ssh->chanctxt; + + /* Update the maximum file descriptor value. */ + sc->channel_max_fd = MAXIMUM(sc->channel_max_fd, rfd); + sc->channel_max_fd = MAXIMUM(sc->channel_max_fd, wfd); + sc->channel_max_fd = MAXIMUM(sc->channel_max_fd, efd); if (rfd != -1) (void)fcntl(rfd, F_SETFD, FD_CLOEXEC); @@ -410,30 +437,18 @@ c->restore_block = 0; if (nonblock == CHANNEL_NONBLOCK_STDIO) { /* - * Special handling for stdio file descriptors: do not set + * Special handling for standard file descriptors: do not set * non-blocking mode if they are TTYs. Otherwise prepare to * restore their blocking state on exit to avoid interfering * with other programs that follow. */ - if (rfd != -1 && !isatty(rfd) && - (val = fcntl(rfd, F_GETFL)) != -1 && !(val & O_NONBLOCK)) { - c->restore_flags[0] = val; + if (rfd != -1 && !isatty(rfd) && set_nonblock(rfd) == 1) c->restore_block |= CHANNEL_RESTORE_RFD; - set_nonblock(rfd); - } - if (wfd != -1 && !isatty(wfd) && - (val = fcntl(wfd, F_GETFL)) != -1 && !(val & O_NONBLOCK)) { - c->restore_flags[1] = val; + if (wfd != -1 && !isatty(wfd) && set_nonblock(wfd) == 1) c->restore_block |= CHANNEL_RESTORE_WFD; - set_nonblock(wfd); - } - if (efd != -1 && !isatty(efd) && - (val = fcntl(efd, F_GETFL)) != -1 && !(val & O_NONBLOCK)) { - c->restore_flags[2] = val; + if (efd != -1 && !isatty(efd) && set_nonblock(efd) == 1) c->restore_block |= CHANNEL_RESTORE_EFD; - set_nonblock(efd); - } - } else if (nonblock) { + } else if (nonblock == CHANNEL_NONBLOCK_SET) { if (rfd != -1) set_nonblock(rfd); if (wfd != -1) @@ -498,60 +513,86 @@ c->remote_name = xstrdup(remote_name); c->ctl_chan = -1; c->delayed = 1; /* prevent call to channel_post handler */ + c->lastused = 0; c->inactive_deadline = lookup_timeout(ssh, c->ctype); TAILQ_INIT(&c->status_confirms); - debug("channel %d: new %s [%s] (inactive timeout: %u)", + debug("channel %d: new %s [%s] (inactive timeout: %ld)", found, c->ctype, remote_name, c->inactive_deadline); return c; } -int -channel_close_fd(struct ssh *ssh, Channel *c, int *fdp) +static void +channel_find_maxfd(struct ssh_channels *sc) { - int ret, fd = *fdp; + u_int i; + int max = 0; + Channel *c; - if (fd == -1) - return 0; + for (i = 0; i < sc->channels_alloc; i++) { + c = sc->channels[i]; + if (c != NULL) { + max = MAXIMUM(max, c->rfd); + max = MAXIMUM(max, c->wfd); + max = MAXIMUM(max, c->efd); + } + } + sc->channel_max_fd = max; +} + +int +channel_close_fd(struct ssh *ssh, Channel *c, int id) +{ + struct ssh_channels *sc = ssh->chanctxt; + int fd, *fdp = NULL, restore_block = 0; - /* restore blocking */ - if (*fdp == c->rfd && - (c->restore_block & CHANNEL_RESTORE_RFD) != 0) - (void)fcntl(*fdp, F_SETFL, c->restore_flags[0]); - else if (*fdp == c->wfd && - (c->restore_block & CHANNEL_RESTORE_WFD) != 0) - (void)fcntl(*fdp, F_SETFL, c->restore_flags[1]); - else if (*fdp == c->efd && - (c->restore_block & CHANNEL_RESTORE_EFD) != 0) - (void)fcntl(*fdp, F_SETFL, c->restore_flags[2]); + switch (id) { + case SSH_CHANNEL_FD_INPUT : + fdp = &c->rfd; + break; + case SSH_CHANNEL_FD_OUTPUT: + fdp = &c->wfd; + break; + case SSH_CHANNEL_FD_ERROR : + fdp = &c->efd; + break; + case SSH_CHANNEL_FD_SOCKET: + fdp = &c->sock; + break; + } + if (fdp == NULL) return 0; + fd = *fdp; + if (fd == -1) return 0; - if (*fdp == c->rfd) { + switch (id) { + case SSH_CHANNEL_FD_INPUT : c->io_want &= ~SSH_CHAN_IO_RFD; c->io_ready &= ~SSH_CHAN_IO_RFD; - c->rfd = -1; - c->pfds[0] = -1; - } - if (*fdp == c->wfd) { + restore_block = ((c->restore_block & CHANNEL_RESTORE_RFD) != 0); + break; + case SSH_CHANNEL_FD_OUTPUT: c->io_want &= ~SSH_CHAN_IO_WFD; c->io_ready &= ~SSH_CHAN_IO_WFD; - c->wfd = -1; - c->pfds[1] = -1; - } - if (*fdp == c->efd) { + restore_block = ((c->restore_block & CHANNEL_RESTORE_WFD) != 0); + break; + case SSH_CHANNEL_FD_ERROR : c->io_want &= ~SSH_CHAN_IO_EFD; c->io_ready &= ~SSH_CHAN_IO_EFD; - c->efd = -1; - c->pfds[2] = -1; - } - if (*fdp == c->sock) { + restore_block = ((c->restore_block & CHANNEL_RESTORE_EFD) != 0); + break; + case SSH_CHANNEL_FD_SOCKET: c->io_want &= ~SSH_CHAN_IO_SOCK; c->io_ready &= ~SSH_CHAN_IO_SOCK; - c->sock = -1; - c->pfds[3] = -1; + break; } - ret = close(fd); - *fdp = -1; /* probably redundant */ - return ret; + if (restore_block) + unset_nonblock(fd); + if (close(fd) == -1) return -1; + + *fdp = -1; + if (fd == sc->channel_max_fd) + channel_find_maxfd(sc); + return 0; } /* Close all channel fd/socket. */ @@ -560,13 +601,13 @@ { int sock = c->sock, rfd = c->rfd, wfd = c->wfd, efd = c->efd; - channel_close_fd(ssh, c, &c->sock); + channel_close_fd(ssh, c, SSH_CHANNEL_FD_SOCKET); if (rfd != sock) - channel_close_fd(ssh, c, &c->rfd); + channel_close_fd(ssh, c, SSH_CHANNEL_FD_INPUT); if (wfd != sock && wfd != rfd) - channel_close_fd(ssh, c, &c->wfd); + channel_close_fd(ssh, c, SSH_CHANNEL_FD_OUTPUT); if (efd != sock && efd != rfd && efd != wfd) - channel_close_fd(ssh, c, &c->efd); + channel_close_fd(ssh, c, SSH_CHANNEL_FD_ERROR); } static void @@ -688,7 +729,7 @@ channel_rfwd_bind_host(perm->listen_host))) != 0 || (r = sshpkt_put_u32(ssh, perm->listen_port)) != 0 || (r = sshpkt_send(ssh)) != 0) { - fatal_fr(r, "channel %i", c->self); + fatal_fr(r, "channel %d", c->self); } fwd_perm_clear(perm); /* unregister */ } @@ -723,14 +764,15 @@ if (c->type == SSH_CHANNEL_MUX_CLIENT) { mux_remove_remote_forwardings(ssh, c); + /* context point to master state */ free(c->mux_ctx); c->mux_ctx = NULL; - } else if (c->type == SSH_CHANNEL_MUX_LISTENER) { - free(c->mux_ctx); + } else if (c->type == SSH_CHANNEL_MUX_PROXY) { + /* context point to client channel */ c->mux_ctx = NULL; } - if (log_level_get() >= SYSLOG_LEVEL_DEBUG3) { + if (get_log_level() >= SYSLOG_LEVEL_DEBUG3) { s = channel_open_message(ssh); debug3("channel %d: status: %s", c->self, s); free(s); @@ -774,6 +816,7 @@ free(sc->channels); sc->channels = NULL; sc->channels_alloc = 0; + sc->channel_max_fd = 0; free(sc->x11_saved_display); sc->x11_saved_display = NULL; @@ -823,7 +866,7 @@ case SSH_CHANNEL_X11_LISTENER: case SSH_CHANNEL_UNIX_LISTENER: case SSH_CHANNEL_RUNIX_LISTENER: - channel_close_fd(ssh, c, &c->sock); + channel_close_fd(ssh, c, SSH_CHANNEL_FD_SOCKET); channel_free(ssh, c); break; } @@ -966,7 +1009,7 @@ xasprintf(&ret, "t%d [%s] %s%u i%u/%zu o%u/%zu e[%s]/%zu " "fd %d/%d/%d sock %d cc %d io 0x%02x/0x%02x", - c->type, c->xctype != NULL ? c->xctype : c->ctype, + c->type, (c->xctype != NULL ? c->xctype : c->ctype), c->have_remote_id ? "r" : "nr", c->remote_id, c->istate, sshbuf_len(c->input), c->ostate, sshbuf_len(c->output), @@ -1041,7 +1084,8 @@ } static void -open_preamble(struct ssh *ssh, const char *where, Channel *c, const char *type) +open_preamble(const char *file, const char *func, int line, + struct ssh *ssh, Channel *c, const char *type) { int r; @@ -1049,10 +1093,11 @@ (r = sshpkt_put_cstring(ssh, type)) != 0 || (r = sshpkt_put_u32(ssh, c->self)) != 0 || (r = sshpkt_put_u32(ssh, c->local_window)) != 0 || - (r = sshpkt_put_u32(ssh, c->local_maxpacket)) != 0) { - fatal_r(r, "%s: channel %i: open", where, c->self); - } + (r = sshpkt_put_u32(ssh, c->local_maxpacket)) != 0) + sshfatal_fr(file, func, line, r, "channel %d: open", c->self); } +#define OPEN_PREAMBLE(ssh, c, type) \ + open_preamble(__FILE__, __func__, __LINE__, ssh, c, type) void channel_send_open(struct ssh *ssh, int id) @@ -1065,9 +1110,9 @@ return; } debug2("channel %d: send open", id); - open_preamble(ssh, __func__, c, c->ctype); + OPEN_PREAMBLE(ssh, c, c->ctype); if ((r = sshpkt_send(ssh)) != 0) - fatal_fr(r, "channel %i", c->self); + fatal_fr(r, "channel %d", c->self); } void @@ -1077,18 +1122,18 @@ int r; if (c == NULL) { - logit_f("%d: unknown channel id", id); + debug_f("%d: unknown channel id", id); return; } if (!c->have_remote_id) fatal_f("channel %d: no remote id", c->self); - debug2("channel %d: request %s confirm %d", id, service, wantconfirm); + debug2_f("channel %d: request %s confirm %d", id, service, wantconfirm); if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_REQUEST)) != 0 || (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 || (r = sshpkt_put_cstring(ssh, service)) != 0 || (r = sshpkt_put_u8(ssh, wantconfirm)) != 0) { - fatal_fr(r, "channel %i", c->self); + fatal_fr(r, "channel %d", c->self); } } @@ -1116,7 +1161,7 @@ Channel *c = channel_lookup(ssh, id); if (c == NULL) { - logit_f("%d: bad id", id); + debug_f("%d: bad id", id); return; } c->open_confirm = fn; @@ -1130,7 +1175,7 @@ Channel *c = channel_by_id(ssh, id); if (c == NULL) { - logit_f("%d: bad id", id); + debug_f("%d: bad id", id); return; } c->detach_user = fn; @@ -1143,7 +1188,7 @@ Channel *c = channel_by_id(ssh, id); if (c == NULL) { - logit_f("%d: bad id", id); + debug_f("%d: bad id", id); return; } c->detach_user = NULL; @@ -1157,7 +1202,7 @@ Channel *c = channel_lookup(ssh, id); if (c == NULL) { - logit_f("%d: bad id", id); + debug_f("%d: bad id", id); return; } c->input_filter = ifn; @@ -1187,18 +1232,20 @@ (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 || (r = sshpkt_put_u32(ssh, c->local_window)) != 0 || (r = sshpkt_send(ssh)) != 0) - fatal_fr(r, "channel %i", c->self); + fatal_fr(r, "channel %d", c->self); } static void channel_pre_listener(struct ssh *ssh, Channel *c) { + UNUSED(ssh); c->io_want = SSH_CHAN_IO_SOCK_R; } static void channel_pre_connecting(struct ssh *ssh, Channel *c) { + UNUSED(ssh); debug3("channel %d: waiting for connection", c->self); c->io_want = SSH_CHAN_IO_SOCK_W; } @@ -1317,31 +1364,43 @@ } void -channel_force_close(struct ssh *ssh, Channel *c, int abandon) +channel_force_close(struct ssh *ssh, Channel *c) { - debug3_f("channel %d: forcibly closing", c->self); + debug3_f("channel %d", c->self); + if (c->istate == CHAN_INPUT_OPEN) chan_read_failed(ssh, c); - if (c->istate == CHAN_INPUT_WAIT_DRAIN) { - sshbuf_reset(c->input); + + sshbuf_reset(c->input); + if (c->istate == CHAN_INPUT_WAIT_DRAIN) chan_ibuf_empty(ssh, c); - } + + sshbuf_reset(c->output); if (c->ostate == CHAN_OUTPUT_OPEN || - c->ostate == CHAN_OUTPUT_WAIT_DRAIN) { - sshbuf_reset(c->output); + c->ostate == CHAN_OUTPUT_WAIT_DRAIN) chan_write_failed(ssh, c); + + if (channel_close_fd(ssh, c, SSH_CHANNEL_FD_ERROR) < 0) { + error_f("channel %d: close() failed for " + "extended fd %d [i%d o%d]: %.100s", c->self, c->efd, + c->istate, c->ostate, strerror(errno)); } - if (c->detach_user) - c->detach_user(ssh, c->self, 1, NULL); - if (c->efd != -1) - channel_close_fd(ssh, c, &c->efd); - if (abandon) - c->type = SSH_CHANNEL_ABANDONED; + c->lastused = 0; /* exempt from inactivity timeouts */ c->inactive_deadline = 0; - c->lastused = 0; } +void +channel_abandon(struct ssh *ssh, Channel *c) { + debug3_f("channel %d", c->self); + + channel_force_close(ssh, c); + if (c->detach_user) + c->detach_user(ssh, c->self, 1, NULL); + c->type = SSH_CHANNEL_ABANDONED; +} + + static void channel_pre_x11_open(struct ssh *ssh, Channel *c) { @@ -1351,14 +1410,13 @@ if (ret == 1) { c->type = SSH_CHANNEL_OPEN; - c->lastused = monotime(); channel_pre_open(ssh, c); } else if (ret == -1) { - logit("X11 connection rejected because of wrong " - "authentication."); + logit("X11 connection rejected because of wrong authentication."); debug2("X11 rejected %d i%d/o%d", c->self, c->istate, c->ostate); - channel_force_close(ssh, c, 0); + channel_force_close(ssh, c); + debug2("X11 closed %d i%d/o%d", c->self, c->istate, c->ostate); } } @@ -1401,7 +1459,7 @@ } s4_req, s4_rsp; int r; - debug2("channel %d: decode socks4", c->self); + debug2_f("channel %d", c->self); have = sshbuf_len(input); len = sizeof(s4_req); @@ -1425,8 +1483,7 @@ } if (i > 1024) { /* the peer is probably sending garbage */ - debug("channel %d: decode socks4: too long", - c->self); + debug_f("channel %d: too long", c->self); return -1; } } @@ -1436,17 +1493,17 @@ (r = sshbuf_get(input, &s4_req.command, 1)) != 0 || (r = sshbuf_get(input, &s4_req.dest_port, 2)) != 0 || (r = sshbuf_get(input, &s4_req.dest_addr, 4)) != 0) { - debug_r(r, "channels %d: decode socks4", c->self); + error_fr(r, "channels %d: parse", c->self); return -1; } have = sshbuf_len(input); p = sshbuf_ptr(input); if (memchr(p, '\0', have) == NULL) { - error("channel %d: decode socks4: unterminated user", c->self); + error_f("channel %d: unterminated user", c->self); return -1; } len = strlen(p); - debug2("channel %d: decode socks4: user %s/%d", c->self, p, len); + debug2_f("channel %d: user %s/%d", c->self, p, len); len++; /* trailing '\0' */ strlcpy(username, p, sizeof(username)); if ((r = sshbuf_consume(input, len)) != 0) @@ -1460,16 +1517,15 @@ have = sshbuf_len(input); p = sshbuf_ptr(input); if (memchr(p, '\0', have) == NULL) { - error("channel %d: decode socks4a: host not nul " - "terminated", c->self); + error_f("channel %d: host not nul terminated", + c->self); return -1; } len = strlen(p); - debug2("channel %d: decode socks4a: host %s/%d", - c->self, p, len); + debug2_f("channel %d: host %s/%d", c->self, p, len); len++; /* trailing '\0' */ if (len > NI_MAXHOST) { - error("channel %d: hostname \"%.100s\" too long", + error_f("channel %d: hostname \"%.100s\" too long", c->self, p); return -1; } @@ -1479,7 +1535,7 @@ } c->host_port = ntohs(s4_req.dest_port); - debug2("channel %d: dynamic request: socks4 host %s port %u command %u", + debug2_f("channel %d: host %s port %u command %u", c->self, c->path, c->host_port, s4_req.command); if (s4_req.command != 1) { @@ -1521,7 +1577,7 @@ u_int have, need, i, found, nmethods, addrlen, af; int r; - debug2("channel %d: decode socks5", c->self); + debug2_f("channel %d", c->self); p = sshbuf_ptr(input); if (p[0] != 0x05) return -1; @@ -1596,7 +1652,7 @@ } if ((r = sshbuf_get(input, &dest_addr, addrlen)) != 0 || (r = sshbuf_get(input, &dest_port, 2)) != 0) { - debug_r(r, "channel %d: parse addr/port", c->self); + error_fr(r, "channel %d: parse addr/port", c->self); return -1; } dest_addr[addrlen] = '\0'; @@ -1604,8 +1660,8 @@ c->path = NULL; if (s5_req.atyp == SSH_SOCKS5_DOMAIN) { if (addrlen >= NI_MAXHOST) { - error("channel %d: dynamic request: socks5 hostname " - "\"%.100s\" too long", c->self, dest_addr); + error_f("channel %d: hostname \"%.100s\" too long", + c->self, dest_addr); return -1; } c->path = xstrdup(dest_addr); @@ -1616,7 +1672,7 @@ } c->host_port = ntohs(dest_port); - debug2("channel %d: dynamic request: socks5 host %s port %u command %u", + debug2_f("channel %d: host %s port %u command %u", c->self, c->path, c->host_port, s5_req.command); s5_rsp.version = 0x05; @@ -1672,7 +1728,7 @@ /* check if the fixed size part of the packet is in buffer. */ if (have < 3) { /* need more */ - c->io_want |= SSH_CHAN_IO_RFD; + c->io_want |= SSH_CHAN_IO_SOCK_R; return; } /* try to guess the protocol */ @@ -1694,9 +1750,9 @@ } else if (ret == 0) { debug2("channel %d: pre_dynamic: need more", c->self); /* need more */ - c->io_want |= SSH_CHAN_IO_RFD; + c->io_want |= SSH_CHAN_IO_SOCK_R; if (sshbuf_len(c->output)) - c->io_want |= SSH_CHAN_IO_WFD; + c->io_want |= SSH_CHAN_IO_SOCK_W; } else { /* switch to the next state */ c->type = SSH_CHANNEL_OPENING; @@ -1708,8 +1764,8 @@ static void rdynamic_close(struct ssh *ssh, Channel *c) { + channel_force_close(ssh, c); c->type = SSH_CHANNEL_OPEN; - channel_force_close(ssh, c, 0); } /* reverse dynamic port forwarding */ @@ -1758,7 +1814,7 @@ (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 || (r = sshpkt_put_stringb(ssh, c->input)) != 0 || (r = sshpkt_send(ssh)) != 0) { - fatal_fr(r, "channel %i: rdynamic", c->self); + fatal_fr(r, "channel %d: rdynamic", c->self); } if ((r = sshbuf_consume(c->input, len)) != 0) fatal_fr(r, "channel %d: consume", c->self); @@ -1789,7 +1845,7 @@ if (c->single_connection) { oerrno = errno; debug2("single_connection: closing X11 listener."); - channel_close_fd(ssh, c, &c->sock); + channel_close_fd(ssh, c, SSH_CHANNEL_FD_SOCKET); chan_mark_dead(ssh, c); errno = oerrno; } @@ -1810,13 +1866,13 @@ nc = channel_new(ssh, "x11-connection", SSH_CHANNEL_OPENING, newsock, newsock, -1, c->local_window_max, c->local_maxpacket, 0, buf, 1); - open_preamble(ssh, __func__, nc, "x11"); + OPEN_PREAMBLE(ssh, nc, "x11"); if ((r = sshpkt_put_cstring(ssh, remote_ipaddr)) != 0 || (r = sshpkt_put_u32(ssh, remote_port)) != 0) { - fatal_fr(r, "channel %i: reply", c->self); + fatal_fr(r, "channel %d: reply", c->self); } if ((r = sshpkt_send(ssh)) != 0) - fatal_fr(r, "channel %i: send", c->self); + fatal_fr(r, "channel %d: send", c->self); free(remote_ipaddr); } @@ -1843,38 +1899,38 @@ rtype, c->listening_port, c->path, c->host_port, remote_ipaddr, remote_port, local_ipaddr, local_port); - open_preamble(ssh, __func__, c, rtype); + OPEN_PREAMBLE(ssh, c, rtype); if (strcmp(rtype, "direct-tcpip") == 0) { /* target host, port */ if ((r = sshpkt_put_cstring(ssh, c->path)) != 0 || (r = sshpkt_put_u32(ssh, c->host_port)) != 0) - fatal_fr(r, "channel %i: reply", c->self); + fatal_fr(r, "channel %d: reply", c->self); } else if (strcmp(rtype, "direct-streamlocal@openssh.com") == 0) { /* target path */ if ((r = sshpkt_put_cstring(ssh, c->path)) != 0) - fatal_fr(r, "channel %i: reply", c->self); + fatal_fr(r, "channel %d: reply", c->self); } else if (strcmp(rtype, "forwarded-streamlocal@openssh.com") == 0) { /* listen path */ if ((r = sshpkt_put_cstring(ssh, c->path)) != 0) - fatal_fr(r, "channel %i: reply", c->self); + fatal_fr(r, "channel %d: reply", c->self); } else { /* listen address, port */ if ((r = sshpkt_put_cstring(ssh, c->path)) != 0 || (r = sshpkt_put_u32(ssh, local_port)) != 0) - fatal_fr(r, "channel %i: reply", c->self); + fatal_fr(r, "channel %d: reply", c->self); } if (strcmp(rtype, "forwarded-streamlocal@openssh.com") == 0) { /* reserved for future owner/mode info */ if ((r = sshpkt_put_cstring(ssh, "")) != 0) - fatal_fr(r, "channel %i: reply", c->self); + fatal_fr(r, "channel %d: reply", c->self); } else { /* originator host and port */ if ((r = sshpkt_put_cstring(ssh, remote_ipaddr)) != 0 || (r = sshpkt_put_u32(ssh, (u_int)remote_port)) != 0) - fatal_fr(r, "channel %i: reply", c->self); + fatal_fr(r, "channel %d: reply", c->self); } if ((r = sshpkt_send(ssh)) != 0) - fatal_fr(r, "channel %i: send", c->self); + fatal_fr(r, "channel %d: send", c->self); free(remote_ipaddr); free(local_ipaddr); } @@ -1970,9 +2026,9 @@ SSH_CHANNEL_OPENING, newsock, newsock, -1, c->local_window_max, c->local_maxpacket, 0, "accepted auth socket", 1); - open_preamble(ssh, __func__, nc, "auth-agent@openssh.com"); + OPEN_PREAMBLE(ssh, nc, "auth-agent@openssh.com"); if ((r = sshpkt_send(ssh)) != 0) - fatal_fr(r, "channel %i", c->self); + fatal_fr(r, "channel %d", c->self); } static void @@ -1987,14 +2043,11 @@ fatal_f("channel %d: no remote id", c->self); /* for rdynamic the OPEN_CONFIRMATION has been sent already */ isopen = (c->type == SSH_CHANNEL_RDYNAMIC_FINISH); - if (getsockopt(c->sock, SOL_SOCKET, SO_ERROR, &err, &sz) == -1) { err = errno; error("getsockopt SO_ERROR failed"); } - if (err == 0) { - /* Non-blocking connection completed */ debug("channel %d: connected to %s port %d", c->self, c->connect_ctx.host, c->connect_ctx.port); channel_connect_ctx_free(&c->connect_ctx); @@ -2010,19 +2063,19 @@ (r = sshpkt_put_u32(ssh, c->local_window)) != 0 || (r = sshpkt_put_u32(ssh, c->local_maxpacket)) != 0 || (r = sshpkt_send(ssh)) != 0) - fatal_fr(r, "channel %i open confirm", c->self); + fatal_fr(r, "channel %d: open confirm", c->self); } - return; - } - if (err == EINTR || err == EAGAIN || err == EINPROGRESS) - return; - - /* Non-blocking connection failed */ - debug("channel %d: connection failed: %s", c->self, strerror(err)); - - /* Try next address, if any */ - if ((sock = connect_next(&c->connect_ctx)) == -1) { - /* Exhausted all addresses for this destination */ + } else { + debug("channel %d: connection failed: %s", + c->self, strerror(err)); + /* Try next address, if any */ + if ((sock = connect_next(&c->connect_ctx)) > 0) { + close(c->sock); + c->sock = c->rfd = c->wfd = sock; + channel_find_maxfd(ssh->chanctxt); + return; + } + /* Exhausted all addresses */ error("connect_to %.100s port %d: failed.", c->connect_ctx.host, c->connect_ctx.port); channel_connect_ctx_free(&c->connect_ctx); @@ -2037,14 +2090,10 @@ (r = sshpkt_put_cstring(ssh, strerror(err))) != 0 || (r = sshpkt_put_cstring(ssh, "")) != 0 || (r = sshpkt_send(ssh)) != 0) - fatal_fr(r, "channel %i: failure", c->self); + fatal_fr(r, "channel %d: open failure", c->self); chan_mark_dead(ssh, c); } } - - /* New non-blocking connection in progress */ - close(c->sock); - c->sock = c->rfd = c->wfd = sock; } static int @@ -2053,7 +2102,6 @@ char buf[CHAN_RBUF]; ssize_t len; int r, force; - size_t nr = 0, have, avail, maxlen = CHANNEL_MAX_READ; int pty_zeroread = 0; #ifdef PTY_ZEROREAD @@ -2065,14 +2113,18 @@ if (!force && (c->io_ready & SSH_CHAN_IO_RFD) == 0) return 1; - if ((avail = sshbuf_avail(c->input)) == 0) - return 1; /* Shouldn't happen */ +#ifdef USE_DIRECT_READ /* * For "simple" channels (i.e. not datagram or filtered), we can * read directly to the channel buffer. */ if (!pty_zeroread && c->input_filter == NULL && !c->datagram) { + size_t nr = 0, have, avail, maxlen = CHAN_RBUF; + + if ((avail = sshbuf_avail(c->input)) == 0) + return 1; /* Shouldn't happen */ + /* Only OPEN channels have valid rwin */ if (c->type == SSH_CHANNEL_OPEN) { if ((have = sshbuf_len(c->input)) >= c->remote_window) @@ -2083,9 +2135,16 @@ if (maxlen > avail) maxlen = avail; if ((r = sshbuf_read(c->rfd, c->input, maxlen, &nr)) != 0) { - if (errno == EINTR || (!force && - (errno == EAGAIN || errno == EWOULDBLOCK))) - return 1; + if (r == SSH_ERR_SYSTEM_ERROR) { + if (errno == EINTR || (!force && + (errno == EAGAIN || errno == EWOULDBLOCK))) + return 1; + if (errno == EPIPE) { + debug2("channel %d: read channel closed" + " by remote rfd %d", c->self, c->rfd); + goto rfail; + } + } debug2("channel %d: read failed rfd %d maxlen %zu: %s", c->self, c->rfd, maxlen, ssh_err(r)); goto rfail; @@ -2094,6 +2153,7 @@ c->lastused = monotime(); return 1; } +#endif /*def USE_DIRECT_READ*/ errno = 0; len = read(c->rfd, buf, sizeof(buf)); @@ -2107,7 +2167,9 @@ debug2("channel %d: read<=0 rfd %d len %zd: %s", c->self, c->rfd, len, len == 0 ? "closed" : strerror(errno)); +#ifdef USE_DIRECT_READ rfail: +#endif if (c->type != SSH_CHANNEL_OPEN) { debug2("channel %d: not open", c->self); chan_mark_dead(ssh, c); @@ -2125,17 +2187,15 @@ } } else if (c->datagram) { if ((r = sshbuf_put_string(c->input, buf, len)) != 0) - fatal_fr(r, "channel %i: put datagram", c->self); + fatal_fr(r, "channel %d: put datagram", c->self); } else if ((r = sshbuf_put(c->input, buf, len)) != 0) - fatal_fr(r, "channel %i: put data", c->self); - + fatal_fr(r, "channel %d: put data", c->self); return 1; } static int channel_handle_wfd(struct ssh *ssh, Channel *c) { - struct termios tio; u_char *data = NULL, *buf; /* XXX const; need filter API change */ size_t dlen, olen = 0; int r, len; @@ -2158,7 +2218,7 @@ } } else if (c->datagram) { if ((r = sshbuf_get_string(c->output, &data, &dlen)) != 0) - fatal_fr(r, "channel %i: get datagram", c->self); + fatal_fr(r, "channel %d: get datagram", c->self); buf = data; } else { buf = data = sshbuf_mutable_ptr(c->output); @@ -2200,8 +2260,10 @@ } c->lastused = monotime(); #ifndef BROKEN_TCGETATTR_ICANON +{ struct termios tio; + if (c->isatty && dlen >= 1 && buf[0] != '\r') { - if (tcgetattr(c->wfd, &tio) == 0 && + if (tcgetattr(c->wfd, &tio) != -1 && !(tio.c_lflag & ECHO) && (tio.c_lflag & ICANON)) { /* * Simulate echo to reduce the impact of @@ -2211,12 +2273,13 @@ */ if ((r = sshpkt_msg_ignore(ssh, 4+len)) != 0 || (r = sshpkt_send(ssh)) != 0) - fatal_fr(r, "channel %i: ignore", c->self); + fatal_fr(r, "channel %d: ignore", c->self); } } +} #endif /* BROKEN_TCGETATTR_ICANON */ if ((r = sshbuf_consume(c->output, len)) != 0) - fatal_fr(r, "channel %i: consume", c->self); + fatal_fr(r, "channel %d: consume", c->self); out: c->local_consumed += olen - sshbuf_len(c->output); @@ -2242,10 +2305,10 @@ return 1; if (len <= 0) { debug2("channel %d: closing write-efd %d", c->self, c->efd); - channel_close_fd(ssh, c, &c->efd); + channel_close_fd(ssh, c, SSH_CHANNEL_FD_ERROR); } else { if ((r = sshbuf_consume(c->extended, len)) != 0) - fatal_fr(r, "channel %i: consume", c->self); + fatal_fr(r, "channel %d: consume", c->self); c->local_consumed += len; c->lastused = monotime(); } @@ -2264,6 +2327,7 @@ if (!force && (c->io_ready & SSH_CHAN_IO_EFD_R) == 0) return 1; + errno = 0; len = read(c->efd, buf, sizeof(buf)); debug2("channel %d: read %zd from efd %d", c->self, len, c->efd); if (len == -1 && (errno == EINTR || ((errno == EAGAIN || @@ -2271,14 +2335,14 @@ return 1; if (len <= 0) { debug2("channel %d: closing read-efd %d", c->self, c->efd); - channel_close_fd(ssh, c, &c->efd); + channel_close_fd(ssh, c, SSH_CHANNEL_FD_ERROR); return 1; } c->lastused = monotime(); if (c->extended_usage == CHAN_EXTENDED_IGNORE) debug3("channel %d: discard efd", c->self); else if ((r = sshbuf_put(c->extended, buf, len)) != 0) - fatal_fr(r, "channel %i: append", c->self); + fatal_fr(r, "channel %d: append", c->self); return 1; } @@ -2316,9 +2380,8 @@ SSH2_MSG_CHANNEL_WINDOW_ADJUST)) != 0 || (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 || (r = sshpkt_put_u32(ssh, c->local_consumed)) != 0 || - (r = sshpkt_send(ssh)) != 0) { - fatal_fr(r, "channel %i", c->self); - } + (r = sshpkt_send(ssh)) != 0) + fatal_fr(r, "channel %d", c->self); debug2("channel %d: window %d sent adjust %d", c->self, c->local_window, c->local_consumed); c->local_window += c->local_consumed; @@ -2355,7 +2418,7 @@ chan_read_failed(ssh, c); return 0; } else if ((r = sshbuf_put(c->input, buf, len)) != 0) - fatal_fr(r, "channel %i: append", c->self); + fatal_fr(r, "channel %d: append", c->self); } return sshbuf_len(c->input); } @@ -2415,7 +2478,7 @@ return; } if ((r = sshbuf_consume(c->output, len)) != 0) - fatal_fr(r, "channel %i: consume", c->self); + fatal_fr(r, "channel %d: consume", c->self); } static void @@ -2540,6 +2603,45 @@ enum channel_table { CHAN_PRE, CHAN_POST }; +/* populate collect wanted io-events by channel pre-callback */ +static void +channel_mask_io_want(Channel *c, fd_set *readset, fd_set *writeset) +{ + u_int event = c->io_want; + +#define EVENT_SET(fd, set, flag) \ + if ((event & flag) != 0) FD_SET(fd, set) + + EVENT_SET(c->rfd , readset , SSH_CHAN_IO_RFD ); + EVENT_SET(c->wfd , writeset, SSH_CHAN_IO_WFD ); + EVENT_SET(c->efd , readset , SSH_CHAN_IO_EFD_R ); + EVENT_SET(c->efd , writeset, SSH_CHAN_IO_EFD_W ); + EVENT_SET(c->sock, readset , SSH_CHAN_IO_SOCK_R); + EVENT_SET(c->sock, writeset, SSH_CHAN_IO_SOCK_W); + +#undef EVENT_SET +} + +/* set events ready for processing by channel post-callback */ +static void +channel_mask_io_ready(Channel *c, fd_set *readset, fd_set *writeset) +{ + u_int event = 0; + +#define EVENT_ISSET(fd, set, flag) \ + if (fd >= 0 && FD_ISSET(fd, set)) event |= (u_int)flag + + EVENT_ISSET(c->rfd , readset , SSH_CHAN_IO_RFD ); + EVENT_ISSET(c->wfd , writeset, SSH_CHAN_IO_WFD ); + EVENT_ISSET(c->efd , readset , SSH_CHAN_IO_EFD_R ); + EVENT_ISSET(c->efd , writeset, SSH_CHAN_IO_EFD_W ); + EVENT_ISSET(c->sock, readset , SSH_CHAN_IO_SOCK_R); + EVENT_ISSET(c->sock, writeset, SSH_CHAN_IO_SOCK_W); + +#undef EVENT_ISSET + c->io_ready = event; +} + static void channel_handler(struct ssh *ssh, int table, struct timespec *timeout) { @@ -2554,9 +2656,6 @@ c = sc->channels[i]; if (c == NULL) continue; - /* Try to keep IO going while rekeying */ - if (ssh_packet_is_rekeying(ssh) && c->type != SSH_CHANNEL_OPEN) - continue; if (c->delayed) { if (table == CHAN_PRE) c->delayed = 0; @@ -2564,29 +2663,32 @@ continue; } if (ftab[c->type] != NULL) { + time_t deadline = (time_t)(c->lastused + c->inactive_deadline); + if (deadline < c->lastused) + deadline = 0; /*overflow*/ if (table == CHAN_PRE && c->type == SSH_CHANNEL_OPEN && c->inactive_deadline != 0 && c->lastused != 0 && - now >= c->lastused + c->inactive_deadline) { + now >= deadline) { /* channel closed for inactivity */ - verbose("channel %d: closing after %u seconds " + verbose("channel %d: closing after %ld seconds " "of inactivity", c->self, c->inactive_deadline); - channel_force_close(ssh, c, 1); + channel_abandon(ssh, c); } else if (c->notbefore <= now) { /* Run handlers that are not paused. */ (*ftab[c->type])(ssh, c); - /* inactivity timeouts must interrupt poll() */ + /* inactivity timeouts must interrupt main loop */ if (timeout != NULL && c->type == SSH_CHANNEL_OPEN && c->lastused != 0 && c->inactive_deadline != 0) { ptimeout_deadline_monotime(timeout, - c->lastused + c->inactive_deadline); + deadline); } } else if (timeout != NULL) { /* - * Arrange for poll() wakeup when channel pause + * Arrange for wakeup when channel pause * timer expires. */ ptimeout_deadline_monotime(timeout, @@ -2598,10 +2700,9 @@ } /* - * Create sockets before preparing IO. + * Create sockets before allocating the select bitmasks. * This is necessary for things that need to happen after reading - * the network-input but need to be completed before IO event setup, e.g. - * because they may create new channels. + * the network-input but before channel_prepare_select(). */ static void channel_before_prepare_io(struct ssh *ssh) @@ -2619,272 +2720,75 @@ } } -static void -dump_channel_poll(const char *func, const char *what, Channel *c, - u_int pollfd_offset, struct pollfd *pfd) -{ -#ifdef DEBUG_CHANNEL_POLL - debug3("%s: channel %d: %s r%d w%d e%d s%d c->pfds [ %d %d %d %d ] " - "io_want 0x%02x io_ready 0x%02x pfd[%u].fd=%d " - "pfd.ev 0x%02x pfd.rev 0x%02x", func, c->self, what, - c->rfd, c->wfd, c->efd, c->sock, - c->pfds[0], c->pfds[1], c->pfds[2], c->pfds[3], - c->io_want, c->io_ready, - pollfd_offset, pfd->fd, pfd->events, pfd->revents); -#endif -} - -/* Prepare pollfd entries for a single channel */ -static void -channel_prepare_pollfd(Channel *c, u_int *next_pollfd, - struct pollfd *pfd, u_int npfd) -{ - u_int ev, p = *next_pollfd; - - if (c == NULL) - return; - if (p + 4 > npfd) { - /* Shouldn't happen */ - fatal_f("channel %d: bad pfd offset %u (max %u)", - c->self, p, npfd); - } - c->pfds[0] = c->pfds[1] = c->pfds[2] = c->pfds[3] = -1; - /* - * prepare c->rfd - * - * This is a special case, since c->rfd might be the same as - * c->wfd, c->efd and/or c->sock. Handle those here if they want - * IO too. - */ - if (c->rfd != -1) { - ev = 0; - if ((c->io_want & SSH_CHAN_IO_RFD) != 0) - ev |= POLLIN; - /* rfd == wfd */ - if (c->wfd == c->rfd) { - if ((c->io_want & SSH_CHAN_IO_WFD) != 0) - ev |= POLLOUT; - } - /* rfd == efd */ - if (c->efd == c->rfd) { - if ((c->io_want & SSH_CHAN_IO_EFD_R) != 0) - ev |= POLLIN; - if ((c->io_want & SSH_CHAN_IO_EFD_W) != 0) - ev |= POLLOUT; - } - /* rfd == sock */ - if (c->sock == c->rfd) { - if ((c->io_want & SSH_CHAN_IO_SOCK_R) != 0) - ev |= POLLIN; - if ((c->io_want & SSH_CHAN_IO_SOCK_W) != 0) - ev |= POLLOUT; - } - /* Pack a pfd entry if any event armed for this fd */ - if (ev != 0) { - c->pfds[0] = p; - pfd[p].fd = c->rfd; - pfd[p].events = ev; - dump_channel_poll(__func__, "rfd", c, p, &pfd[p]); - p++; - } - } - /* prepare c->wfd if wanting IO and not already handled above */ - if (c->wfd != -1 && c->rfd != c->wfd) { - ev = 0; - if ((c->io_want & SSH_CHAN_IO_WFD)) - ev |= POLLOUT; - /* Pack a pfd entry if any event armed for this fd */ - if (ev != 0) { - c->pfds[1] = p; - pfd[p].fd = c->wfd; - pfd[p].events = ev; - dump_channel_poll(__func__, "wfd", c, p, &pfd[p]); - p++; - } - } - /* prepare c->efd if wanting IO and not already handled above */ - if (c->efd != -1 && c->rfd != c->efd) { - ev = 0; - if ((c->io_want & SSH_CHAN_IO_EFD_R) != 0) - ev |= POLLIN; - if ((c->io_want & SSH_CHAN_IO_EFD_W) != 0) - ev |= POLLOUT; - /* Pack a pfd entry if any event armed for this fd */ - if (ev != 0) { - c->pfds[2] = p; - pfd[p].fd = c->efd; - pfd[p].events = ev; - dump_channel_poll(__func__, "efd", c, p, &pfd[p]); - p++; - } - } - /* prepare c->sock if wanting IO and not already handled above */ - if (c->sock != -1 && c->rfd != c->sock) { - ev = 0; - if ((c->io_want & SSH_CHAN_IO_SOCK_R) != 0) - ev |= POLLIN; - if ((c->io_want & SSH_CHAN_IO_SOCK_W) != 0) - ev |= POLLOUT; - /* Pack a pfd entry if any event armed for this fd */ - if (ev != 0) { - c->pfds[3] = p; - pfd[p].fd = c->sock; - pfd[p].events = 0; - dump_channel_poll(__func__, "sock", c, p, &pfd[p]); - p++; - } - } - *next_pollfd = p; -} - -/* * Allocate/prepare poll structure */ +/* + * Allocate/update select bitmasks and add any bits relevant to channels in + * select bitmasks. + */ void -channel_prepare_poll(struct ssh *ssh, struct pollfd **pfdp, u_int *npfd_allocp, - u_int *npfd_activep, u_int npfd_reserved, struct timespec *timeout) +channel_prepare_select(struct ssh *ssh, fd_set **readsetp, fd_set **writesetp, + int *maxfdp, u_int *nallocp, struct timespec *timeout) { - struct ssh_channels *sc = ssh->chanctxt; - u_int i, oalloc, p, npfd = npfd_reserved; + u_int n, sz, nfdset; channel_before_prepare_io(ssh); /* might create a new channel */ - /* clear out I/O flags from last poll */ - for (i = 0; i < sc->channels_alloc; i++) { - if (sc->channels[i] == NULL) - continue; - sc->channels[i]->io_want = sc->channels[i]->io_ready = 0; - } - /* Allocate 4x pollfd for each channel (rfd, wfd, efd, sock) */ - if (sc->channels_alloc >= (INT_MAX / 4) - npfd_reserved) - fatal_f("too many channels"); /* shouldn't happen */ - npfd += sc->channels_alloc * 4; - if (npfd > *npfd_allocp) { - *pfdp = xrecallocarray(*pfdp, *npfd_allocp, - npfd, sizeof(**pfdp)); - *npfd_allocp = npfd; - } - *npfd_activep = npfd_reserved; - oalloc = sc->channels_alloc; - channel_handler(ssh, CHAN_PRE, timeout); + n = MAXIMUM(*maxfdp, ssh->chanctxt->channel_max_fd); - if (oalloc != sc->channels_alloc) { - /* shouldn't happen */ - fatal_f("channels_alloc changed during CHAN_PRE " - "(was %u, now %u)", oalloc, sc->channels_alloc); - } + nfdset = howmany(n+1, NFDBITS); + /* Explicitly test here, because xreallocarray isn't always called */ + if (nfdset && SIZE_MAX / nfdset < sizeof(fd_mask)) + fatal("channel_prepare_select: max_fd (%d) is too large", n); + sz = nfdset * sizeof(fd_mask); + + /* perhaps check sz < nalloc/2 and shrink? */ + if (*readsetp == NULL || sz > *nallocp) { + *readsetp = xreallocarray(*readsetp, nfdset, sizeof(fd_mask)); + *writesetp = xreallocarray(*writesetp, nfdset, sizeof(fd_mask)); + *nallocp = sz; + } + *maxfdp = n; + memset(*readsetp, 0, sz); + memset(*writesetp, 0, sz); - /* Prepare pollfd */ - p = npfd_reserved; - for (i = 0; i < sc->channels_alloc; i++) - channel_prepare_pollfd(sc->channels[i], &p, *pfdp, npfd); - *npfd_activep = p; -} + if (ssh_packet_is_rekeying(ssh)) return; -static void -fd_ready(Channel *c, int p, struct pollfd *pfds, u_int npfd, int fd, - const char *what, u_int revents_mask, u_int ready) -{ - struct pollfd *pfd = &pfds[p]; + channel_handler(ssh, CHAN_PRE, timeout); - if (fd == -1) - return; - if (p == -1 || (u_int)p >= npfd) - fatal_f("channel %d: bad pfd %d (max %u)", c->self, p, npfd); - dump_channel_poll(__func__, what, c, p, pfd); - if (pfd->fd != fd) { - fatal("channel %d: inconsistent %s fd=%d pollfd[%u].fd %d " - "r%d w%d e%d s%d", c->self, what, fd, p, pfd->fd, - c->rfd, c->wfd, c->efd, c->sock); - } - if ((pfd->revents & POLLNVAL) != 0) { - fatal("channel %d: invalid %s pollfd[%u].fd %d r%d w%d e%d s%d", - c->self, what, p, pfd->fd, c->rfd, c->wfd, c->efd, c->sock); +{ /* convert c->io_want into read/write sets */ + struct ssh_channels *sc = ssh->chanctxt; + u_int i; + Channel *c; + + for (i = 0; i < sc->channels_alloc; i++) { + c = sc->channels[i]; + if (c == NULL) + continue; + channel_mask_io_want(c, *readsetp, *writesetp); } - if ((pfd->revents & (revents_mask|POLLHUP|POLLERR)) != 0) - c->io_ready |= ready & c->io_want; +} } /* - * After poll, perform any appropriate operations for channels which have + * After select, perform any appropriate operations for channels which have * events pending. */ void -channel_after_poll(struct ssh *ssh, struct pollfd *pfd, u_int npfd) +channel_after_select(struct ssh *ssh, fd_set *readset, fd_set *writeset) { + if (ssh_packet_is_rekeying(ssh)) return; + +{ /* convert read/write sets into c->io_ready */ struct ssh_channels *sc = ssh->chanctxt; u_int i; - int p; Channel *c; -#ifdef DEBUG_CHANNEL_POLL - for (p = 0; p < (int)npfd; p++) { - if (pfd[p].revents == 0) - continue; - debug_f("pfd[%u].fd %d rev 0x%04x", - p, pfd[p].fd, pfd[p].revents); - } -#endif - - /* Convert pollfd into c->io_ready */ for (i = 0; i < sc->channels_alloc; i++) { c = sc->channels[i]; if (c == NULL) continue; - /* if rfd is shared with efd/sock then wfd should be too */ - if (c->rfd != -1 && c->wfd != -1 && c->rfd != c->wfd && - (c->rfd == c->efd || c->rfd == c->sock)) { - /* Shouldn't happen */ - fatal_f("channel %d: unexpected fds r%d w%d e%d s%d", - c->self, c->rfd, c->wfd, c->efd, c->sock); - } - c->io_ready = 0; - /* rfd, potentially shared with wfd, efd and sock */ - if (c->rfd != -1 && (p = c->pfds[0]) != -1) { - fd_ready(c, p, pfd, npfd, c->rfd, - "rfd", POLLIN, SSH_CHAN_IO_RFD); - if (c->rfd == c->wfd) { - fd_ready(c, p, pfd, npfd, c->wfd, - "wfd/r", POLLOUT, SSH_CHAN_IO_WFD); - } - if (c->rfd == c->efd) { - fd_ready(c, p, pfd, npfd, c->efd, - "efdr/r", POLLIN, SSH_CHAN_IO_EFD_R); - fd_ready(c, p, pfd, npfd, c->efd, - "efdw/r", POLLOUT, SSH_CHAN_IO_EFD_W); - } - if (c->rfd == c->sock) { - fd_ready(c, p, pfd, npfd, c->sock, - "sockr/r", POLLIN, SSH_CHAN_IO_SOCK_R); - fd_ready(c, p, pfd, npfd, c->sock, - "sockw/r", POLLOUT, SSH_CHAN_IO_SOCK_W); - } - dump_channel_poll(__func__, "rfd", c, p, pfd); - } - /* wfd */ - if (c->wfd != -1 && c->wfd != c->rfd && - (p = c->pfds[1]) != -1) { - fd_ready(c, p, pfd, npfd, c->wfd, - "wfd", POLLOUT, SSH_CHAN_IO_WFD); - dump_channel_poll(__func__, "wfd", c, p, pfd); - } - /* efd */ - if (c->efd != -1 && c->efd != c->rfd && - (p = c->pfds[2]) != -1) { - fd_ready(c, p, pfd, npfd, c->efd, - "efdr", POLLIN, SSH_CHAN_IO_EFD_R); - fd_ready(c, p, pfd, npfd, c->efd, - "efdw", POLLOUT, SSH_CHAN_IO_EFD_W); - dump_channel_poll(__func__, "efd", c, p, pfd); - } - /* sock */ - if (c->sock != -1 && c->sock != c->rfd && - (p = c->pfds[3]) != -1) { - fd_ready(c, p, pfd, npfd, c->sock, - "sockr", POLLIN, SSH_CHAN_IO_SOCK_R); - fd_ready(c, p, pfd, npfd, c->sock, - "sockw", POLLOUT, SSH_CHAN_IO_SOCK_W); - dump_channel_poll(__func__, "sock", c, p, pfd); - } + channel_mask_io_ready(c, readset, writeset); } +} channel_handler(ssh, CHAN_POST, NULL); } @@ -2923,7 +2827,7 @@ if (c->datagram) { /* Check datagram will fit; drop if not */ if ((r = sshbuf_get_string_direct(c->input, &pkt, &plen)) != 0) - fatal_fr(r, "channel %i: get datagram", c->self); + fatal_fr(r, "channel %d: get datagram", c->self); /* * XXX this does tail-drop on the datagram queue which is * usually suboptimal compared to head-drop. Better to have @@ -2938,7 +2842,7 @@ (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 || (r = sshpkt_put_string(ssh, pkt, plen)) != 0 || (r = sshpkt_send(ssh)) != 0) - fatal_fr(r, "channel %i: send datagram", c->self); + fatal_fr(r, "channel %d: send datagram", c->self); c->remote_window -= plen; return; } @@ -2954,9 +2858,9 @@ (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 || (r = sshpkt_put_string(ssh, sshbuf_ptr(c->input), len)) != 0 || (r = sshpkt_send(ssh)) != 0) - fatal_fr(r, "channel %i: send data", c->self); + fatal_fr(r, "channel %d: send data", c->self); if ((r = sshbuf_consume(c->input, len)) != 0) - fatal_fr(r, "channel %i: consume", c->self); + fatal_fr(r, "channel %d: consume", c->self); c->remote_window -= len; } @@ -2987,9 +2891,9 @@ (r = sshpkt_put_u32(ssh, SSH2_EXTENDED_DATA_STDERR)) != 0 || (r = sshpkt_put_string(ssh, sshbuf_ptr(c->extended), len)) != 0 || (r = sshpkt_send(ssh)) != 0) - fatal_fr(r, "channel %i: data", c->self); + fatal_fr(r, "channel %d: data", c->self); if ((r = sshbuf_consume(c->extended, len)) != 0) - fatal_fr(r, "channel %i: consume", c->self); + fatal_fr(r, "channel %d: consume", c->self); c->remote_window -= len; debug2("channel %d: sent ext data %zu", c->self, len); } @@ -3098,7 +3002,7 @@ cp += 2; have -= 2; if (ssh_packet_log_type(type)) - debug3_f("channel %u: down->up: type %u", + debug3_f("channel %d: down->up: type %u", downstream->self, type); switch (type) { @@ -3234,6 +3138,7 @@ size_t len; int r; + UNUSED(seq); /* * When receiving packets from the peer we need to check whether we * need to forward the packets to the mux client. In this case we @@ -3257,7 +3162,7 @@ case SSH2_MSG_CHANNEL_REQUEST: break; default: - debug2_f("channel %u: unsupported type %u", c->self, type); + debug2_f("channel %d: unsupported type %u", c->self, type); return 0; } if ((b = sshbuf_new()) == NULL) { @@ -3281,7 +3186,7 @@ } /* sshbuf_dump(b, stderr); */ if (ssh_packet_log_type(type)) - debug3_f("channel %u: up->down: type %u", c->self, type); + debug3_f("channel %d: up->down: type %u", c->self, type); out: /* update state */ switch (type) { @@ -3307,42 +3212,48 @@ /* Parse a channel ID from the current packet */ static int -channel_parse_id(struct ssh *ssh, const char *where, const char *what) +channel_parse_id(const char *file, const char *func, int line, + struct ssh *ssh, const char *what) { u_int32_t id; int r; if ((r = sshpkt_get_u32(ssh, &id)) != 0) { - error_r(r, "%s: parse id", where); + sshlog_fr(file, func, line, r, SYSLOG_LEVEL_ERROR, "parse"); ssh_packet_disconnect(ssh, "Invalid %s message", what); } if (id > INT_MAX) { - error_r(r, "%s: bad channel id %u", where, id); + sshlog_f(file, func, line, SYSLOG_LEVEL_ERROR, "bad channel id %u", id); ssh_packet_disconnect(ssh, "Invalid %s channel id", what); } return (int)id; } +#define CHANNEL_PARSE_ID(ssh, what) \ + channel_parse_id(__FILE__, __func__, __LINE__, ssh, what) + /* Lookup a channel from an ID in the current packet */ static Channel * -channel_from_packet_id(struct ssh *ssh, const char *where, const char *what) +channel_from_packet_id(const char *file, const char *func, int line, + struct ssh *ssh, const char *what) { - int id = channel_parse_id(ssh, where, what); + int id = channel_parse_id(file, func, line, ssh, what); Channel *c; - if ((c = channel_lookup(ssh, id)) == NULL) { + if ((c = channel_lookup(ssh, id)) == NULL) ssh_packet_disconnect(ssh, "%s packet referred to nonexistent channel %d", what, id); - } return c; } +#define CHANNEL_FROM_PACKET_ID(ssh, what) \ + channel_from_packet_id(__FILE__, __func__, __LINE__, ssh, what) int channel_input_data(int type, u_int32_t seq, struct ssh *ssh) { const u_char *data; size_t data_len, win_len; - Channel *c = channel_from_packet_id(ssh, __func__, "data"); + Channel *c = CHANNEL_FROM_PACKET_ID(ssh, "data"); int r; if (channel_proxy_upstream(c, type, seq, ssh)) @@ -3358,7 +3269,7 @@ /* Get the data. */ if ((r = sshpkt_get_string_direct(ssh, &data, &data_len)) != 0 || (r = sshpkt_get_end(ssh)) != 0) - fatal_fr(r, "channel %i: get data", c->self); + fatal_fr(r, "channel %d: get data", c->self); win_len = data_len; if (c->datagram) @@ -3389,9 +3300,9 @@ if (c->datagram) { if ((r = sshbuf_put_string(c->output, data, data_len)) != 0) - fatal_fr(r, "channel %i: append datagram", c->self); + fatal_fr(r, "channel %d: append datagram", c->self); } else if ((r = sshbuf_put(c->output, data, data_len)) != 0) - fatal_fr(r, "channel %i: append data", c->self); + fatal_fr(r, "channel %d: append data", c->self); return 0; } @@ -3402,7 +3313,7 @@ const u_char *data; size_t data_len; u_int32_t tcode; - Channel *c = channel_from_packet_id(ssh, __func__, "extended data"); + Channel *c = CHANNEL_FROM_PACKET_ID(ssh, "extended data"); int r; if (channel_proxy_upstream(c, type, seq, ssh)) @@ -3412,7 +3323,7 @@ return 0; } if (c->flags & CHAN_EOF_RCVD) { - if (ssh->compat & SSH_BUG_EXTEOF) + if (ssh_compat_fellows(ssh, SSH_BUG_EXTEOF)) debug("channel %d: accepting ext data after eof", c->self); else @@ -3452,7 +3363,7 @@ int channel_input_ieof(int type, u_int32_t seq, struct ssh *ssh) { - Channel *c = channel_from_packet_id(ssh, __func__, "ieof"); + Channel *c = CHANNEL_FROM_PACKET_ID(ssh, "ieof"); int r; if ((r = sshpkt_get_end(ssh)) != 0) { @@ -3477,7 +3388,7 @@ int channel_input_oclose(int type, u_int32_t seq, struct ssh *ssh) { - Channel *c = channel_from_packet_id(ssh, __func__, "oclose"); + Channel *c = CHANNEL_FROM_PACKET_ID(ssh, "oclose"); int r; if (channel_proxy_upstream(c, type, seq, ssh)) @@ -3493,7 +3404,7 @@ int channel_input_open_confirmation(int type, u_int32_t seq, struct ssh *ssh) { - Channel *c = channel_from_packet_id(ssh, __func__, "open confirmation"); + Channel *c = CHANNEL_FROM_PACKET_ID(ssh, "open confirmation"); u_int32_t remote_window, remote_maxpacket; int r; @@ -3548,7 +3459,7 @@ int channel_input_open_failure(int type, u_int32_t seq, struct ssh *ssh) { - Channel *c = channel_from_packet_id(ssh, __func__, "open failure"); + Channel *c = CHANNEL_FROM_PACKET_ID(ssh, "open failure"); u_int32_t reason; char *msg = NULL; int r; @@ -3585,7 +3496,7 @@ int channel_input_window_adjust(int type, u_int32_t seq, struct ssh *ssh) { - int id = channel_parse_id(ssh, __func__, "window adjust"); + int id = CHANNEL_PARSE_ID(ssh, "window adjust"); Channel *c; u_int32_t adjust; u_int new_rwin; @@ -3603,10 +3514,10 @@ error_fr(r, "parse adjust"); ssh_packet_disconnect(ssh, "Invalid window adjust message"); } - debug2("channel %d: rcvd adjust %u", c->self, adjust); + debug2("channel %d: rcvd adjust %u", c->self, (unsigned)adjust); if ((new_rwin = c->remote_window + adjust) < c->remote_window) { fatal("channel %d: adjust %u overflows remote window %u", - c->self, adjust, c->remote_window); + c->self, (unsigned)adjust, c->remote_window); } c->remote_window = new_rwin; return 0; @@ -3615,7 +3526,7 @@ int channel_input_status_confirm(int type, u_int32_t seq, struct ssh *ssh) { - int id = channel_parse_id(ssh, __func__, "status confirm"); + int id = CHANNEL_PARSE_ID(ssh, "status confirm"); Channel *c; struct channel_confirm *cc; @@ -3625,7 +3536,7 @@ debug2_f("type %d id %d", type, id); if ((c = channel_lookup(ssh, id)) == NULL) { - logit_f("%d: unknown", id); + debug_f("%d: unknown", id); return 0; } if (channel_proxy_upstream(c, type, seq, ssh)) @@ -3676,7 +3587,7 @@ if (fwd_opts->gateway_ports) wildcard = 1; } else if (fwd_opts->gateway_ports || is_client) { - if (((ssh->compat & SSH_OLD_FORWARD_ADDR) && + if ((ssh_compat_fellows(ssh, SSH_OLD_FORWARD_ADDR) && strcmp(listen_addr, "0.0.0.0") == 0 && is_client == 0) || *listen_addr == '\0' || strcmp(listen_addr, "*") == 0 || (!is_client && fwd_opts->gateway_ports == 1)) { @@ -3864,7 +3775,7 @@ c->host_port = fwd->connect_port; c->listening_addr = addr == NULL ? NULL : xstrdup(addr); if (fwd->listen_port == 0 && allocated_listen_port != NULL && - !(ssh->compat & SSH_BUG_DYNAMIC_RPORT)) + !ssh_compat_fellows(ssh, SSH_BUG_DYNAMIC_RPORT)) c->listening_port = *allocated_listen_port; else c->listening_port = fwd->listen_port; @@ -4492,7 +4403,7 @@ idx, pset->num_permitted_user); return; } - debug("%s allowed port %d for forwarding to host %s port %d", + verbose("%s allowed port %d for forwarding to host %s port %d", newport > 0 ? "Updating" : "Removing", newport, pset->permitted_user[idx].host_to_connect, @@ -4501,7 +4412,7 @@ fwd_perm_clear(&pset->permitted_user[idx]); else { pset->permitted_user[idx].listen_port = - (ssh->compat & SSH_BUG_DYNAMIC_RPORT) ? 0 : newport; + ssh_compat_fellows(ssh, SSH_BUG_DYNAMIC_RPORT) ? 0 : newport; } } @@ -4605,6 +4516,8 @@ int sock = -1; char strport[NI_MAXSERV]; + UNUSED(ctype); + UNUSED(rname); if (port == PORT_STREAMLOCAL) { struct sockaddr_un *sunaddr; struct addrinfo *ai; @@ -4860,7 +4773,7 @@ (r = sshpkt_put_u32(ssh, (u_int)ws.ws_xpixel)) != 0 || (r = sshpkt_put_u32(ssh, (u_int)ws.ws_ypixel)) != 0 || (r = sshpkt_send(ssh)) != 0) - fatal_fr(r, "channel %u; send window-change", i); + fatal_fr(r, "channel %u: send window-change", i); } } @@ -4885,7 +4798,7 @@ (r = sshpkt_put_u32(ssh, c->self)) != 0 || (r = sshpkt_put_u32(ssh, c->local_window)) != 0 || (r = sshpkt_put_u32(ssh, c->local_maxpacket)) != 0) - fatal_fr(r, "channel %i; confirm", c->self); + fatal_fr(r, "channel %d: confirm", c->self); return c; } @@ -4975,13 +4888,13 @@ if ((errno != EINVAL) && (errno != EAFNOSUPPORT) #ifdef EPFNOSUPPORT && (errno != EPFNOSUPPORT) -#endif +#endif ) { error("socket: %.100s", strerror(errno)); freeaddrinfo(aitop); return -1; } else { - debug("x11_create_display_inet: Socket family %d not supported", + debug_f("socket family %d not supported", ai->ai_family); continue; } @@ -5053,7 +4966,7 @@ memset(&addr, 0, sizeof(addr)); addr.sun_family = AF_UNIX; strlcpy(addr.sun_path, pathname, sizeof addr.sun_path); - if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) == 0) + if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) != -1) return sock; close(sock); error("connect %.100s: %.100s", addr.sun_path, strerror(errno)); @@ -5075,18 +4988,18 @@ struct stat sbuf; if (strlcpy(path, display, pathlen) >= pathlen) { - error("%s: display path too long", __func__); + error_f("display path too long"); return 0; } if (display[0] != '/') return 0; - if (stat(path, &sbuf) == 0) { + if (stat(path, &sbuf) != -1) { return 1; } else { char *dot = strrchr(path, '.'); if (dot != NULL) { *dot = '\0'; - if (stat(path, &sbuf) == 0) { + if (stat(path, &sbuf) != -1) { return 1; } } @@ -5122,7 +5035,7 @@ char path[PATH_MAX]; if (is_path_to_xsocket(display, path, sizeof(path))) { - debug("x11_connect_display: $DISPLAY is launchd"); + debug_f("$DISPLAY is launchd"); /* Create a socket. */ sock = connect_local_xsocket_path(path); @@ -5149,7 +5062,7 @@ } /* Create a socket. */ sock = connect_local_xsocket(display_number); - if (sock < 0) + if (sock == -1) return -1; /* OK, we now have a connection to the display. */ @@ -5252,10 +5165,9 @@ /* Extract real authentication data. */ sc->x11_saved_data = xmalloc(data_len); for (i = 0; i < data_len; i++) { - if (sscanf(data + 2 * i, "%2x", &value) != 1) { + if (sscanf(data + 2 * i, "%2x", &value) != 1) fatal("x11_request_forwarding: bad " "authentication data: %.100s", data); - } sc->x11_saved_data[i] = value; } sc->x11_saved_data_len = data_len; diff -ruN openssh-9.4p1/channels.h openssh-9.4p1+x509-14.2.1/channels.h --- openssh-9.4p1/channels.h 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/channels.h 2023-08-20 10:07:00.000000000 +0300 @@ -1,5 +1,4 @@ /* $OpenBSD: channels.h,v 1.151 2023/07/04 03:59:21 dlg Exp $ */ - /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -13,6 +12,7 @@ */ /* * Copyright (c) 1999, 2000, 2001, 2002 Markus Friedl. All rights reserved. + * Copyright (c) 2021-2023 Roumen Petrov. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -38,6 +38,12 @@ #ifndef CHANNEL_H #define CHANNEL_H +/* Definitions for channel descriptors. */ +#define SSH_CHANNEL_FD_INPUT 1 +#define SSH_CHANNEL_FD_OUTPUT 2 +#define SSH_CHANNEL_FD_ERROR 3 +#define SSH_CHANNEL_FD_SOCKET 4 + /* Definitions for channel types. */ #define SSH_CHANNEL_X11_LISTENER 1 /* Listening for inet X11 conn. */ #define SSH_CHANNEL_PORT_LISTENER 2 /* Listening on a port. */ @@ -138,7 +144,6 @@ int sock; /* sock fd */ u_int io_want; /* bitmask of SSH_CHAN_IO_* */ u_int io_ready; /* bitmask of SSH_CHAN_IO_* */ - int pfds[4]; /* pollfd entries for rfd/wfd/efd/sock */ int ctl_chan; /* control channel (multiplexed connections) */ int isatty; /* rfd is a tty */ #ifdef _AIX @@ -147,13 +152,12 @@ int client_tty; /* (client) TTY has been requested */ int force_drain; /* force close on iEOF */ time_t notbefore; /* Pause IO until deadline (time_t) */ - int delayed; /* post-IO handlers for newly created + int delayed; /* post-select handlers for newly created * channels are delayed until the first call - * to a matching pre-IO handler. - * this way post-IO handlers are not + * to a matching pre-select handler. + * this way post-select handlers are not * accidentally called if a FD gets reused */ int restore_block; /* fd mask to restore blocking status */ - int restore_flags[3];/* flags to restore */ struct sshbuf *input; /* data read from socket, to be sent over * encrypted connection */ struct sshbuf *output; /* data received over encrypted connection for @@ -205,12 +209,10 @@ int mux_pause; int mux_downstream_id; - /* Inactivity timeouts */ - /* Last traffic seen for OPEN channels */ time_t lastused; /* Inactivity timeout deadline in seconds (0 = no timeout) */ - int inactive_deadline; + long inactive_deadline; }; #define CHAN_EXTENDED_IGNORE 0 @@ -253,12 +255,6 @@ #define SSH_CHAN_IO_SOCK_W 0x20 #define SSH_CHAN_IO_SOCK (SSH_CHAN_IO_SOCK_R|SSH_CHAN_IO_SOCK_W) -/* Read buffer size */ -#define CHAN_RBUF (16*1024) - -/* Maximum size for direct reads to buffers */ -#define CHANNEL_MAX_READ CHAN_SES_PACKET_DEFAULT - /* Maximum channel input buffer size */ #define CHAN_INPUT_MAX (16*1024*1024) @@ -290,7 +286,8 @@ void channel_free(struct ssh *, Channel *); void channel_free_all(struct ssh *); void channel_stop_listening(struct ssh *); -void channel_force_close(struct ssh *, Channel *, int); +void channel_force_close(struct ssh *, Channel *); +void channel_abandon(struct ssh *, Channel *); void channel_set_xtype(struct ssh *, int, const char *); void channel_send_open(struct ssh *, int); @@ -304,11 +301,10 @@ void channel_register_status_confirm(struct ssh *, int, channel_confirm_cb *, channel_confirm_abandon_cb *, void *); void channel_cancel_cleanup(struct ssh *, int); -int channel_close_fd(struct ssh *, Channel *, int *); void channel_send_window_changes(struct ssh *); /* channel inactivity timeouts */ -void channel_add_timeout(struct ssh *, const char *, int); +void channel_add_timeout(struct ssh *, const char *, long); void channel_clear_timeouts(struct ssh *); /* mux proxy support */ @@ -329,12 +325,11 @@ int channel_input_status_confirm(int, u_int32_t, struct ssh *); /* file descriptor handling (read/write) */ -struct pollfd; struct timespec; -void channel_prepare_poll(struct ssh *, struct pollfd **, - u_int *, u_int *, u_int, struct timespec *); -void channel_after_poll(struct ssh *, struct pollfd *, u_int); +void channel_prepare_select(struct ssh *, fd_set **, fd_set **, int *, + u_int*, struct timespec*); +void channel_after_select(struct ssh *, fd_set *, fd_set *); void channel_output_poll(struct ssh *); int channel_not_very_much_buffered_data(struct ssh *); diff -ruN openssh-9.4p1/cipher-aes.c openssh-9.4p1+x509-14.2.1/cipher-aes.c --- openssh-9.4p1/cipher-aes.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/cipher-aes.c 2023-08-20 10:07:01.000000000 +0300 @@ -24,9 +24,6 @@ #include "includes.h" -/* compatibility with old or broken OpenSSL versions */ -#include "openbsd-compat/openssl-compat.h" - #ifdef USE_BUILTIN_RIJNDAEL #include @@ -35,6 +32,7 @@ #include #include +#include "cipher.h" #include "rijndael.h" #include "xmalloc.h" #include "log.h" @@ -69,7 +67,7 @@ static int ssh_rijndael_cbc(EVP_CIPHER_CTX *ctx, u_char *dest, const u_char *src, - size_t len) + LIBCRYPTO_EVP_INL_TYPE len) { struct ssh_rijndael_ctx *c; u_char buf[RIJNDAEL_BLOCKSIZE]; @@ -79,9 +77,9 @@ if (len == 0) return (1); if (len % RIJNDAEL_BLOCKSIZE) - fatal("ssh_rijndael_cbc: bad len %d", len); + fatal_f("bad len %d", len); if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) { - error("ssh_rijndael_cbc: no context"); + error_f("no context"); return (0); } if (ctx->encrypt) { @@ -132,7 +130,7 @@ struct ssh_rijndael_ctx *c; if ((c = EVP_CIPHER_CTX_get_app_data(evp)) == NULL) - fatal("ssh_rijndael_iv: no context"); + fatal_f("no context"); if (doset) memcpy(c->r_iv, iv, len); else diff -ruN openssh-9.4p1/cipher.c openssh-9.4p1+x509-14.2.1/cipher.c --- openssh-9.4p1/cipher.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/cipher.c 2023-08-20 10:07:01.000000000 +0300 @@ -13,6 +13,7 @@ * * Copyright (c) 1999 Niels Provos. All rights reserved. * Copyright (c) 1999, 2000 Markus Friedl. All rights reserved. + * Copyright (c) 2011-2022 Roumen Petrov. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -45,16 +46,35 @@ #include "cipher.h" #include "misc.h" +#include "xmalloc.h" +#include "log.h" #include "sshbuf.h" #include "ssherr.h" #include "digest.h" -#include "openbsd-compat/openssl-compat.h" +#ifdef WITH_OPENSSL -#ifndef WITH_OPENSSL -#define EVP_CIPHER_CTX void +#ifndef OPENSSL_HAVE_EVPCTR +const EVP_CIPHER *evp_aes_128_ctr(void); +void ssh_aes_ctr_iv(EVP_CIPHER_CTX *, int, u_char *, size_t); +# define EVP_aes_128_ctr evp_aes_128_ctr +# define EVP_aes_192_ctr evp_aes_128_ctr +# define EVP_aes_256_ctr evp_aes_128_ctr +#endif + +/* code that uses these is unreachable without GCM */ +#if !defined(OPENSSL_HAVE_EVPGCM) && !defined(EVP_CTRL_GCM_SET_IV_FIXED) +# define EVP_CTRL_GCM_SET_IV_FIXED -1 +# define EVP_CTRL_GCM_IV_GEN -1 +# define EVP_CTRL_GCM_SET_TAG -1 +# define EVP_CTRL_GCM_GET_TAG -1 +#endif + +#else /*ndef WITH_OPENSSL*/ +# define EVP_CIPHER_CTX void #endif + struct sshcipher_ctx { int plaintext; int encrypt; @@ -65,7 +85,7 @@ }; struct sshcipher { - char *name; + const char *name; u_int block_size; u_int key_len; u_int iv_len; /* defaults to block_size */ @@ -85,19 +105,21 @@ static const struct sshcipher ciphers[] = { #ifdef WITH_OPENSSL -#ifndef OPENSSL_NO_DES +# ifndef OPENSSL_NO_DES { "3des-cbc", 8, 24, 0, 0, CFLAG_CBC, EVP_des_ede3_cbc }, -#endif +# endif { "aes128-cbc", 16, 16, 0, 0, CFLAG_CBC, EVP_aes_128_cbc }, { "aes192-cbc", 16, 24, 0, 0, CFLAG_CBC, EVP_aes_192_cbc }, { "aes256-cbc", 16, 32, 0, 0, CFLAG_CBC, EVP_aes_256_cbc }, { "aes128-ctr", 16, 16, 0, 0, 0, EVP_aes_128_ctr }, { "aes192-ctr", 16, 24, 0, 0, 0, EVP_aes_192_ctr }, { "aes256-ctr", 16, 32, 0, 0, 0, EVP_aes_256_ctr }, +# ifdef OPENSSL_HAVE_EVPGCM { "aes128-gcm@openssh.com", 16, 16, 12, 16, 0, EVP_aes_128_gcm }, { "aes256-gcm@openssh.com", 16, 32, 12, 16, 0, EVP_aes_256_gcm }, +# endif /* OPENSSL_HAVE_EVPGCM */ #else { "aes128-ctr", 16, 16, 0, 0, CFLAG_AESCTR, NULL }, { "aes192-ctr", 16, 24, 0, 0, CFLAG_AESCTR, NULL }, @@ -112,6 +134,23 @@ /*--*/ +static inline int/*bool*/ +cipher_allowed(const struct sshcipher *c) { +#ifdef OPENSSL_FIPS + if (FIPS_mode()) { + const EVP_CIPHER *evp = NULL; + if (c->evptype == NULL) return(0); + evp = c->evptype(); + if (evp == NULL) return(0); + if ((EVP_CIPHER_flags(evp) & EVP_CIPH_FLAG_FIPS) == 0) + return(0); + } +#else + (void) c; +#endif + return(1); +} + /* Returns a comma-separated list of supported ciphers. */ char * cipher_alg_list(char sep, int auth_only) @@ -125,6 +164,8 @@ continue; if (auth_only && c->auth_len == 0) continue; + if (!cipher_allowed(c)) + continue; if (ret != NULL) ret[rlen++] = sep; nlen = strlen(c->name); @@ -146,6 +187,7 @@ return compression ? "zlib@openssh.com,zlib,none" : "none,zlib@openssh.com,zlib"; #else + UNUSED(compression); return "none"; #endif } @@ -199,13 +241,32 @@ return cc->plaintext; } +/* NOTE: "none" is not allowed in FIPS mode, so temporary + * work-around for "none"-cipher used in ssh_packet_set_connection() + */ +const struct sshcipher * cipher_none(void); + +const struct sshcipher * +cipher_none(void) +{ + const struct sshcipher *c; + for (c = ciphers; c->name != NULL; c++) + if (strcmp(c->name, "none") == 0) + return c; + return NULL; +} + const struct sshcipher * cipher_by_name(const char *name) { const struct sshcipher *c; for (c = ciphers; c->name != NULL; c++) if (strcmp(c->name, name) == 0) + { + if (!cipher_allowed(c)) + continue; return c; + } return NULL; } @@ -270,7 +331,7 @@ cc->cipher = cipher; if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) { cc->cp_ctx = chachapoly_new(key, keylen); - ret = cc->cp_ctx != NULL ? 0 : SSH_ERR_INVALID_ARGUMENT; + ret = cc->cp_ctx != NULL ? 0 : SSH_ERR_ALLOC_FAIL; goto out; } if ((cc->cipher->flags & CFLAG_NONE) != 0) { @@ -292,7 +353,11 @@ ret = SSH_ERR_ALLOC_FAIL; goto out; } +#ifndef BROKEN_EVP_CIPHERINIT if (EVP_CipherInit(cc->evp, type, NULL, (u_char *)iv, +#else + if (EVP_CipherInit(cc->evp, type, key, (u_char *)iv, +#endif /*ndef BROKEN_EVP_CIPHERINIT*/ (do_encrypt == CIPHER_ENCRYPT)) == 0) { ret = SSH_ERR_LIBCRYPTO_ERROR; goto out; @@ -310,10 +375,13 @@ goto out; } } +#ifndef BROKEN_EVP_CIPHERINIT if (EVP_CipherInit(cc->evp, NULL, (u_char *)key, NULL, -1) == 0) { ret = SSH_ERR_LIBCRYPTO_ERROR; goto out; } +#endif /*ndef BROKEN_EVP_CIPHERINIT*/ + ret = 0; #endif /* WITH_OPENSSL */ out: @@ -324,6 +392,7 @@ if (cc != NULL) { #ifdef WITH_OPENSSL EVP_CIPHER_CTX_free(cc->evp); + cc->evp = NULL; #endif /* WITH_OPENSSL */ freezero(cc, sizeof(*cc)); } @@ -434,24 +503,27 @@ freezero(cc, sizeof(*cc)); } -/* - * Exports an IV from the sshcipher_ctx required to export the key - * state back from the unprivileged child to the privileged parent - * process. - */ -int -cipher_get_keyiv_len(const struct sshcipher_ctx *cc) -{ - const struct sshcipher *c = cc->cipher; - if ((c->flags & CFLAG_CHACHAPOLY) != 0) - return 0; - else if ((c->flags & CFLAG_AESCTR) != 0) - return sizeof(cc->ac_ctx.ctr); -#ifdef WITH_OPENSSL - return EVP_CIPHER_CTX_iv_length(cc->evp); +static inline int +ssh_copy_iv(EVP_CIPHER_CTX *ctx, void *buf, size_t len) { +#ifdef HAVE_OPENSSL_VERSION_MAJOR /* OpenSSL >= 3.0 */ +/* EVP_CIPHER_CTX_get_updated_iv() is very specific OpenSSL 3+ function. + * So there is no need to test for availability at configure time. + */ + return EVP_CIPHER_CTX_get_updated_iv(ctx, buf, len); +#elif defined(HAVE_EVP_CIPHER_CTX_GET_IV) && defined(LIBRESSL_VERSION_NUMBER) +/* At some point of time was defined by OpenSSL but wrongly designed + * to return initial IV. Who cares for initial IV?!?! + */ + return EVP_CIPHER_CTX_get_iv(ctx, buf, len); #else - return 0; +/* Defined in OpenSSL 1.1, deprecated in 3.0 ?!?! */ +#ifdef HAVE_EVP_CIPHER_CTX_IV + memcpy(buf, EVP_CIPHER_CTX_iv(ctx), len); +#else + memcpy(buf, ctx->iv, len); +#endif + return 1; #endif } @@ -485,42 +557,18 @@ return SSH_ERR_LIBCRYPTO_ERROR; if ((size_t)evplen != len) return SSH_ERR_INVALID_ARGUMENT; - if (cipher_authlen(c)) { - if (!EVP_CIPHER_CTX_ctrl(cc->evp, EVP_CTRL_GCM_IV_GEN, - len, iv)) - return SSH_ERR_LIBCRYPTO_ERROR; - } else if (!EVP_CIPHER_CTX_get_iv(cc->evp, iv, len)) - return SSH_ERR_LIBCRYPTO_ERROR; -#endif - return 0; -} - -int -cipher_set_keyiv(struct sshcipher_ctx *cc, const u_char *iv, size_t len) -{ -#ifdef WITH_OPENSSL - const struct sshcipher *c = cc->cipher; - int evplen = 0; +#ifndef OPENSSL_HAVE_EVPCTR + if (c->evptype == evp_aes_128_ctr) + ssh_aes_ctr_iv(cc->evp, 0, iv, len); + else #endif - - if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) - return 0; - if ((cc->cipher->flags & CFLAG_NONE) != 0) - return 0; - -#ifdef WITH_OPENSSL - evplen = EVP_CIPHER_CTX_iv_length(cc->evp); - if (evplen <= 0) - return SSH_ERR_LIBCRYPTO_ERROR; - if ((size_t)evplen != len) - return SSH_ERR_INVALID_ARGUMENT; if (cipher_authlen(c)) { - /* XXX iv arg is const, but EVP_CIPHER_CTX_ctrl isn't */ - if (!EVP_CIPHER_CTX_ctrl(cc->evp, - EVP_CTRL_GCM_SET_IV_FIXED, -1, (void *)iv)) + if (!EVP_CIPHER_CTX_ctrl(cc->evp, EVP_CTRL_GCM_IV_GEN, + evplen, iv)) return SSH_ERR_LIBCRYPTO_ERROR; - } else if (!EVP_CIPHER_CTX_set_iv(cc->evp, iv, evplen)) - return SSH_ERR_LIBCRYPTO_ERROR; + } else + if (ssh_copy_iv(cc->evp, iv, len) != 1) + return SSH_ERR_INVALID_ARGUMENT; #endif return 0; } diff -ruN openssh-9.4p1/cipher-chachapoly.c openssh-9.4p1+x509-14.2.1/cipher-chachapoly.c --- openssh-9.4p1/cipher-chachapoly.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/cipher-chachapoly.c 2023-08-20 10:07:01.000000000 +0300 @@ -1,4 +1,3 @@ -/* $OpenBSD: cipher-chachapoly.c,v 1.10 2023/07/17 05:26:38 djm Exp $ */ /* * Copyright (c) 2013 Damien Miller * @@ -15,12 +14,11 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +/* $OpenBSD: cipher-chachapoly.c,v 1.9 2020/04/03 04:27:03 djm Exp $ */ + #include "includes.h" -#ifdef WITH_OPENSSL -#include "openbsd-compat/openssl-compat.h" -#endif -#if !defined(HAVE_EVP_CHACHA20) || defined(HAVE_BROKEN_CHACHA20) +#ifdef USE_BUILTIN_CHACHAPOLY #include #include /* needed for log.h */ @@ -74,6 +72,7 @@ u_char expected_tag[POLY1305_TAGLEN], poly_key[POLY1305_KEYLEN]; int r = SSH_ERR_INTERNAL_ERROR; + UNUSED(authlen); /* * Run ChaCha20 once to generate the Poly1305 key. The IV is the * packet sequence number. @@ -135,4 +134,8 @@ return 0; } -#endif /* !defined(HAVE_EVP_CHACHA20) || defined(HAVE_BROKEN_CHACHA20) */ +#else /*def USE_BUILTIN_CHACHAPOLY*/ + +typedef int cipher_chachapoly_empty_translation_unit; + +#endif /*def USE_BUILTIN_CHACHAPOLY*/ diff -ruN openssh-9.4p1/cipher-chachapoly.h openssh-9.4p1+x509-14.2.1/cipher-chachapoly.h --- openssh-9.4p1/cipher-chachapoly.h 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/cipher-chachapoly.h 2023-08-20 10:07:00.000000000 +0300 @@ -26,8 +26,7 @@ struct chachapoly_ctx; -struct chachapoly_ctx *chachapoly_new(const u_char *key, u_int keylen) - __attribute__((__bounded__(__buffer__, 1, 2))); +struct chachapoly_ctx *chachapoly_new(const u_char *key, u_int keylen); void chachapoly_free(struct chachapoly_ctx *cpctx); int chachapoly_crypt(struct chachapoly_ctx *cpctx, u_int seqnr, diff -ruN openssh-9.4p1/cipher-chachapoly-libcrypto.c openssh-9.4p1+x509-14.2.1/cipher-chachapoly-libcrypto.c --- openssh-9.4p1/cipher-chachapoly-libcrypto.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/cipher-chachapoly-libcrypto.c 2023-08-20 10:07:01.000000000 +0300 @@ -1,4 +1,3 @@ -/* $OpenBSD: cipher-chachapoly-libcrypto.c,v 1.2 2023/07/17 05:26:38 djm Exp $ */ /* * Copyright (c) 2013 Damien Miller * @@ -15,12 +14,11 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +/* $OpenBSD: cipher-chachapoly-libcrypto.c,v 1.1 2020/04/03 04:32:21 djm Exp $ */ + #include "includes.h" -#ifdef WITH_OPENSSL -#include "openbsd-compat/openssl-compat.h" -#endif -#if defined(HAVE_EVP_CHACHA20) && !defined(HAVE_BROKEN_CHACHA20) +#ifndef USE_BUILTIN_CHACHAPOLY #include #include /* needed for log.h */ @@ -89,6 +87,7 @@ int r = SSH_ERR_INTERNAL_ERROR; u_char expected_tag[POLY1305_TAGLEN], poly_key[POLY1305_KEYLEN]; + UNUSED(authlen); /* * Run ChaCha20 once to generate the Poly1305 key. The IV is the * packet sequence number. @@ -162,4 +161,9 @@ *plenp = PEEK_U32(buf); return 0; } -#endif /* defined(HAVE_EVP_CHACHA20) && !defined(HAVE_BROKEN_CHACHA20) */ + +#else /*ndef USE_BUILTIN_CHACHAPOLY*/ + +typedef int cipher_chachapoly_libcrypto_empty_translation_unit; + +#endif /*ndef USE_BUILTIN_CHACHAPOLY*/ diff -ruN openssh-9.4p1/cipher-ctr.c openssh-9.4p1+x509-14.2.1/cipher-ctr.c --- openssh-9.4p1/cipher-ctr.c 1970-01-01 02:00:00.000000000 +0200 +++ openssh-9.4p1+x509-14.2.1/cipher-ctr.c 2023-08-20 10:07:01.000000000 +0300 @@ -0,0 +1,150 @@ +/* $OpenBSD: cipher-ctr.c,v 1.11 2010/10/01 23:05:32 djm Exp $ */ +/* + * Copyright (c) 2003 Markus Friedl + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#include "includes.h" + +#if defined(WITH_OPENSSL) && !defined(OPENSSL_HAVE_EVPCTR) +#include + +#include +#include + +#include +#ifndef USE_BUILTIN_RIJNDAEL +#include +#endif + +#include "cipher.h" +#include "xmalloc.h" +#include "log.h" + +const EVP_CIPHER * evp_aes_128_ctr(void); +void ssh_aes_ctr_iv(EVP_CIPHER_CTX *evp, int doset, u_char * iv, size_t len); + +struct ssh_aes_ctr_ctx +{ + AES_KEY aes_ctx; + u_char aes_counter[AES_BLOCK_SIZE]; +}; + +/* + * increment counter 'ctr', + * the counter is of size 'len' bytes and stored in network-byte-order. + * (LSB at ctr[len-1], MSB at ctr[0]) + */ +static void +ssh_ctr_inc(u_char *ctr, size_t len) +{ + int i; + + for (i = len - 1; i >= 0; i--) + if (++ctr[i]) /* continue on overflow */ + return; +} + +static int +ssh_aes_ctr(EVP_CIPHER_CTX *ctx, u_char *dest, const u_char *src, + LIBCRYPTO_EVP_INL_TYPE len) +{ + struct ssh_aes_ctr_ctx *c; + size_t n = 0; + u_char buf[AES_BLOCK_SIZE]; + + if (len == 0) + return (1); + if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) + return (0); + + while ((len--) > 0) { + if (n == 0) { + AES_encrypt(c->aes_counter, buf, &c->aes_ctx); + ssh_ctr_inc(c->aes_counter, AES_BLOCK_SIZE); + } + *(dest++) = *(src++) ^ buf[n]; + n = (n + 1) % AES_BLOCK_SIZE; + } + return (1); +} + +static int +ssh_aes_ctr_init(EVP_CIPHER_CTX *ctx, const u_char *key, const u_char *iv, + int enc) +{ + struct ssh_aes_ctr_ctx *c; + + UNUSED(enc); + if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) { + c = xmalloc(sizeof(*c)); + EVP_CIPHER_CTX_set_app_data(ctx, c); + } + if (key != NULL) + AES_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8, + &c->aes_ctx); + if (iv != NULL) + memcpy(c->aes_counter, iv, AES_BLOCK_SIZE); + return (1); +} + +static int +ssh_aes_ctr_cleanup(EVP_CIPHER_CTX *ctx) +{ + struct ssh_aes_ctr_ctx *c; + + if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) != NULL) { + memset(c, 0, sizeof(*c)); + free(c); + EVP_CIPHER_CTX_set_app_data(ctx, NULL); + } + return (1); +} + +void +ssh_aes_ctr_iv(EVP_CIPHER_CTX *evp, int doset, u_char * iv, size_t len) +{ + struct ssh_aes_ctr_ctx *c; + + if ((c = EVP_CIPHER_CTX_get_app_data(evp)) == NULL) + fatal_f("no context"); + if (doset) + memcpy(c->aes_counter, iv, len); + else + memcpy(iv, c->aes_counter, len); +} + +const EVP_CIPHER * +evp_aes_128_ctr(void) +{ + static EVP_CIPHER aes_ctr; + + memset(&aes_ctr, 0, sizeof(EVP_CIPHER)); + aes_ctr.nid = NID_undef; + aes_ctr.block_size = AES_BLOCK_SIZE; + aes_ctr.iv_len = AES_BLOCK_SIZE; + aes_ctr.key_len = 16; + aes_ctr.init = ssh_aes_ctr_init; + aes_ctr.cleanup = ssh_aes_ctr_cleanup; + aes_ctr.do_cipher = ssh_aes_ctr; +#ifndef SSH_OLD_EVP + aes_ctr.flags = EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH | +#ifdef EVP_CIPH_FLAG_FIPS + EVP_CIPH_FLAG_FIPS | +#endif + EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CUSTOM_IV; +#endif + return (&aes_ctr); +} + +#endif /* defined(WITH_OPENSSL) && !defined(OPENSSL_HAVE_EVPCTR) */ diff -ruN openssh-9.4p1/cipher.h openssh-9.4p1+x509-14.2.1/cipher.h --- openssh-9.4p1/cipher.h 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/cipher.h 2023-08-20 10:07:00.000000000 +0300 @@ -12,6 +12,7 @@ * called by a name other than "ssh" or "Secure Shell". * * Copyright (c) 2000 Markus Friedl. All rights reserved. + * Copyright (c) 2011-2022 Roumen Petrov. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -37,13 +38,58 @@ #ifndef CIPHER_H #define CIPHER_H +#include "includes.h" + #include #ifdef WITH_OPENSSL #include +#include "evp-compat.h" #endif + #include "cipher-chachapoly.h" #include "cipher-aesctr.h" + +#ifdef WITH_OPENSSL + +#if defined(OPENSSL_VERSION_NUMBER) && (OPENSSL_VERSION_NUMBER < 0x00908000L) +/* Workaround for bug in some openssl versions before 0.9.8f + * We will not use configure check as 0.9.7x define correct + * macro or some verdors patch their versions. + */ +#undef EVP_CIPHER_CTX_key_length +#define EVP_CIPHER_CTX_key_length ssh_EVP_CIPHER_CTX_key_length + +static inline int +ssh_EVP_CIPHER_CTX_key_length(const EVP_CIPHER_CTX *ctx) { return ctx->key_len; } +#endif + + +#ifndef HAVE_EVP_CIPHER_CTX_NEW /* OpenSSL < 0.9.8 */ +static inline EVP_CIPHER_CTX* +EVP_CIPHER_CTX_new(void) { + EVP_CIPHER_CTX *ctx; + + ctx = OPENSSL_malloc(sizeof(EVP_CIPHER_CTX)); + if (ctx != NULL) { + EVP_CIPHER_CTX_init(ctx); + } + return(ctx); +} + + +static inline void +EVP_CIPHER_CTX_free(EVP_CIPHER_CTX *ctx) { + if (ctx == NULL) return; + + EVP_CIPHER_CTX_cleanup(ctx); + OPENSSL_free(ctx); +} +#endif /* ndef HAVE_EVP_CIPHER_CTX_NEW OpenSSL < 0.9.8 */ + +#endif /*def WITH_OPENSSL*/ + + #define CIPHER_ENCRYPT 1 #define CIPHER_DECRYPT 0 @@ -73,6 +119,5 @@ int cipher_get_keyiv(struct sshcipher_ctx *, u_char *, size_t); int cipher_set_keyiv(struct sshcipher_ctx *, const u_char *, size_t); -int cipher_get_keyiv_len(const struct sshcipher_ctx *); #endif /* CIPHER_H */ diff -ruN openssh-9.4p1/clientloop.c openssh-9.4p1+x509-14.2.1/clientloop.c --- openssh-9.4p1/clientloop.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/clientloop.c 2023-08-20 10:07:01.000000000 +0300 @@ -13,6 +13,7 @@ * * * Copyright (c) 1999 Theo de Raadt. All rights reserved. + * Copyright (c) 2017-2023 Roumen Petrov. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -76,9 +77,6 @@ #ifdef HAVE_PATHS_H #include #endif -#ifdef HAVE_POLL_H -#include -#endif #include #include #include @@ -94,11 +92,10 @@ #include "ssh.h" #include "ssh2.h" #include "packet.h" -#include "sshbuf.h" +#include "ssh-x509.h" #include "compat.h" #include "channels.h" #include "dispatch.h" -#include "sshkey.h" #include "cipher.h" #include "kex.h" #include "myproposal.h" @@ -115,8 +112,24 @@ #include "ssherr.h" #include "hostfile.h" -/* Permitted RSA signature algorithms for UpdateHostkeys proofs */ -#define HOSTKEY_PROOF_RSA_ALGS "rsa-sha2-512,rsa-sha2-256" +/* read buffer size used in main loop */ +#if defined(HAVE_CYGWIN) && !defined(SSH_IOBUFSZ) +# define SSH_IOBUFSZ (64*1024) +#endif +#ifndef SSH_IOBUFSZ +# define SSH_IOBUFSZ (8*1024) +#endif +/* 256к 64к 32к 16к 8к 4к +memory: 1.001 0.997 0.995 1.000 1(*) 1.003 +buffer: 1.001 0.994 1.003 0.996 0.991 0.998 +Relative time for sftp 64M download where (*) is old basis. +Deviation: +memory: 0.244 0.236 0.205 0.121 0.129 0.082 +buffer: 0.165 0.080 0.100 0.074 0.124 0.160 +*/ +#if 0 +# define USE_DIRECT_READ +#endif /* import options */ extern Options options; @@ -158,10 +171,10 @@ static int connection_out; /* Connection to server (output). */ static int need_rekeying; /* Set to non-zero if rekeying is requested. */ static int session_closed; /* In SSH2: login session closed. */ -static time_t x11_refuse_time; /* If >0, refuse x11 opens after this time. */ -static time_t server_alive_time; /* Time to do server_alive_check */ -static int hostkeys_update_complete; -static int session_setup_complete; +static time_t x11_refuse_time = 0; /* If >0, refuse x11 opens after this time. */ +static time_t server_alive_time = 0; /* Time to do server_alive_check */ +static int hostkeys_update_complete = 0; +static int session_setup_complete = 0; static void client_init_dispatch(struct ssh *ssh); int session_ident = -1; @@ -191,7 +204,7 @@ static struct global_confirms global_confirms = TAILQ_HEAD_INITIALIZER(global_confirms); -void ssh_process_session2_setup(int, int, int, struct sshbuf *); + static void quit_message(const char *fmt, ...) __attribute__((__format__ (printf, 1, 2))); @@ -199,16 +212,17 @@ quit_message(const char *fmt, ...) { char *msg; - va_list args; int r; +{ va_list args; va_start(args, fmt); xvasprintf(&msg, fmt, args); va_end(args); - +} if ((r = sshbuf_putf(stderr_buffer, "%s\r\n", msg)) != 0) fatal_fr(r, "sshbuf_putf"); quit_pending = 1; + free(msg); } /* @@ -218,6 +232,7 @@ static void window_change_handler(int sig) { + UNUSED(sig); received_window_change_signal = 1; } @@ -398,7 +413,7 @@ generated ? "-f " : "" , generated ? xauthfile : "", display); - debug2("x11_get_proto: %s", cmd); + debug2_f("%s", cmd); f = popen(cmd, "r"); if (f && fgets(line, sizeof(line), f) && sscanf(line, "%*s %511s %511s", proto, data) == 2) @@ -512,40 +527,36 @@ * one of the file descriptors). */ static void -client_wait_until_can_do_something(struct ssh *ssh, struct pollfd **pfdp, - u_int *npfd_allocp, u_int *npfd_activep, int rekeying, - int *conn_in_readyp, int *conn_out_readyp) +client_wait_until_can_do_something(struct ssh *ssh, + fd_set **readsetp, fd_set **writesetp, + int *maxfdp, u_int *nallocp, int rekeying) { struct timespec timeout; int ret; - u_int p; - - *conn_in_readyp = *conn_out_readyp = 0; - /* Prepare channel poll. First two pollfd entries are reserved */ ptimeout_init(&timeout); - channel_prepare_poll(ssh, pfdp, npfd_allocp, npfd_activep, 2, &timeout); - if (*npfd_activep < 2) - fatal_f("bad npfd %u", *npfd_activep); /* shouldn't happen */ + /* Add any selections by the channel mechanism. */ + channel_prepare_select(ssh, readsetp, writesetp, maxfdp, + nallocp, &timeout); - /* channel_prepare_poll could have closed the last channel */ + /* channel_prepare_select could have closed the last channel */ if (session_closed && !channel_still_open(ssh) && !ssh_packet_have_data_to_write(ssh)) { - /* clear events since we did not call poll() */ - for (p = 0; p < *npfd_activep; p++) - (*pfdp)[p].revents = 0; + /* clear mask since we did not call select() */ + memset(*readsetp, 0, *nallocp); + memset(*writesetp, 0, *nallocp); return; } - /* Monitor server connection on reserved pollfd entries */ - (*pfdp)[0].fd = connection_in; - (*pfdp)[0].events = POLLIN; - (*pfdp)[1].fd = connection_out; - (*pfdp)[1].events = ssh_packet_have_data_to_write(ssh) ? POLLOUT : 0; + FD_SET(connection_in, *readsetp); + + /* Select server connection if have data to write to the server. */ + if (ssh_packet_have_data_to_write(ssh)) + FD_SET(connection_out, *writesetp); /* * Wait for something to happen. This will suspend the process until - * some polled descriptor can be read, written, or has some other + * some selected descriptor can be read, written, or has some other * event pending, or a timeout expires. */ set_control_persist_exit_time(ssh); @@ -553,40 +564,33 @@ ptimeout_deadline_monotime(&timeout, control_persist_exit_time); if (options.server_alive_interval > 0) ptimeout_deadline_monotime(&timeout, server_alive_time); - if (options.rekey_interval > 0 && !rekeying) { + if (options.rekey_interval > 0 && !rekeying) ptimeout_deadline_sec(&timeout, ssh_packet_get_rekey_timeout(ssh)); - } - - ret = poll(*pfdp, *npfd_activep, ptimeout_get_ms(&timeout)); + ret = pselect((*maxfdp)+1, *readsetp, *writesetp, NULL, + ptimeout_get_tsp(&timeout), NULL); if (ret == -1) { /* - * We have to clear the events because we return. + * We have to clear the select masks, because we return. * We have to return, because the mainloop checks for the flags * set by the signal handlers. */ - for (p = 0; p < *npfd_activep; p++) - (*pfdp)[p].revents = 0; + memset(*readsetp, 0, *nallocp); + memset(*writesetp, 0, *nallocp); if (errno == EINTR) return; /* Note: we might still have data in the buffers. */ - quit_message("poll: %s", strerror(errno)); - return; - } - - *conn_in_readyp = (*pfdp)[0].revents != 0; - *conn_out_readyp = (*pfdp)[1].revents != 0; - - if (options.server_alive_interval > 0 && !*conn_in_readyp && - monotime() >= server_alive_time) { + quit_message("select: %s", strerror(errno)); + } else if (options.server_alive_interval > 0 && + !FD_ISSET(connection_in, *readsetp) && + monotime() >= server_alive_time) /* - * ServerAlive check is needed. We can't rely on the poll + * ServerAlive check is needed. We can't rely on the select * timing out since traffic on the client side such as port * forwards can keep waking it up. */ server_alive_check(ssh); - } } static void @@ -615,18 +619,54 @@ enter_raw_mode(options.request_tty == REQUEST_TTY_FORCE); } +/* + * Read input from the server, and add any such data to the buffer of + * the packet subsystem. + */ +/* Read as much as possible. */ static void client_process_net_input(struct ssh *ssh) { - int r; +#ifndef USE_DIRECT_READ + /* read into memory buffer */ + char buf[SSH_IOBUFSZ]; + int len; + len = read(connection_in, buf, sizeof(buf)); + if (len == 0) { + /* + * Received EOF. The remote host has closed the + * connection. + */ + quit_message("Connection to %s closed by remote host.", + host); + return; + } /* - * Read input from the server, and add any such data to the buffer of - * the packet subsystem. + * There is a kernel bug on Solaris that causes select to + * sometimes wake up even though there is no data available. */ - schedule_server_alive_check(); - if ((r = ssh_packet_process_read(ssh, connection_in)) == 0) - return; /* success */ + if (len == -1 && + (errno == EAGAIN || errno == EINTR || errno == EWOULDBLOCK)) + len = 0; + + if (len == -1) { + /* + * An error has encountered. Perhaps there is a + * network problem. + */ + quit_message("Read from remote host %s: %s", + host, strerror(errno)); + return; + } + ssh_packet_process_incoming(ssh, buf, len); +#else + /* direct read into input buffer */ + int r; + + r = ssh_packet_process_read(ssh, connection_in, SSH_IOBUFSZ); + if (r == 0) return; /* success */ + if (r == SSH_ERR_SYSTEM_ERROR) { if (errno == EAGAIN || errno == EINTR || errno == EWOULDBLOCK) return; @@ -637,6 +677,7 @@ } } quit_message("Read from remote host %s: %s", host, ssh_err(r)); +#endif } static void @@ -679,8 +720,6 @@ * their stderr. */ if (tochan) { - debug3_f("channel %d: mux request: %s", c->self, - cr->request_type); if ((r = sshbuf_put(c->extended, errmsg, strlen(errmsg))) != 0) fatal_fr(r, "sshbuf_put"); @@ -706,6 +745,8 @@ static void client_abandon_status_confirm(struct ssh *ssh, Channel *c, void *ctx) { + UNUSED(ssh); + UNUSED(c); free(ctx); } @@ -743,10 +784,6 @@ TAILQ_INSERT_TAIL(&global_confirms, gc, entry); } -/* - * Returns non-zero if the client is able to handle a hostkeys-00@openssh.com - * hostkey update request. - */ static int can_update_hostkeys(void) { @@ -1007,7 +1044,7 @@ char *s; struct escape_filter_ctx *efc; - if (c == NULL || c->filter_ctx == NULL || len <= 0) + if (c->filter_ctx == NULL || len <= 0) return 0; efc = (struct escape_filter_ctx *)c->filter_ctx; @@ -1028,8 +1065,8 @@ if ((r = sshbuf_putf(berr, "%c.\r\n", efc->escape_char)) != 0) fatal_fr(r, "sshbuf_putf"); - if (c && c->ctl_chan != -1) { - channel_force_close(ssh, c, 1); + if (c->ctl_chan != -1) { + channel_abandon(ssh, c); return 0; } else quit_pending = 1; @@ -1037,7 +1074,7 @@ case 'Z' - 64: /* XXX support this for mux clients */ - if (c && c->ctl_chan != -1) { + if (c->ctl_chan != -1) { char b[16]; noescape: if (ch == 'Z' - 64) @@ -1074,7 +1111,7 @@ continue; case 'R': - if (ssh->compat & SSH_BUG_NOREKEY) + if (ssh_compat_fellows(ssh, SSH_BUG_NOREKEY)) logit("Server does not " "support re-keying"); else @@ -1084,7 +1121,7 @@ case 'V': /* FALLTHROUGH */ case 'v': - if (c && c->ctl_chan != -1) + if (c->ctl_chan != -1) goto noescape; if (!log_is_on_stderr()) { if ((r = sshbuf_putf(berr, @@ -1142,7 +1179,7 @@ return -1; case '?': print_escape_help(berr, efc->escape_char, - (c && c->ctl_chan != -1), + (c->ctl_chan != -1), log_is_on_stderr()); continue; @@ -1157,7 +1194,7 @@ continue; case 'C': - if (c && c->ctl_chan != -1) + if (c->ctl_chan != -1) goto noescape; if (options.enable_escape_commandline == 0) { if ((r = sshbuf_putf(berr, @@ -1241,6 +1278,8 @@ void client_filter_cleanup(struct ssh *ssh, int cid, void *ctx) { + UNUSED(ssh); + UNUSED(cid); free(ctx); } @@ -1257,6 +1296,8 @@ static void client_channel_closed(struct ssh *ssh, int id, int force, void *arg) { + UNUSED(force); + UNUSED(arg); channel_cancel_cleanup(ssh, id); session_closed = 1; leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE); @@ -1272,12 +1313,11 @@ client_loop(struct ssh *ssh, int have_pty, int escape_char_arg, int ssh2_chan_id) { - struct pollfd *pfd = NULL; - u_int npfd_alloc = 0, npfd_active = 0; + fd_set *readset = NULL, *writeset = NULL; double start_time, total_time; - int r, len; + int r, max_fd = 0, max_fd2 = 0, len; u_int64_t ibytes, obytes; - int conn_in_ready, conn_out_ready; + u_int nalloc = 0; debug("Entering interactive session."); session_ident = ssh2_chan_id; @@ -1323,6 +1363,7 @@ exit_status = -1; connection_in = ssh_packet_get_connection_in(ssh); connection_out = ssh_packet_get_connection_out(ssh); + max_fd = MAXIMUM(connection_in, connection_out); quit_pending = 0; @@ -1365,6 +1406,7 @@ /* Main loop of the client for the interactive session mode. */ while (!quit_pending) { + int conn_in_ready, conn_out_ready; /* Process buffered packets sent by the server. */ client_process_buffered_input_packets(ssh); @@ -1401,19 +1443,23 @@ * Wait until we have something to do (something becomes * available on one of the descriptors). */ - client_wait_until_can_do_something(ssh, &pfd, &npfd_alloc, - &npfd_active, ssh_packet_is_rekeying(ssh), - &conn_in_ready, &conn_out_ready); + max_fd2 = max_fd; + client_wait_until_can_do_something(ssh, &readset, &writeset, + &max_fd2, &nalloc, ssh_packet_is_rekeying(ssh)); + conn_in_ready = FD_ISSET(connection_in, readset); + conn_out_ready = FD_ISSET(connection_out, writeset); if (quit_pending) break; /* Do channel operations. */ - channel_after_poll(ssh, pfd, npfd_active); + channel_after_select(ssh, readset, writeset); /* Buffer input from the connection. */ - if (conn_in_ready) + if (conn_in_ready) { + schedule_server_alive_check(); client_process_net_input(ssh); + } if (quit_pending) break; @@ -1445,7 +1491,8 @@ } } } - free(pfd); + free(readset); + free(writeset); /* Terminate the session. */ @@ -1470,15 +1517,14 @@ * exit status to be returned. In that case, clear error code if the * connection was deliberately terminated at this end. */ - if (options.session_type == SESSION_TYPE_NONE && - received_signal == SIGTERM) { + if (options.session_type == SESSION_TYPE_NONE && received_signal == SIGTERM) { received_signal = 0; exit_status = 0; } if (received_signal) { verbose("Killed by signal %d.", (int) received_signal); - cleanup_exit(255); + cleanup_exit(128 + received_signal); /*shell style*/ } /* @@ -1491,7 +1537,7 @@ /* Output any buffered data for stderr. */ if (sshbuf_len(stderr_buffer) > 0) { len = atomicio(vwrite, fileno(stderr), - (u_char *)sshbuf_ptr(stderr_buffer), + sshbuf_mutable_ptr(stderr_buffer), sshbuf_len(stderr_buffer)); if (len < 0 || (u_int)len != sshbuf_len(stderr_buffer)) error("Write failed flushing stderr buffer."); @@ -1524,7 +1570,7 @@ Channel *c = NULL; struct sshbuf *b = NULL; char *listen_address, *originator_address; - u_int listen_port, originator_port; + u_int32_t listen_port, originator_port; int r; /* Get rest of the packet */ @@ -1536,7 +1582,7 @@ fatal_fr(r, "parse packet"); debug_f("listen %s port %d, originator %s port %d", - listen_address, listen_port, originator_address, originator_port); + listen_address, (int)listen_port, originator_address, (int)originator_port); if (listen_port > 0xffff) error_f("invalid listen port"); @@ -1585,6 +1631,8 @@ char *listen_path; int r; + UNUSED(request_type); + UNUSED(rchan); /* Get the remote path. */ if ((r = sshpkt_get_cstring(ssh, &listen_path, NULL)) != 0 || (r = sshpkt_get_string(ssh, NULL, NULL)) != 0 || /* reserved */ @@ -1604,9 +1652,11 @@ { Channel *c = NULL; char *originator; - u_int originator_port; + u_int32_t originator_port; int r, sock; + UNUSED(request_type); + UNUSED(rchan); if (!options.forward_x11) { error("Warning: ssh server tried X11 forwarding."); error("Warning: this is probably a break-in attempt by a " @@ -1624,15 +1674,15 @@ fatal_fr(r, "parse packet"); /* XXX check permission */ /* XXX range check originator port? */ - debug("client_request_x11: request from %s %u", originator, - originator_port); + debug_f("request from %s %u", originator, (unsigned)originator_port); free(originator); sock = x11_connect_display(ssh); if (sock < 0) return NULL; c = channel_new(ssh, "x11", SSH_CHANNEL_X11_OPEN, sock, sock, -1, - CHAN_TCP_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT, 0, "x11", 1); + CHAN_TCP_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT, 0, "x11", + CHANNEL_NONBLOCK_SET); c->force_drain = 1; return c; } @@ -1643,6 +1693,8 @@ Channel *c = NULL; int r, sock; + UNUSED(request_type); + UNUSED(rchan); if (!options.forward_agent) { error("Warning: ssh server tried agent forwarding."); error("Warning: this is probably a break-in attempt by a " @@ -1656,19 +1708,13 @@ } if (r != 0) { if (r != SSH_ERR_AGENT_NOT_PRESENT) - debug_fr(r, "ssh_get_authentication_socket"); + error_fr(r, "ssh_get_authentication_socket"); return NULL; } - if ((r = ssh_agent_bind_hostkey(sock, ssh->kex->initial_hostkey, - ssh->kex->session_id, ssh->kex->initial_sig, 1)) == 0) - debug_f("bound agent to hostkey"); - else - debug2_fr(r, "ssh_agent_bind_hostkey"); - c = channel_new(ssh, "authentication agent connection", SSH_CHANNEL_OPEN, sock, sock, -1, CHAN_X11_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, - "authentication agent connection", 1); + "authentication agent connection", CHANNEL_NONBLOCK_SET); c->force_drain = 1; return c; } @@ -1694,7 +1740,8 @@ debug("Tunnel forwarding using interface %s", ifname); c = channel_new(ssh, "tun", SSH_CHANNEL_OPENING, fd, fd, -1, - CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, "tun", 1); + CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, "tun", + CHANNEL_NONBLOCK_SET); c->datagram = 1; #if defined(SSH_TUN_FILTER) @@ -1726,18 +1773,19 @@ Channel *c = NULL; char *ctype = NULL; int r; - u_int rchan; size_t len; - u_int rmaxpack, rwindow; + u_int32_t rchan, rmaxpack, rwindow; + UNUSED(type); + UNUSED(seq); if ((r = sshpkt_get_cstring(ssh, &ctype, &len)) != 0 || (r = sshpkt_get_u32(ssh, &rchan)) != 0 || (r = sshpkt_get_u32(ssh, &rwindow)) != 0 || (r = sshpkt_get_u32(ssh, &rmaxpack)) != 0) goto out; - debug("client_input_channel_open: ctype %s rchan %d win %d max %d", - ctype, rchan, rwindow, rmaxpack); + debug_f("ctype %s rchan %d win %d max %d", + ctype, (int)rchan, (int)rwindow, (int)rmaxpack); if (strcmp(ctype, "forwarded-tcpip") == 0) { c = client_request_forwarded_tcpip(ssh, ctype, rchan, rwindow, @@ -1776,7 +1824,7 @@ (r = sshpkt_send(ssh)) != 0) sshpkt_fatal(ssh, r, "%s: send failure", __func__); } - r = 0; + out: free(ctype); return r; @@ -1788,46 +1836,80 @@ Channel *c = NULL; char *rtype = NULL; u_char reply; - u_int id, exitval; + int id; int r, success = 0; - if ((r = sshpkt_get_u32(ssh, &id)) != 0) +{ u_int32_t val; + if ((r = sshpkt_get_u32(ssh, &val)) != 0) return r; - if (id <= INT_MAX) - c = channel_lookup(ssh, id); + id = val; /*safe cast*/ +} + /* channel_by_id() filter bad id */ + c = channel_lookup(ssh, id); + /* channel_proxy_upstream() filter NULL channel */ if (channel_proxy_upstream(c, type, seq, ssh)) return 0; if ((r = sshpkt_get_cstring(ssh, &rtype, NULL)) != 0 || (r = sshpkt_get_u8(ssh, &reply)) != 0) goto out; - debug("client_input_channel_req: channel %u rtype %s reply %d", - id, rtype, reply); + debug_f("channel %d rtype %s reply %d", id, rtype, (int)reply); if (c == NULL) { - error("client_input_channel_req: channel %d: " - "unknown channel", id); + error_f("channel %d: unknown channel", id); } else if (strcmp(rtype, "eow@openssh.com") == 0) { if ((r = sshpkt_get_end(ssh)) != 0) goto out; chan_rcvd_eow(ssh, c); } else if (strcmp(rtype, "exit-status") == 0) { + u_int32_t exitval; if ((r = sshpkt_get_u32(ssh, &exitval)) != 0) goto out; + debug3_f("remote exit with code %d", (int)exitval); if (c->ctl_chan != -1) { mux_exit_message(ssh, c, exitval); success = 1; - } else if ((int)id == session_ident) { + } else if (id == session_ident) { /* Record exit value of local session */ success = 1; exit_status = exitval; } else { /* Probably for a mux channel that has already closed */ - debug_f("no sink for exit-status on channel %d", - id); + debug_f("no sink for exit-status on channel %d", id); } if ((r = sshpkt_get_end(ssh)) != 0) goto out; + } else if (strcmp(rtype, "exit-signal") == 0) { + char *signame = NULL; + int exitval; + + if ((r = sshpkt_get_cstring(ssh, &signame, NULL)) != 0 || + (r = sshpkt_get_u8(ssh, NULL/*core dumped*/)) != 0 || + (r = sshpkt_get_cstring(ssh, NULL/*error message*/, NULL)) != 0 || + (r = sshpkt_get_cstring(ssh, NULL/*language*/, NULL)) != 0 || + (r = sshpkt_get_end(ssh)) != 0 + ) { + free(signame); + goto out; + } + + exitval = ssh_signame2code(signame); + debug3_f("remote killed by signal '%s'", signame); + free(signame); + + if (exitval >= 0) exitval += 128; /*shell style*/ + + if (c->ctl_chan != -1) { + mux_exit_message(ssh, c, exitval); + success = 1; + } else if (id == session_ident) { + /* Record exit value of local session */ + success = 1; + exit_status = exitval; + } else { + /* Probably for a mux channel that has already closed */ + debug_f("no sink for exit-signal on channel %d", id); + } } if (reply && c != NULL && !(c->flags & CHAN_CLOSE_SENT)) { if (!c->have_remote_id) @@ -1838,7 +1920,7 @@ (r = sshpkt_send(ssh)) != 0) sshpkt_fatal(ssh, r, "%s: send failure", __func__); } - r = 0; + out: free(rtype); return r; @@ -1854,6 +1936,7 @@ * keys_match is filled in by hostkeys_find() and later (for new * keys) by client_global_hostkeys_prove_confirm(). */ + char **algs; struct sshkey **keys; u_int *keys_match; /* mask of HKF_MATCH_* from hostfile.h */ int *keys_verified; /* flag for new keys verified by server */ @@ -1882,6 +1965,9 @@ if (ctx == NULL) return; for (i = 0; i < ctx->nkeys; i++) + free(ctx->algs[i]); + free(ctx->algs); + for (i = 0; i < ctx->nkeys; i++) sshkey_free(ctx->keys[i]); free(ctx->keys); free(ctx->keys_match); @@ -2070,31 +2156,59 @@ int r, was_raw = 0, first = 1; int asking = options.update_hostkeys == SSH_UPDATE_HOSTKEYS_ASK; LogLevel loglevel = asking ? SYSLOG_LEVEL_INFO : SYSLOG_LEVEL_VERBOSE; - char *fp, *response; + struct sshkey *key; + int is_x509; + char *fp; size_t i; struct stat sb; for (i = 0; i < ctx->nkeys; i++) { if (!ctx->keys_verified[i]) continue; - if ((fp = sshkey_fingerprint(ctx->keys[i], - options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL) - fatal_f("sshkey_fingerprint failed"); + key = ctx->keys[i]; + is_x509 = sshkey_is_x509(key); + if (is_x509) { + fp = x509key_subject(key); + if (fp == NULL) + fatal_f("x509key_subject failed"); + free(fp); + continue; + } else { + fp = sshkey_fingerprint(key, + options.fingerprint_hash, SSH_FP_DEFAULT); + if (fp == NULL) + fatal_f("sshkey_fingerprint failed"); + } if (first && asking) hostkey_change_preamble(loglevel); - do_log2(loglevel, "Learned new hostkey: %s %s", - sshkey_type(ctx->keys[i]), fp); + if (is_x509) + do_log2(loglevel, "Learned new hostkey: %s", fp); + else + do_log2(loglevel, "Learned new hostkey: %s %s", + sshkey_type(key), fp); first = 0; free(fp); } for (i = 0; i < ctx->nold; i++) { - if ((fp = sshkey_fingerprint(ctx->old_keys[i], - options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL) - fatal_f("sshkey_fingerprint failed"); + key = ctx->old_keys[i]; + is_x509 = sshkey_is_x509(key); + if (is_x509) { + fp = x509key_subject(key); + if (fp == NULL) + fatal_f("x509key_subject failed"); + } else { + fp = sshkey_fingerprint(key, + options.fingerprint_hash, SSH_FP_DEFAULT); + if (fp == NULL) + fatal_f("sshkey_fingerprint failed"); + } if (first && asking) hostkey_change_preamble(loglevel); - do_log2(loglevel, "Deprecating obsolete hostkey: %s %s", - sshkey_type(ctx->old_keys[i]), fp); + if (is_x509) + do_log2(loglevel, "Deprecating obsolete hostkey: %s", fp); + else + do_log2(loglevel, "Deprecating obsolete hostkey: %s %s", + sshkey_type(key), fp); first = 0; free(fp); } @@ -2103,25 +2217,8 @@ leave_raw_mode(1); was_raw = 1; } - response = NULL; - for (i = 0; !quit_pending && i < 3; i++) { - free(response); - response = read_passphrase("Accept updated hostkeys? " - "(yes/no): ", RP_ECHO); - if (response != NULL && strcasecmp(response, "yes") == 0) - break; - else if (quit_pending || response == NULL || - strcasecmp(response, "no") == 0) { - options.update_hostkeys = 0; - break; - } else { - do_log2(loglevel, "Please enter " - "\"yes\" or \"no\""); - } - } - if (quit_pending || i >= 3 || response == NULL) + if (!ask_permission("Accept updated hostkeys?")) options.update_hostkeys = 0; - free(response); if (was_raw) enter_raw_mode(1); } @@ -2133,28 +2230,28 @@ * cancel the operation). */ for (i = 0; i < options.num_user_hostfiles; i++) { + char *known_hosts_file = options.user_hostfiles[i]; /* * NB. keys are only added to hostfiles[0], for the rest we * just delete the hostname entries. */ - if (stat(options.user_hostfiles[i], &sb) != 0) { + if (stat(known_hosts_file, &sb) == -1) { if (errno == ENOENT) { debug_f("known hosts file %s does not " - "exist", options.user_hostfiles[i]); + "exist", known_hosts_file); } else { error_f("known hosts file %s " "inaccessible: %s", - options.user_hostfiles[i], strerror(errno)); + known_hosts_file, strerror(errno)); } continue; } - if ((r = hostfile_replace_entries(options.user_hostfiles[i], + if ((r = hostfile_replace_entries(known_hosts_file, ctx->host_str, ctx->ip_str, i == 0 ? ctx->keys : NULL, i == 0 ? ctx->nkeys : 0, - options.hash_known_hosts, 0, - options.fingerprint_hash)) != 0) { + options.hash_known_hosts, options.fingerprint_hash)) != 0) { error_fr(r, "hostfile_replace_entries failed for %s", - options.user_hostfiles[i]); + known_hosts_file); } } } @@ -2166,12 +2263,13 @@ struct hostkeys_update_ctx *ctx = (struct hostkeys_update_ctx *)_ctx; size_t i, ndone; struct sshbuf *signdata; - int r, plaintype; - const u_char *sig; + int r; const char *rsa_kexalg = NULL; - char *alg = NULL; + char *rsa_keyalg = NULL; + const u_char *sig; size_t siglen; + UNUSED(seq); if (ctx->nnew == 0) fatal_f("ctx->nnew == 0"); /* sanity */ if (type != SSH2_MSG_REQUEST_SUCCESS) { @@ -2180,64 +2278,75 @@ hostkeys_update_ctx_free(ctx); return; } - if (sshkey_type_plain(sshkey_type_from_name( - ssh->kex->hostkey_alg)) == KEY_RSA) - rsa_kexalg = ssh->kex->hostkey_alg; + + if (ssh->kex->hostkey_alg != NULL) { + int hktype = sshkey_type_from_name(ssh->kex->hostkey_alg); + if (sshkey_type_plain(hktype) == KEY_RSA) + rsa_kexalg = ssh->kex->hostkey_alg; + } + if ((signdata = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); + /* Don't want to accidentally accept an unbound signature */ + if (sshbuf_len(ssh->kex->session_id) == 0) + fatal_f("zero length session_id"); /* * Expect a signature for each of the ctx->nnew private keys we * haven't seen before. They will be in the same order as the * ctx->keys where the corresponding ctx->keys_match[i] == 0. */ for (ndone = i = 0; i < ctx->nkeys; i++) { + struct sshkey *key; + const char *pkalg; + if (ctx->keys_match[i]) continue; - plaintype = sshkey_type_plain(ctx->keys[i]->type); - /* Prepare data to be signed: session ID, unique string, key */ + + key = ctx->keys[i]; + pkalg = sshkey_ssh_name(key); sshbuf_reset(signdata); - if ( (r = sshbuf_put_cstring(signdata, - "hostkeys-prove-00@openssh.com")) != 0 || - (r = sshbuf_put_stringb(signdata, - ssh->kex->session_id)) != 0 || - (r = sshkey_puts(ctx->keys[i], signdata)) != 0) - fatal_fr(r, "compose signdata"); /* Extract and verify signature */ if ((r = sshpkt_get_string_direct(ssh, &sig, &siglen)) != 0) { error_fr(r, "parse sig"); goto out; } - if ((r = sshkey_get_sigtype(sig, siglen, &alg)) != 0) { - error_fr(r, "server gave unintelligible signature " - "for %s key %zu", sshkey_type(ctx->keys[i]), i); - goto out; - } - /* - * Special case for RSA keys: if a RSA hostkey was negotiated, - * then use its signature type for verification of RSA hostkey - * proofs. Otherwise, accept only RSA-SHA256/512 signatures. - */ - if (plaintype == KEY_RSA && rsa_kexalg == NULL && - match_pattern_list(alg, HOSTKEY_PROOF_RSA_ALGS, 0) != 1) { - debug_f("server used untrusted RSA signature algorithm " - "%s for key %zu, disregarding", alg, i); - free(alg); - /* zap the key from the list */ - sshkey_free(ctx->keys[i]); - ctx->keys[i] = NULL; - ndone++; - continue; + /* Prepare data to be signed: session ID, unique string, key */ + if ((sshkey_type_plain(key->type) == KEY_RSA) && + !sshkey_is_x509(key) + ) { + free(rsa_keyalg); + r = sshkey_sigtype(sig, siglen, &rsa_keyalg); + if (r != 0) { + error_fr(r, "server gave unintelligible signature " + "for %s key %zu", pkalg, i); + goto out; + } + pkalg = rsa_keyalg; + /* warn for untrusted signature only + * if host-key is not rsa based + */ + if (rsa_kexalg == NULL && + match_pattern_list(rsa_keyalg, + "rsa-sha2-256,rsa-sha2-512", 0) != 1) { + debug("server uses untrusted RSA signature" + " algorithm %s for hostkey prove %zu", + rsa_keyalg, i); + } } - debug3_f("verify %s key %zu using sigalg %s", - sshkey_type(ctx->keys[i]), i, alg); - free(alg); - if ((r = sshkey_verify(ctx->keys[i], sig, siglen, - sshbuf_ptr(signdata), sshbuf_len(signdata), - plaintype == KEY_RSA ? rsa_kexalg : NULL, 0, NULL)) != 0) { - error_fr(r, "server gave bad signature for %s key %zu", - sshkey_type(ctx->keys[i]), i); + if ((r = sshbuf_put_cstring(signdata, + "hostkeys-prove-00@openssh.com")) != 0 || + (r = sshbuf_put_stringb(signdata, + ssh->kex->session_id)) != 0 || + (r = Xkey_puts(pkalg, key, signdata)) != 0) + fatal_fr(r, "compose signdata"); + { ssh_verify_ctx verify_ctx = { pkalg, key, &ssh->compat }; + + r = Xkey_verify(&verify_ctx, sig, siglen, sshbuf_ptr(signdata), sshbuf_len(signdata)); + if (r != 0) { + error_f("server gave bad signature for %s key %zu", pkalg, i); goto out; } + } /* Key is good. Mark it as 'seen' */ ctx->keys_verified[i] = 1; ndone++; @@ -2253,31 +2362,13 @@ /* Make the edits to known_hosts */ update_known_hosts(ctx); out: + free(rsa_keyalg); hostkeys_update_ctx_free(ctx); hostkeys_update_complete = 1; client_repledge(); } /* - * Returns non-zero if the key is accepted by HostkeyAlgorithms. - * Made slightly less trivial by the multiple RSA signature algorithm names. - */ -static int -key_accepted_by_hostkeyalgs(const struct sshkey *key) -{ - const char *ktype = sshkey_ssh_name(key); - const char *hostkeyalgs = options.hostkeyalgorithms; - - if (key->type == KEY_UNSPEC) - return 0; - if (key->type == KEY_RSA && - (match_pattern_list("rsa-sha2-256", hostkeyalgs, 0) == 1 || - match_pattern_list("rsa-sha2-512", hostkeyalgs, 0) == 1)) - return 1; - return match_pattern_list(ktype, hostkeyalgs, 0) == 1; -} - -/* * Handle hostkeys-00@openssh.com global request to inform the client of all * the server's hostkeys. The keys are checked against the user's * HostkeyAlgorithms preference before they are accepted. @@ -2289,6 +2380,7 @@ size_t i, len = 0; struct sshbuf *buf = NULL; struct sshkey *key = NULL, **tmp; + char *pkalg = NULL, **algtmp; int r, prove_sent = 0; char *fp; static int hostkeys_seen = 0; /* XXX use struct ssh */ @@ -2298,53 +2390,68 @@ if (hostkeys_seen) fatal_f("server already sent hostkeys"); + hostkeys_seen = 1; if (!can_update_hostkeys()) return 1; - hostkeys_seen = 1; ctx = xcalloc(1, sizeof(*ctx)); while (ssh_packet_remaining(ssh) > 0) { sshkey_free(key); key = NULL; + free(pkalg); + pkalg = NULL; if ((r = sshpkt_get_string_direct(ssh, &blob, &len)) != 0) { error_fr(r, "parse key"); goto out; } - if ((r = sshkey_from_blob(blob, len, &key)) != 0) { + if ((r = parse_key_from_blob(blob, len, &key, &pkalg)) != 0) { do_log2_fr(r, r == SSH_ERR_KEY_TYPE_UNKNOWN ? SYSLOG_LEVEL_DEBUG1 : SYSLOG_LEVEL_ERROR, - "convert key"); + "parse key"); continue; } fp = sshkey_fingerprint(key, options.fingerprint_hash, SSH_FP_DEFAULT); - debug3_f("received %s key %s", sshkey_type(key), fp); + debug3_f("received key %s %s", pkalg, fp); free(fp); - if (!key_accepted_by_hostkeyalgs(key)) { - debug3_f("%s key not permitted by " - "HostkeyAlgorithms", sshkey_ssh_name(key)); + /* Check that the key is accepted in HostkeyAlgorithms */ + /* NOTE: Before key exchange option HostKeyAlgorithms + is either assembled (if not set by configuration) + or set to default. See ssh_kex2() in sshconnect2.c */ + if (match_pattern_list(pkalg, options.hostkeyalgorithms, 0) != 1) { + debug3_f("%s key not permitted by HostkeyAlgorithms", + pkalg); continue; } /* Skip certs */ if (sshkey_is_cert(key)) { debug3_f("%s key is a certificate; skipping", - sshkey_ssh_name(key)); + pkalg); continue; } - /* Ensure keys are unique */ + { /* Exclude equal keys */ + int found = 0; for (i = 0; i < ctx->nkeys; i++) { if (sshkey_equal(key, ctx->keys[i])) { - error_f("received duplicated %s host key", - sshkey_ssh_name(key)); - goto out; + debug3_f("host key is equal but algorithm is %s ", + pkalg); + found = 1; + break; } } + if (found) continue; + } /* Key is good, record it */ - if ((tmp = recallocarray(ctx->keys, ctx->nkeys, ctx->nkeys + 1, - sizeof(*ctx->keys))) == NULL) - fatal_f("recallocarray failed nkeys = %zu", - ctx->nkeys); + tmp = recallocarray(ctx->keys, ctx->nkeys, ctx->nkeys + 1, sizeof(*ctx->keys)); + if (tmp == NULL) + fatal_f("recallocarray failed nkeys = %zu", ctx->nkeys); + algtmp = reallocarray(ctx->algs, ctx->nkeys + 1, sizeof(*ctx->algs)); + if (algtmp == NULL) + fatal_f("reallocarray failed nalgs = %zu", ctx->nkeys); + ctx->algs = algtmp; + ctx->algs[ctx->nkeys] = pkalg; + pkalg = NULL; ctx->keys = tmp; ctx->keys[ctx->nkeys++] = key; key = NULL; @@ -2460,7 +2567,7 @@ if (ctx->keys_match[i]) continue; sshbuf_reset(buf); - if ((r = sshkey_putb(ctx->keys[i], buf)) != 0 || + if ((r = Xkey_putb(ctx->algs[i], ctx->keys[i], buf)) != 0 || (r = sshpkt_put_stringb(ssh, buf)) != 0) fatal_fr(r, "assemble hostkeys-prove"); } @@ -2474,6 +2581,7 @@ /* Success */ out: hostkeys_update_ctx_free(ctx); + free(pkalg); sshkey_free(key); sshbuf_free(buf); if (!prove_sent) { @@ -2495,11 +2603,12 @@ u_char want_reply; int r, success = 0; + UNUSED(type); + UNUSED(seq); if ((r = sshpkt_get_cstring(ssh, &rtype, NULL)) != 0 || (r = sshpkt_get_u8(ssh, &want_reply)) != 0) goto out; - debug("client_input_global_request: rtype %s want_reply %d", - rtype, want_reply); + debug_f("rtype %s want_reply %d", rtype, (int)want_reply); if (strcmp(rtype, "hostkeys-00@openssh.com") == 0) success = client_input_hostkeys(ssh); if (want_reply) { @@ -2509,7 +2618,7 @@ (r = ssh_packet_write_wait(ssh)) != 0) goto out; } - r = 0; + out: free(rtype); return r; @@ -2533,7 +2642,7 @@ const char *term, struct termios *tiop, int in_fd, struct sshbuf *cmd, char **env) { - size_t i, j, len; + u_int i, j; int matched, r; char *name, *val; Channel *c = NULL; @@ -2557,10 +2666,10 @@ client_expect_confirm(ssh, id, "PTY allocation", CONFIRM_TTY); if ((r = sshpkt_put_cstring(ssh, term != NULL ? term : "")) != 0 || - (r = sshpkt_put_u32(ssh, (u_int)ws.ws_col)) != 0 || - (r = sshpkt_put_u32(ssh, (u_int)ws.ws_row)) != 0 || - (r = sshpkt_put_u32(ssh, (u_int)ws.ws_xpixel)) != 0 || - (r = sshpkt_put_u32(ssh, (u_int)ws.ws_ypixel)) != 0) + (r = sshpkt_put_u32(ssh, ws.ws_col)) != 0 || + (r = sshpkt_put_u32(ssh, ws.ws_row)) != 0 || + (r = sshpkt_put_u32(ssh, ws.ws_xpixel)) != 0 || + (r = sshpkt_put_u32(ssh, ws.ws_ypixel)) != 0) fatal_fr(r, "build pty-req"); if (tiop == NULL) tiop = get_saved_tio(); @@ -2585,13 +2694,13 @@ matched = 0; for (j = 0; j < options.num_send_env; j++) { - if (match_pattern(name, options.send_env[j])) { - matched = 1; - break; - } + matched = match_pattern_list(name, options.send_env[j], 0); + if (matched != 0) break; } - if (!matched) { - debug3("Ignored env %s", name); + if (matched != 1) { + debug3("%s env %s", + (matched == -1 ? "Ignored" : "Skipped"), + name); free(name); continue; } @@ -2611,19 +2720,19 @@ free(name); } - len = sshbuf_len(cmd); +{ size_t len = sshbuf_len(cmd); if (len > 0) { if (len > 900) len = 900; if (want_subsystem) { debug("Sending subsystem: %.*s", - (int)len, (const u_char*)sshbuf_ptr(cmd)); + (int)len, sshbuf_ptr(cmd)); channel_request_start(ssh, id, "subsystem", 1); client_expect_confirm(ssh, id, "subsystem", CONFIRM_CLOSE); } else { debug("Sending command: %.*s", - (int)len, (const u_char*)sshbuf_ptr(cmd)); + (int)len, sshbuf_ptr(cmd)); channel_request_start(ssh, id, "exec", 1); client_expect_confirm(ssh, id, "exec", CONFIRM_CLOSE); } @@ -2640,6 +2749,7 @@ session_setup_complete = 1; client_repledge(); } +} static void client_init_dispatch(struct ssh *ssh) diff -ruN openssh-9.4p1/compat.c openssh-9.4p1+x509-14.2.1/compat.c --- openssh-9.4p1/compat.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/compat.c 2023-08-20 10:07:01.000000000 +0300 @@ -1,6 +1,7 @@ /* $OpenBSD: compat.c,v 1.126 2023/03/06 12:14:48 dtucker Exp $ */ /* * Copyright (c) 1999, 2000, 2001, 2002 Markus Friedl. All rights reserved. + * Copyright (c) 2017-2021 Roumen Petrov. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -36,10 +37,11 @@ #include "compat.h" #include "log.h" #include "match.h" +#include "sshbuf.h" -/* determine bug flags from SSH protocol banner */ -void -compat_banner(struct ssh *ssh, const char *version) +/* datafellows bug compatibility */ +static u_int +compat_datafellows(const char *version) { int i; static struct { @@ -51,8 +53,7 @@ "OpenSSH_3.1*", SSH_BUG_EXTEOF|SSH_OLD_FORWARD_ADDR| SSH_BUG_SIGTYPE}, { "OpenSSH_3.*", SSH_OLD_FORWARD_ADDR|SSH_BUG_SIGTYPE }, - { "Sun_SSH_1.0*", SSH_BUG_NOREKEY|SSH_BUG_EXTEOF| - SSH_BUG_SIGTYPE}, + { "Sun_SSH_1.0*", SSH_BUG_NOREKEY|SSH_BUG_EXTEOF}, { "OpenSSH_2*," "OpenSSH_3*," "OpenSSH_4*", SSH_BUG_SIGTYPE }, @@ -62,12 +63,11 @@ { "OpenSSH_6.5*," "OpenSSH_6.6*", SSH_NEW_OPENSSH|SSH_BUG_CURVE25519PAD| SSH_BUG_SIGTYPE}, - { "OpenSSH_7.4*", SSH_NEW_OPENSSH|SSH_BUG_SIGTYPE| - SSH_BUG_SIGTYPE74}, { "OpenSSH_7.0*," "OpenSSH_7.1*," "OpenSSH_7.2*," "OpenSSH_7.3*," + "OpenSSH_7.4*," "OpenSSH_7.5*," "OpenSSH_7.6*," "OpenSSH_7.7*", SSH_NEW_OPENSSH|SSH_BUG_SIGTYPE}, @@ -125,42 +125,158 @@ }; /* process table, return first match */ - ssh->compat = 0; for (i = 0; check[i].pat; i++) { if (match_pattern_list(version, check[i].pat, 0) == 1) { - debug_f("match: %s pat %s compat 0x%08x", + debug("match: %s pat %s compat 0x%08x", version, check[i].pat, check[i].bugs); - ssh->compat = check[i].bugs; - return; + return check[i].bugs; } } - debug_f("no match: %s", version); + debug("no match: %s", version); + return 0; } /* Always returns pointer to allocated memory, caller must free. */ char * -compat_kex_proposal(struct ssh *ssh, const char *p) +compat_kex_proposal(struct ssh *ssh, char *p) { - char *cp = NULL, *cp2 = NULL; + char *cp = NULL; - if ((ssh->compat & (SSH_BUG_CURVE25519PAD|SSH_OLD_DHGEX)) == 0) + if (!ssh_compat_fellows(ssh, (SSH_BUG_CURVE25519PAD|SSH_OLD_DHGEX))) return xstrdup(p); + debug2_f("original KEX proposal: %s", p); - if ((ssh->compat & SSH_BUG_CURVE25519PAD) != 0) - if ((cp = match_filter_denylist(p, + if (ssh_compat_fellows(ssh, SSH_BUG_CURVE25519PAD)) { + if ((p = match_filter_denylist(p, "curve25519-sha256@libssh.org")) == NULL) fatal("match_filter_denylist failed"); - if ((ssh->compat & SSH_OLD_DHGEX) != 0) { - if ((cp2 = match_filter_denylist(cp ? cp : p, + cp = p; + } + if (ssh_compat_fellows(ssh, SSH_OLD_DHGEX)) { + if ((p = match_filter_denylist(p, "diffie-hellman-group-exchange-sha256," "diffie-hellman-group-exchange-sha1")) == NULL) fatal("match_filter_denylist failed"); free(cp); - cp = cp2; } - if (cp == NULL || *cp == '\0') + debug2_f("compat KEX proposal: %s", p); + if (*p == '\0') fatal("No supported key exchange algorithms found"); - debug2_f("compat KEX proposal: %s", cp); - return cp; + return p; +} + + +struct sshx_compatibility_st { + int/*boolean*/ flag; + const char *pattern; +}; +typedef struct sshx_compatibility_st sshx_compatibility; + + +static sshx_compatibility* +xkey_compatibility_find( + const char *remote_version, + sshx_compatibility *compatibility_info +) { + sshx_compatibility *p; + + for (p = compatibility_info; p->pattern; p++) { + if (match_pattern_list(remote_version, p->pattern, 0) == 1) + break; + } + return p; +} + + +int xcompat = 0; + +static u_int +xkey_compatibility(const char *remote_version) { + u_int res = 0; + sshx_compatibility *p; + +/* Process each table and stop on first match. + Order of compatibility info is important! +*/ +{ static sshx_compatibility info[] = { + { 0, "OpenSSH*PKIX[??.*" /* 10.+ first correct */ }, + { 0, "OpenSSH*PKIX[X.*" /* developlement */ }, + { 1, "OpenSSH*" /* PKIX pre 10.0 */ }, + { 1, "SecureNetTerm-3.1" /* same as PKIX pre 10.0 */}, + { 0, NULL } }; + p = xkey_compatibility_find(remote_version, info); +} + if (p->flag != 0) { + res |= SSHX_RFC6187_MISSING_KEY_IDENTIFIER; + res |= SSHX_RFC6187_ASN1_OPAQUE_ECDSA_SIGNATURE; + } + debug("x.509 compatibility rfc6187_missing_key_identifier=%s: pattern '%s' match '%s'", + (p->flag != 0 ? "yes": "no"), + (p->pattern != NULL ? p->pattern : "*"), + remote_version); + debug("x.509 compatibility rfc6187_asn1_opaque_ecdsa_signature=%s: pattern '%s' match '%s'", + (p->flag != 0 ? "yes": "no"), + (p->pattern != NULL ? p->pattern : "*"), + remote_version); + +{ static sshx_compatibility info[] = { + { 0, "OpenSSH*PKIX*" /* all correct */ }, + { 1, "OpenSSH_7.2*" /* list only rsa-sha2-256 and rsa-sha2-512 */ }, + { 1, "OpenSSH_7.3*" /* list only rsa-sha2-256 and rsa-sha2-512 */ }, + { 1, "OpenSSH_7.4*" /* list without rsa-sha2-256 and rsa-sha2-512 */ }, + { 0, NULL } }; + p = xkey_compatibility_find(remote_version, info); +} + if (p->flag != 0) { + res |= SSHX_OPENSSH_BROKEN_ALGO_INFO; + } + debug("x.509 compatibility broken list with accepted publickey algorithms=%s: pattern '%s' match '%s'", + (p->flag != 0 ? "yes": "no"), + (p->pattern != NULL ? p->pattern : "*"), + remote_version); + + xcompat = res; /* TODO */ + return res; +} + + +void +ssh_set_compatibility(struct ssh *ssh, const char *remote_version) { + ssh_compat *flags = &ssh->compat; + if (remote_version == NULL) { + flags->datafellows = 0; + flags->extra = 0; + return; + } + flags->datafellows = compat_datafellows(remote_version); + flags->extra = xkey_compatibility(remote_version); } + +int +sshbuf_get_compat(struct sshbuf *b, ssh_compat *v) { + u_int32_t v1, v2; + int r; + + r = sshbuf_get_u32(b, &v1); + if (r != 0) return r; + r = sshbuf_get_u32(b, &v2); + if (r != 0) return r; + + v->datafellows = v1; + v->extra = v2; + return 0; +} + + +int +sshbuf_put_compat(struct sshbuf *b, const ssh_compat *v) { + int r; + + r = sshbuf_put_u32(b, v->datafellows); + if (r != 0) return r; + r = sshbuf_put_u32(b, v->extra); + if (r != 0) return r; + + return 0; +} diff -ruN openssh-9.4p1/compat.h openssh-9.4p1+x509-14.2.1/compat.h --- openssh-9.4p1/compat.h 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/compat.h 2023-08-20 10:07:00.000000000 +0300 @@ -1,7 +1,7 @@ /* $OpenBSD: compat.h,v 1.62 2023/03/06 12:14:48 dtucker Exp $ */ - /* * Copyright (c) 1999, 2000, 2001 Markus Friedl. All rights reserved. + * Copyright (c) 2017-2021 Roumen Petrov. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -29,7 +29,7 @@ #define SSH_BUG_UTF8TTYMODE 0x00000001 #define SSH_BUG_SIGTYPE 0x00000002 -#define SSH_BUG_SIGTYPE74 0x00000004 +/* #define unused 0x00000004 */ /* #define unused 0x00000008 */ #define SSH_OLD_SESSIONID 0x00000010 /* #define unused 0x00000020 */ @@ -60,6 +60,32 @@ struct ssh; -void compat_banner(struct ssh *, const char *); -char *compat_kex_proposal(struct ssh *, const char *); +char *compat_kex_proposal(struct ssh *, char *); + + +extern int xcompat; /* extra compatibility */ + +#define SSHX_RFC6187_MISSING_KEY_IDENTIFIER 0x00000001U +#define SSHX_RFC6187_ASN1_OPAQUE_ECDSA_SIGNATURE 0x00000002U +#define SSHX_OPENSSH_BROKEN_ALGO_INFO 0x00000004U + + +/* enhanced secure shell compatibility */ +struct ssh_compat_st { + u_int datafellows; + u_int extra; +}; + +static inline int/*bool*/ +check_compat_fellows(ssh_compat *compat, u_int flag) { + return (flag & compat->datafellows) != 0; +} + +static inline int/*bool*/ +check_compat_extra(ssh_compat *compat, u_int flag) { + return (flag & compat->extra) != 0; +} + +int sshbuf_get_compat(struct sshbuf *b, ssh_compat *v); +int sshbuf_put_compat(struct sshbuf *b, const ssh_compat *v); #endif diff -ruN openssh-9.4p1/config.guess openssh-9.4p1+x509-14.2.1/config.guess --- openssh-9.4p1/config.guess 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/config.guess 2023-08-20 10:07:00.000000000 +0300 @@ -1,10 +1,10 @@ #! /bin/sh # Attempt to guess a canonical system name. -# Copyright 1992-2022 Free Software Foundation, Inc. +# Copyright 1992-2023 Free Software Foundation, Inc. # shellcheck disable=SC2006,SC2268 # see below for rationale -timestamp='2022-09-17' +timestamp='2023-07-20' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by @@ -47,7 +47,7 @@ usage="\ Usage: $0 [OPTION] -Output the configuration name of the system \`$me' is run on. +Output the configuration name of the system '$me' is run on. Options: -h, --help print this help, then exit @@ -60,13 +60,13 @@ GNU config.guess ($timestamp) Originally written by Per Bothner. -Copyright 1992-2022 Free Software Foundation, Inc. +Copyright 1992-2023 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" -Try \`$me --help' for more information." +Try '$me --help' for more information." # Parse command line while test $# -gt 0 ; do @@ -102,8 +102,8 @@ # temporary files to be created and, as you can see below, it is a # headache to deal with in a portable fashion. -# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still -# use `HOST_CC' if defined, but it is deprecated. +# Historically, 'CC_FOR_BUILD' used to be named 'HOST_CC'. We still +# use 'HOST_CC' if defined, but it is deprecated. # Portable tmp directory creation inspired by the Autoconf team. @@ -459,7 +459,7 @@ UNAME_RELEASE=`uname -v` ;; esac - # Japanese Language versions have a version number like `4.1.3-JL'. + # Japanese Language versions have a version number like '4.1.3-JL'. SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/-/_/'` GUESS=sparc-sun-sunos$SUN_REL ;; @@ -976,7 +976,27 @@ GUESS=$UNAME_MACHINE-unknown-minix ;; aarch64:Linux:*:*) - GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + set_cc_for_build + CPU=$UNAME_MACHINE + LIBCABI=$LIBC + if test "$CC_FOR_BUILD" != no_compiler_found; then + ABI=64 + sed 's/^ //' << EOF > "$dummy.c" + #ifdef __ARM_EABI__ + #ifdef __ARM_PCS_VFP + ABI=eabihf + #else + ABI=eabi + #endif + #endif +EOF + cc_set_abi=`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^ABI' | sed 's, ,,g'` + eval "$cc_set_abi" + case $ABI in + eabi | eabihf) CPU=armv8l; LIBCABI=$LIBC$ABI ;; + esac + fi + GUESS=$CPU-unknown-linux-$LIBCABI ;; aarch64_be:Linux:*:*) UNAME_MACHINE=aarch64_be @@ -1042,6 +1062,15 @@ k1om:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; + kvx:Linux:*:*) + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; + kvx:cos:*:*) + GUESS=$UNAME_MACHINE-unknown-cos + ;; + kvx:mbr:*:*) + GUESS=$UNAME_MACHINE-unknown-mbr + ;; loongarch32:Linux:*:* | loongarch64:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; @@ -1197,7 +1226,7 @@ GUESS=$UNAME_MACHINE-pc-sysv4.2uw$UNAME_VERSION ;; i*86:OS/2:*:*) - # If we were able to find `uname', then EMX Unix compatibility + # If we were able to find 'uname', then EMX Unix compatibility # is probably installed. GUESS=$UNAME_MACHINE-pc-os2-emx ;; @@ -1338,7 +1367,7 @@ GUESS=ns32k-sni-sysv fi ;; - PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort + PENTIUM:*:4.0*:*) # Unisys 'ClearPath HMP IX 4000' SVR4/MP effort # says GUESS=i586-unisys-sysv4 ;; diff -ruN openssh-9.4p1/config.h.in openssh-9.4p1+x509-14.2.1/config.h.in --- openssh-9.4p1/config.h.in 2023-08-10 04:12:03.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/config.h.in 2023-08-20 10:07:01.000000000 +0300 @@ -10,6 +10,9 @@ /* Define if your AIX loginfailed() function takes 4 arguments (AIX >= 5.2) */ #undef AIX_LOGINFAILED_4ARG +/* Define as const if ASN1_STRING_CONST() declare const argument */ +#undef ASN1_STRING_LENGTH_CONST + /* System only supports IPv4 audit records */ #undef AU_IPv4 @@ -19,13 +22,10 @@ /* The system has incomplete BSM API */ #undef BROKEN_BSM_API -/* broken in chroots on older kernels */ -#undef BROKEN_CLOSEFROM - /* Define if cmsg_type is not passed correctly */ #undef BROKEN_CMSG_TYPE -/* getaddrinfo is broken (if present) */ +/* Define to 1 if system getaddrinfo(3) is broken */ #undef BROKEN_GETADDRINFO /* getgroups(0,NULL) will return -1 */ @@ -34,17 +34,17 @@ /* getline is not what we expect */ #undef BROKEN_GETLINE -/* FreeBSD glob does not do what we need */ +/* Define to 1 if system glob(3) does not do what we expect */ #undef BROKEN_GLOB -/* Define if you system's inet_ntoa is busted (e.g. Irix gcc issue) */ +/* Define to 1 if system inet_ntoa(3) is broken */ #undef BROKEN_INET_NTOA -/* Define if your struct dirent expects you to allocate extra space for d_name - */ +/* Define to 1 if system struct dirent expects program to allocate extra space + for d_name */ #undef BROKEN_ONE_BYTE_DIRENT_D_NAME -/* System poll(2) implementation is broken */ +/* Define to 1 if system poll(2) implementation is broken */ #undef BROKEN_POLL /* Can't do comparisons on readv */ @@ -57,7 +57,10 @@ /* Needed for NeXT */ #undef BROKEN_SAVED_UIDS -/* Define if your setregid() is broken */ +/* Define if restarted signals do not interrupt select */ +#undef BROKEN_SA_RESTART + +/* Define to 1 if system setregid(2) is broken */ #undef BROKEN_SETREGID /* Define if your setresgid() is broken */ @@ -66,7 +69,7 @@ /* Define if your setresuid() is broken */ #undef BROKEN_SETRESUID -/* Define if your setreuid() is broken */ +/* Define to 1 if system setreuid(2) is broken */ #undef BROKEN_SETREUID /* LynxOS has broken setvbuf() implementation */ @@ -75,7 +78,7 @@ /* QNX shadow support is broken */ #undef BROKEN_SHADOW_EXPIRE -/* Define if your snprintf is busted */ +/* Define to 1 if snprintf is broken or outdated (lack %zu, %ld and etc.) */ #undef BROKEN_SNPRINTF /* strndup broken, see APAR IY61211 */ @@ -87,10 +90,10 @@ /* strnvis detected broken */ #undef BROKEN_STRNVIS -/* tcgetattr with ICANON may hang */ +/* Define to 1 if tcgetattr with ICANON may hang */ #undef BROKEN_TCGETATTR_ICANON -/* updwtmpx is broken (if present) */ +/* Define to 1 if system updwtmpx(3) is broken */ #undef BROKEN_UPDWTMPX /* Define if you have BSD auth support */ @@ -108,7 +111,7 @@ /* Define if you want to specify the path to your wtmp file */ #undef CONF_WTMP_FILE -/* Need to call setpgrp as root */ +/* Define if your platform needs to skip post auth file descriptor passing */ #undef DISABLE_FD_PASSING /* Define if you don't want to use lastlog */ @@ -138,15 +141,9 @@ /* Define if you don't want to use wtmpx */ #undef DISABLE_WTMPX -/* Enable for PKCS#11 support */ +/* Define if you want to enable PKCS#11 support */ #undef ENABLE_PKCS11 -/* Enable for U2F/FIDO support */ -#undef ENABLE_SK - -/* Enable for built-in U2F/FIDO support */ -#undef ENABLE_SK_INTERNAL - /* define if fflush(NULL) does not work */ #undef FFLUSH_NULL_BUG @@ -174,7 +171,7 @@ /* Define if your system glob() function has gl_statv options in glob_t */ #undef GLOB_HAS_GL_STATV -/* Define this if you want GSSAPI support in the version 2 protocol */ +/* Define this if you want GSSAPI support */ #undef GSSAPI /* Define if you want to use shadow password expire field */ @@ -195,6 +192,9 @@ /* Define if you have ut_addr_v6 in utmpx.h */ #undef HAVE_ADDR_V6_IN_UTMPX +/* Define to 1 if you have the `AES_encrypt' function. */ +#undef HAVE_AES_ENCRYPT + /* Define to 1 if you have the `arc4random' function. */ #undef HAVE_ARC4RANDOM @@ -207,6 +207,12 @@ /* Define to 1 if you have the `arc4random_uniform' function. */ #undef HAVE_ARC4RANDOM_UNIFORM +/* Define to 1 if you have the header file. */ +#undef HAVE_ARPA_INET_H + +/* Define to 1 if you have the `ASN1_STRING_get0_data' function. */ +#undef HAVE_ASN1_STRING_GET0_DATA + /* Define to 1 if you have the `asprintf' function. */ #undef HAVE_ASPRINTF @@ -216,7 +222,8 @@ /* Have attribute nonnull */ #undef HAVE_ATTRIBUTE__NONNULL__ -/* OpenBSD's gcc has sentinel */ +/* Define to 1 if compiler accept __attribute__ that warn if last parameter is + not NULL */ #undef HAVE_ATTRIBUTE__SENTINEL__ /* Define to 1 if you have the `aug_get_machine' function. */ @@ -231,9 +238,6 @@ /* Define if you have the basename function. */ #undef HAVE_BASENAME -/* Define to 1 if you have the `bcopy' function. */ -#undef HAVE_BCOPY - /* Define to 1 if you have the `bcrypt_pbkdf' function. */ #undef HAVE_BCRYPT_PBKDF @@ -258,6 +262,12 @@ /* Define to 1 if you have the `Blowfish_stream2word' function. */ #undef HAVE_BLOWFISH_STREAM2WORD +/* Define to 1 if you have the `BN_check_prime' function. */ +#undef HAVE_BN_CHECK_PRIME + +/* Define to 1 if you have the `BN_is_negative' function. */ +#undef HAVE_BN_IS_NEGATIVE + /* Define to 1 if you have the `BN_is_prime_ex' function. */ #undef HAVE_BN_IS_PRIME_EX @@ -270,13 +280,11 @@ /* Define to 1 if you have the header file. */ #undef HAVE_BSTRING_H -/* Define to 1 if you have the `bzero' function. */ -#undef HAVE_BZERO - -/* calloc(0, x) returns NULL */ +/* Define to 1 if your system function calloc(0, x) returns non-null, and to 0 + otherwise. */ #undef HAVE_CALLOC -/* Define if you have caph_cache_tzdata */ +/* Define to 1 if you have the `caph_cache_tzdata' function. */ #undef HAVE_CAPH_CACHE_TZDATA /* Define to 1 if you have the header file. */ @@ -309,9 +317,6 @@ /* Define to 1 if you have the `crypt' function. */ #undef HAVE_CRYPT -/* Define to 1 if you have the header file. */ -#undef HAVE_CRYPTO_SHA2_H - /* Define to 1 if you have the header file. */ #undef HAVE_CRYPT_H @@ -325,21 +330,49 @@ you don't. */ #undef HAVE_DECL_AI_NUMERICSERV +/* Define to 1 if you have the declaration of `arc4random', and to 0 if you + don't. */ +#undef HAVE_DECL_ARC4RANDOM + +/* Define to 1 if you have the declaration of `arc4random_buf', and to 0 if + you don't. */ +#undef HAVE_DECL_ARC4RANDOM_BUF + +/* Define to 1 if you have the declaration of `arc4random_stir', and to 0 if + you don't. */ +#undef HAVE_DECL_ARC4RANDOM_STIR + +/* Define to 1 if you have the declaration of `arc4random_uniform', and to 0 + if you don't. */ +#undef HAVE_DECL_ARC4RANDOM_UNIFORM + /* Define to 1 if you have the declaration of `authenticate', and to 0 if you don't. */ #undef HAVE_DECL_AUTHENTICATE -/* Define to 1 if you have the declaration of `bzero', and to 0 if you don't. - */ -#undef HAVE_DECL_BZERO +/* Define to 1 if you have the declaration of `DEFINE_STACK_OF', and to 0 if + you don't. */ +#undef HAVE_DECL_DEFINE_STACK_OF -/* Define to 1 if you have the declaration of `ftruncate', and to 0 if you +/* Define to 1 if you have the declaration of `endgrent', and to 0 if you don't. */ -#undef HAVE_DECL_FTRUNCATE +#undef HAVE_DECL_ENDGRENT -/* Define to 1 if you have the declaration of `getentropy', and to 0 if you +/* Define to 1 if you have the declaration of `endpwent', and to 0 if you don't. */ -#undef HAVE_DECL_GETENTROPY +#undef HAVE_DECL_ENDPWENT + +/* Define to 1 if you have the declaration of `endutent', and to 0 if you + don't. */ +#undef HAVE_DECL_ENDUTENT + +/* Define to 1 if you have the declaration of `ERR_load_FIPS_strings', and to + 0 if you don't. */ +#undef HAVE_DECL_ERR_LOAD_FIPS_STRINGS + +/* Define to 1 if you have the declaration of `ftruncate', and to 0 if you + don't. */ +#undef HAVE_DECL_FTRUNCATE /* Define to 1 if you have the declaration of `getpeereid', and to 0 if you don't. */ @@ -381,6 +414,10 @@ */ #undef HAVE_DECL_MEMMEM +/* Define to 1 if you have the declaration of `memset_s', and to 0 if you + don't. */ +#undef HAVE_DECL_MEMSET_S + /* Define to 1 if you have the declaration of `NFDBITS', and to 0 if you don't. */ #undef HAVE_DECL_NFDBITS @@ -397,6 +434,10 @@ don't. */ #undef HAVE_DECL_PASSWDEXPIRED +/* Define to 1 if you have the declaration of `pututline', and to 0 if you + don't. */ +#undef HAVE_DECL_PUTUTLINE + /* Define to 1 if you have the declaration of `readv', and to 0 if you don't. */ #undef HAVE_DECL_READV @@ -413,6 +454,10 @@ don't. */ #undef HAVE_DECL_UINT32_MAX +/* Define to 1 if you have the declaration of `UTF8_getc', and to 0 if you + don't. */ +#undef HAVE_DECL_UTF8_GETC + /* Define to 1 if you have the declaration of `writev', and to 0 if you don't. */ #undef HAVE_DECL_WRITEV @@ -434,6 +479,9 @@ /* Define if you have /dev/ptc */ #undef HAVE_DEV_PTS_AND_PTC +/* Define to 1 if you have the `DH_get0_key' function. */ +#undef HAVE_DH_GET0_KEY + /* Define to 1 if you have the header file. */ #undef HAVE_DIRENT_H @@ -443,15 +491,39 @@ /* Define to 1 if you have the `dirname' function. */ #undef HAVE_DIRNAME -/* Define to 1 if you have the `dlopen' function. */ -#undef HAVE_DLOPEN - /* Define to 1 if you have the `DSA_generate_parameters_ex' function. */ #undef HAVE_DSA_GENERATE_PARAMETERS_EX +/* Define to 1 if you have the `DSA_get0_key' function. */ +#undef HAVE_DSA_GET0_KEY + +/* Define to 1 if you have the `DSA_SIG_get0' function. */ +#undef HAVE_DSA_SIG_GET0 + +/* Define to 1 if you have the `DSA_SIG_set0' function. */ +#undef HAVE_DSA_SIG_SET0 + +/* Define to 1 if `name' is a member of `ECDSA_METHOD'. */ +#undef HAVE_ECDSA_METHOD_NAME + +/* Define to 1 if you have the `ECDSA_METHOD_new' function. */ +#undef HAVE_ECDSA_METHOD_NEW + +/* Define to 1 if you have the `ECDSA_SIG_get0' function. */ +#undef HAVE_ECDSA_SIG_GET0 + +/* Define to 1 if you have the `ECDSA_SIG_set0' function. */ +#undef HAVE_ECDSA_SIG_SET0 + +/* Define to 1 if you have the `EC_GROUP_get_field_type' function. */ +#undef HAVE_EC_GROUP_GET_FIELD_TYPE + /* Define to 1 if you have the `EC_KEY_METHOD_new' function. */ #undef HAVE_EC_KEY_METHOD_NEW +/* Define to 1 if you have the `EC_POINT_get_affine_coordinates' function. */ +#undef HAVE_EC_POINT_GET_AFFINE_COORDINATES + /* Define to 1 if you have the header file. */ #undef HAVE_ELF_H @@ -473,9 +545,18 @@ /* Define to 1 if you have the `errx' function. */ #undef HAVE_ERRX +/* Define to 1 if you have the `ERR_get_error_all' function. */ +#undef HAVE_ERR_GET_ERROR_ALL + /* Define to 1 if you have the header file. */ #undef HAVE_ERR_H +/* Define to 1 if you have the `ERR_load_FIPS_strings' function. */ +#undef HAVE_ERR_LOAD_FIPS_STRINGS + +/* Define to 1 if you have the `ERR_remove_thread_state' function. */ +#undef HAVE_ERR_REMOVE_THREAD_STATE + /* Define if your system has /etc/default/login */ #undef HAVE_ETC_DEFAULT_LOGIN @@ -485,33 +566,51 @@ /* Define to 1 if you have the `EVP_CIPHER_CTX_get_iv' function. */ #undef HAVE_EVP_CIPHER_CTX_GET_IV -/* Define to 1 if you have the `EVP_CIPHER_CTX_get_updated_iv' function. */ -#undef HAVE_EVP_CIPHER_CTX_GET_UPDATED_IV - /* Define to 1 if you have the `EVP_CIPHER_CTX_iv' function. */ #undef HAVE_EVP_CIPHER_CTX_IV -/* Define to 1 if you have the `EVP_CIPHER_CTX_iv_noconst' function. */ -#undef HAVE_EVP_CIPHER_CTX_IV_NOCONST - -/* Define to 1 if you have the `EVP_CIPHER_CTX_set_iv' function. */ -#undef HAVE_EVP_CIPHER_CTX_SET_IV +/* Define to 1 if you have the `EVP_CIPHER_CTX_new' function. */ +#undef HAVE_EVP_CIPHER_CTX_NEW -/* Define to 1 if you have the `EVP_DigestFinal_ex' function. */ -#undef HAVE_EVP_DIGESTFINAL_EX +/* Define to 1 if you have the `EVP_DigestSign' function. */ +#undef HAVE_EVP_DIGESTSIGN -/* Define to 1 if you have the `EVP_DigestInit_ex' function. */ -#undef HAVE_EVP_DIGESTINIT_EX +/* Define to 1 if you have the `EVP_DigestSignInit' function. */ +#undef HAVE_EVP_DIGESTSIGNINIT -/* Define to 1 if you have the `EVP_MD_CTX_cleanup' function. */ -#undef HAVE_EVP_MD_CTX_CLEANUP +/* Define to 1 if you have the `EVP_dss1' function. */ +#undef HAVE_EVP_DSS1 -/* Define to 1 if you have the `EVP_MD_CTX_copy_ex' function. */ -#undef HAVE_EVP_MD_CTX_COPY_EX +/* Define to 1 if you have the `EVP_KEYMGMT_get0_provider' function. */ +#undef HAVE_EVP_KEYMGMT_GET0_PROVIDER /* Define to 1 if you have the `EVP_MD_CTX_init' function. */ #undef HAVE_EVP_MD_CTX_INIT +/* Define to 1 if you have the `EVP_MD_CTX_new' function. */ +#undef HAVE_EVP_MD_CTX_NEW + +/* Define to 1 if you have the `EVP_MD_flags' function. */ +#undef HAVE_EVP_MD_FLAGS + +/* Define to 1 if you have the `EVP_MD_get_flags' function. */ +#undef HAVE_EVP_MD_GET_FLAGS + +/* Define to 1 if you have the `EVP_PKEY_base_id' function. */ +#undef HAVE_EVP_PKEY_BASE_ID + +/* Define to 1 if you have the `EVP_PKEY_cmp' function. */ +#undef HAVE_EVP_PKEY_CMP + +/* Define to 1 if you have the `EVP_PKEY_eq' function. */ +#undef HAVE_EVP_PKEY_EQ + +/* Define to 1 if you have the `EVP_PKEY_get_base_id' function. */ +#undef HAVE_EVP_PKEY_GET_BASE_ID + +/* Define to 1 if you have the `EVP_PKEY_print_params' function. */ +#undef HAVE_EVP_PKEY_PRINT_PARAMS + /* Define to 1 if you have the `EVP_sha256' function. */ #undef HAVE_EVP_SHA256 @@ -554,29 +653,8 @@ /* Define to 1 if you have the header file. */ #undef HAVE_FEATURES_H -/* Define to 1 if you have the `fido_assert_set_clientdata' function. */ -#undef HAVE_FIDO_ASSERT_SET_CLIENTDATA - -/* Define to 1 if you have the `fido_cred_prot' function. */ -#undef HAVE_FIDO_CRED_PROT - -/* Define to 1 if you have the `fido_cred_set_clientdata' function. */ -#undef HAVE_FIDO_CRED_SET_CLIENTDATA - -/* Define to 1 if you have the `fido_cred_set_prot' function. */ -#undef HAVE_FIDO_CRED_SET_PROT - -/* Define to 1 if you have the `fido_dev_get_touch_begin' function. */ -#undef HAVE_FIDO_DEV_GET_TOUCH_BEGIN - -/* Define to 1 if you have the `fido_dev_get_touch_status' function. */ -#undef HAVE_FIDO_DEV_GET_TOUCH_STATUS - -/* Define to 1 if you have the `fido_dev_is_winhello' function. */ -#undef HAVE_FIDO_DEV_IS_WINHELLO - -/* Define to 1 if you have the `fido_dev_supports_cred_prot' function. */ -#undef HAVE_FIDO_DEV_SUPPORTS_CRED_PROT +/* Define to 1 if you have the header file. */ +#undef HAVE_FIPSCHECK_H /* Define to 1 if you have the header file. */ #undef HAVE_FLOATINGPOINT_H @@ -638,6 +716,9 @@ /* Define to 1 if you have the `getgrset' function. */ #undef HAVE_GETGRSET +/* Define to 1 if you have the `getifaddrs' function. */ +#undef HAVE_GETIFADDRS + /* Define to 1 if you have the `getlastlogxbyname' function. */ #undef HAVE_GETLASTLOGXBYNAME @@ -698,15 +779,6 @@ /* Define to 1 if you have the `getttyent' function. */ #undef HAVE_GETTTYENT -/* Define to 1 if you have the `getutent' function. */ -#undef HAVE_GETUTENT - -/* Define to 1 if you have the `getutid' function. */ -#undef HAVE_GETUTID - -/* Define to 1 if you have the `getutline' function. */ -#undef HAVE_GETUTLINE - /* Define to 1 if you have the `getutxent' function. */ #undef HAVE_GETUTXENT @@ -752,9 +824,6 @@ /* Define if HEADER.ad exists in arpa/nameser.h */ #undef HAVE_HEADER_AD -/* Define to 1 if you have the `HMAC_CTX_init' function. */ -#undef HAVE_HMAC_CTX_INIT - /* Define if you have ut_host in utmp.h */ #undef HAVE_HOST_IN_UTMP @@ -827,6 +896,27 @@ /* Define to 1 if you have the header file. */ #undef HAVE_LASTLOG_H +/* Define to 1 if you have the header file. */ +#undef HAVE_LBER_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_LDAP_H + +/* Define to 1 if you have the `ldap_initialize' function. */ +#undef HAVE_LDAP_INITIALIZE + +/* Define to 1 if you have the `ldap_parse_result' function. */ +#undef HAVE_LDAP_PARSE_RESULT + +/* Define to 1 if you have the `ldap_sasl_bind_s' function. */ +#undef HAVE_LDAP_SASL_BIND_S + +/* Define to 1 if you have the `ldap_search_ext_s' function. */ +#undef HAVE_LDAP_SEARCH_EXT_S + +/* Define to 1 if you have the `ldap_unbind_ext_s' function. */ +#undef HAVE_LDAP_UNBIND_EXT_S + /* Define if you want ldns support */ #undef HAVE_LDNS @@ -881,9 +971,6 @@ /* Define to 1 if you have the header file. */ #undef HAVE_LINUX_SECCOMP_H -/* Define to 1 if you have the `llabs' function. */ -#undef HAVE_LLABS - /* Define to 1 if you have the header file. */ #undef HAVE_LOCALE_H @@ -930,12 +1017,21 @@ /* Define to 1 if you have the `mbtowc' function. */ #undef HAVE_MBTOWC +/* Define to 1 if you have the `md5_crypt' function. */ +#undef HAVE_MD5_CRYPT + +/* Define if you want to allow MD5 passwords */ +#undef HAVE_MD5_PASSWORDS + /* Define to 1 if you have the `memmem' function. */ #undef HAVE_MEMMEM /* Define to 1 if you have the `memmove' function. */ #undef HAVE_MEMMOVE +/* Define to 1 if you have the header file. */ +#undef HAVE_MEMORY_H + /* Define to 1 if you have the `memset_s' function. */ #undef HAVE_MEMSET_S @@ -960,6 +1056,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_NET_IF_TUN_H +/* Define to 1 if you have the header file. */ +#undef HAVE_NET_IF_UTUN_H + /* Define to 1 if you have the header file. */ #undef HAVE_NET_ROUTE_H @@ -978,6 +1077,9 @@ /* Define to 1 if you have the `nsleep' function. */ #undef HAVE_NSLEEP +/* Define to 1 if you have the `OCSP_sendreq_bio' function. */ +#undef HAVE_OCSP_SENDREQ_BIO + /* Define to 1 if you have the `ogetaddrinfo' function. */ #undef HAVE_OGETADDRINFO @@ -991,14 +1093,26 @@ /* Define to 1 if you have the `openpty' function. */ #undef HAVE_OPENPTY -/* as a macro */ -#undef HAVE_OPENSSL_ADD_ALL_ALGORITHMS +/* Define if your ssl headers are included with #include */ +#undef HAVE_OPENSSL + +/* Define to 1 if you have the `OPENSSL_cleanup' function. */ +#undef HAVE_OPENSSL_CLEANUP + +/* Define to 1 if you have the header file. */ +#undef HAVE_OPENSSL_EC_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_OPENSSL_ENGINE_H -/* Define to 1 if you have the `OpenSSL_version' function. */ -#undef HAVE_OPENSSL_VERSION +/* Define to 1 if you have the header file. */ +#undef HAVE_OPENSSL_FIPS_H -/* Define to 1 if you have the `OpenSSL_version_num' function. */ -#undef HAVE_OPENSSL_VERSION_NUM +/* Define to 1 if you have the `OPENSSL_init_crypto' function. */ +#undef HAVE_OPENSSL_INIT_CRYPTO + +/* Define to 1 if you have the `OPENSSL_version_major' function. */ +#undef HAVE_OPENSSL_VERSION_MAJOR /* Define if you have Digital Unix Security Integration Architecture */ #undef HAVE_OSF_SIA @@ -1069,6 +1183,9 @@ /* Define to 1 if you have the `raise' function. */ #undef HAVE_RAISE +/* Define to 1 if you have the `RAND_keep_random_devices_open' function. */ +#undef HAVE_RAND_KEEP_RANDOM_DEVICES_OPEN + /* Define to 1 if you have the `readpassphrase' function. */ #undef HAVE_READPASSPHRASE @@ -1082,9 +1199,6 @@ /* Define to 1 if you have the `reallocarray' function. */ #undef HAVE_REALLOCARRAY -/* Define to 1 if you have the `realpath' function. */ -#undef HAVE_REALPATH - /* Define to 1 if you have the `recallocarray' function. */ #undef HAVE_RECALLOCARRAY @@ -1103,8 +1217,23 @@ /* Define to 1 if you have the `RSA_generate_key_ex' function. */ #undef HAVE_RSA_GENERATE_KEY_EX -/* Define to 1 if you have the `RSA_get_default_method' function. */ -#undef HAVE_RSA_GET_DEFAULT_METHOD +/* Define to 1 if you have the `RSA_get0_key' function. */ +#undef HAVE_RSA_GET0_KEY + +/* Define to 1 if you have the `RSA_meth_get_pub_enc' function. */ +#undef HAVE_RSA_METH_GET_PUB_ENC + +/* Define to 1 if you have the `RSA_meth_new' function. */ +#undef HAVE_RSA_METH_NEW + +/* Define to 1 if you have the `RSA_meth_set1_name' function. */ +#undef HAVE_RSA_METH_SET1_NAME + +/* Define to 1 if you have the `RSA_meth_set_priv_enc' function. */ +#undef HAVE_RSA_METH_SET_PRIV_ENC + +/* Define to 1 if you have the `RSA_PKCS1_OpenSSL' function. */ +#undef HAVE_RSA_PKCS1_OPENSSL /* Define to 1 if you have the header file. */ #undef HAVE_SANDBOX_H @@ -1223,9 +1352,6 @@ /* Define to 1 if you have the `sigaction' function. */ #undef HAVE_SIGACTION -/* Define to 1 if the system has the type `sighandler_t'. */ -#undef HAVE_SIGHANDLER_T - /* Define to 1 if you have the `sigvec' function. */ #undef HAVE_SIGVEC @@ -1235,6 +1361,9 @@ /* define if you have size_t data type */ #undef HAVE_SIZE_T +/* Define to 1 if you have the 'sk_OPENSSL_STRING_new_null' function. */ +#undef HAVE_SK_OPENSSL_STRING_NEW_NULL + /* Define to 1 if you have the `snprintf' function. */ #undef HAVE_SNPRINTF @@ -1265,9 +1394,6 @@ /* Define to 1 if you have the header file. */ #undef HAVE_STDINT_H -/* Define to 1 if you have the header file. */ -#undef HAVE_STDIO_H - /* Define to 1 if you have the header file. */ #undef HAVE_STDLIB_H @@ -1358,9 +1484,6 @@ /* define if you have struct sockaddr_storage data type */ #undef HAVE_STRUCT_SOCKADDR_STORAGE -/* Define to 1 if `f_files' is a member of `struct statfs'. */ -#undef HAVE_STRUCT_STATFS_F_FILES - /* Define to 1 if `f_flags' is a member of `struct statfs'. */ #undef HAVE_STRUCT_STATFS_F_FLAGS @@ -1373,12 +1496,15 @@ /* Define to 1 if `st_mtime' is a member of `struct stat'. */ #undef HAVE_STRUCT_STAT_ST_MTIME -/* define if you have struct timespec */ +/* Define to 1 if the system has the type `struct timespec'. */ #undef HAVE_STRUCT_TIMESPEC -/* define if you have struct timeval */ +/* Define to 1 if the system has the type `struct timeval'. */ #undef HAVE_STRUCT_TIMEVAL +/* Define to 1 if the system has the type `struct x509_lookup_method_st'. */ +#undef HAVE_STRUCT_X509_LOOKUP_METHOD_ST + /* Define to 1 if you have the `swap32' function. */ #undef HAVE_SWAP32 @@ -1430,9 +1556,6 @@ /* Define if your system defines sys_nerr */ #undef HAVE_SYS_NERR -/* Define to 1 if you have the header file. */ -#undef HAVE_SYS_PARAM_H - /* Define to 1 if you have the header file. */ #undef HAVE_SYS_POLL_H @@ -1457,6 +1580,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_SYS_SELECT_H +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_STATFS_H + /* Define to 1 if you have the header file. */ #undef HAVE_SYS_STATVFS_H @@ -1520,6 +1646,9 @@ /* Define to 1 if you have the `timingsafe_bcmp' function. */ #undef HAVE_TIMINGSAFE_BCMP +/* Define to 1 if you have the `TLS_client_method' function. */ +#undef HAVE_TLS_CLIENT_METHOD + /* Define to 1 if you have the header file. */ #undef HAVE_TMPDIR_H @@ -1574,6 +1703,9 @@ /* Define to 1 if you have the `usleep' function. */ #undef HAVE_USLEEP +/* Define to 1 if you have the `UTF8_getc' function. */ +#undef HAVE_UTF8_GETC + /* Define to 1 if you have the header file. */ #undef HAVE_UTIL_H @@ -1586,9 +1718,6 @@ /* Define to 1 if you have the header file. */ #undef HAVE_UTIME_H -/* Define to 1 if you have the `utmpname' function. */ -#undef HAVE_UTMPNAME - /* Define to 1 if you have the `utmpxname' function. */ #undef HAVE_UTMPXNAME @@ -1634,6 +1763,45 @@ /* Define to 1 if you have the `wcwidth' function. */ #undef HAVE_WCWIDTH +/* Define to 1 if you have the `X509_CRL_get0_lastUpdate' function. */ +#undef HAVE_X509_CRL_GET0_LASTUPDATE + +/* Define to 1 if you have the `X509_get0_tbs_sigalg' function. */ +#undef HAVE_X509_GET0_TBS_SIGALG + +/* Define to 1 if you have the `X509_get_extension_flags' function. */ +#undef HAVE_X509_GET_EXTENSION_FLAGS + +/* Define to 1 if you have the `X509_get_key_usage' function. */ +#undef HAVE_X509_GET_KEY_USAGE + +/* Define to 1 if you have the `X509_LOOKUP_store' function. */ +#undef HAVE_X509_LOOKUP_STORE + +/* Define to 1 if you have the `X509_OBJECT_get0_X509' function. */ +#undef HAVE_X509_OBJECT_GET0_X509 + +/* Define to 1 if you have the `X509_OBJECT_new' function. */ +#undef HAVE_X509_OBJECT_NEW + +/* Define to 1 if you have the `X509_STORE_CTX_get0_param' function. */ +#undef HAVE_X509_STORE_CTX_GET0_PARAM + +/* Define to 1 if you have the `X509_STORE_CTX_get_by_subject' function. */ +#undef HAVE_X509_STORE_CTX_GET_BY_SUBJECT + +/* Define to 1 if you have the `X509_STORE_get0_objects' function. */ +#undef HAVE_X509_STORE_GET0_OBJECTS + +/* Define to 1 if you have the `X509_STORE_lock' function. */ +#undef HAVE_X509_STORE_LOCK + +/* Define to 1 if you have the `X509_STORE_set_verify_cb' function. */ +#undef HAVE_X509_STORE_SET_VERIFY_CB + +/* Define to 1 if you have the `X509_VERIFY_PARAM_get_time' function. */ +#undef HAVE_X509_VERIFY_PARAM_GET_TIME + /* Define to 1 if you have the `_getlong' function. */ #undef HAVE__GETLONG @@ -1685,6 +1853,12 @@ /* Define if pututxline updates lastlog too */ #undef LASTLOG_WRITE_PUTUTXLINE +/* Define if you want to enable LDAP queries */ +#undef LDAP_ENABLED + +/* Define if you want TCP Wrappers support */ +#undef LIBWRAP + /* Define to whatever link() returns for "not supported" if it doesn't return EOPNOTSUPP. */ #undef LINK_OPNOTSUPP_ERRNO @@ -1713,7 +1887,7 @@ /* Set this to your mail directory if you do not have _PATH_MAILDIR */ #undef MAIL_DIRECTORY -/* Need setpgrp to for controlling tty */ +/* Need setpgrp to acquire controlling tty */ #undef NEED_SETPGRP /* compiler does not accept __attribute__ on prototype args */ @@ -1722,21 +1896,21 @@ /* compiler does not accept __attribute__ on return types */ #undef NO_ATTRIBUTE_ON_RETURN_TYPE -/* SA_RESTARTed signals do no interrupt select */ -#undef NO_SA_RESTART - /* Define to disable UID restoration test */ #undef NO_UID_RESTORATION_TEST /* Define if X11 doesn't support AF_UNIX sockets on that system */ #undef NO_X11_UNIX_SOCKETS -/* Define if EVP_DigestUpdate returns void */ -#undef OPENSSL_EVP_DIGESTUPDATE_VOID +/* Define as const if openpty declare const arguments */ +#undef OPENPTY_CONST_ARG /* OpenSSL has ECC */ #undef OPENSSL_HAS_ECC +/* libcrypto has ed25519 support */ +#undef OPENSSL_HAS_ED25519 + /* libcrypto has NID_X9_62_prime256v1 */ #undef OPENSSL_HAS_NISTP256 @@ -1746,6 +1920,12 @@ /* libcrypto has NID_secp521r1 */ #undef OPENSSL_HAS_NISTP521 +/* libcrypto has EVP AES CTR */ +#undef OPENSSL_HAVE_EVPCTR + +/* libcrypto has EVP AES GCM */ +#undef OPENSSL_HAVE_EVPGCM + /* libcrypto is missing AES 192 and 256 bit functions */ #undef OPENSSL_LOBOTOMISED_AES @@ -1813,9 +1993,6 @@ /* setrlimit RLIMIT_FSIZE works */ #undef SANDBOX_SKIP_RLIMIT_FSIZE -/* define if setrlimit RLIMIT_NOFILE breaks things */ -#undef SANDBOX_SKIP_RLIMIT_NOFILE - /* Sandbox using Solaris/Illumos privileges */ #undef SANDBOX_SOLARIS @@ -1843,7 +2020,7 @@ /* The size of `time_t', as computed by sizeof. */ #undef SIZEOF_TIME_T -/* Define as const if snprintf() can declare const char *fmt */ +/* Define as const if broken snprintf() declare const char *fmt */ #undef SNPRINTF_CONST /* sockaddr_in has sin_len */ @@ -1853,7 +2030,10 @@ bsd-setproctitle.c */ #undef SPT_TYPE -/* Define if sshd somehow reacquires a controlling TTY after setsid() */ +/* Specify location of ssh CA root */ +#undef SSHCADIR + +/* Define to 1 if sshd somehow reacquires a controlling TTY after setsid() */ #undef SSHD_ACQUIRES_CTTY /* sshd PAM service name */ @@ -1865,8 +2045,8 @@ /* Use audit debugging module */ #undef SSH_AUDIT_EVENTS -/* Windows is sensitive to read buffer size */ -#undef SSH_IOBUFSZ +/* Define if you want to validate X.509 certificates with OCSP */ +#undef SSH_OCSP_ENABLED /* non-privileged user for privilege separation */ #undef SSH_PRIVSEP_USER @@ -1874,6 +2054,9 @@ /* Use tunnel device compatibility to OpenBSD */ #undef SSH_TUN_COMPAT_AF +/* Open tunnel devices the Darwin way */ +#undef SSH_TUN_DARWIN + /* Open tunnel devices the FreeBSD way */ #undef SSH_TUN_FREEBSD @@ -1889,11 +2072,12 @@ /* Prepend the address family to IP tunnel traffic */ #undef SSH_TUN_PREPEND_AF -/* Define to 1 if all of the C90 standard headers exist (not just the ones - required in a freestanding environment). This macro is provided for - backward compatibility; new code need not use it. */ +/* Define to 1 if you have the ANSI C header files. */ #undef STDC_HEADERS +/* Define as const if store find method uses const criteria */ +#undef STORE_FIND_CRITERION_CONST + /* Define if you want a different $PATH for the superuser */ #undef SUPERUSER_PATH @@ -1927,6 +2111,9 @@ /* Enable OpenSSL engine support */ #undef USE_OPENSSL_ENGINE +/* Use OpenSSL STORE functionality */ +#undef USE_OPENSSL_STORE2 + /* Define if you want to enable PAM support */ #undef USE_PAM @@ -1942,11 +2129,8 @@ /* Define if you have Solaris projects */ #undef USE_SOLARIS_PROJECTS -/* compiler variable declarations after code */ -#undef VARIABLE_DECLARATION_AFTER_CODE - -/* compiler supports variable length arrays */ -#undef VARIABLE_LENGTH_ARRAYS +/* Define to 1 if you have the `statfs' structure */ +#undef USE_STRUCT_STATFS /* Define if you shouldn't strip 'tty' from your ttyname in [uw]tmp */ #undef WITH_ABBREV_NO_TTY @@ -1991,6 +2175,11 @@ /* Define if xauth is found in your path */ #undef XAUTH_PATH +/* Enable large inode numbers on Mac OS X 10.5. */ +#ifndef _DARWIN_USE_64_BIT_INODE +# define _DARWIN_USE_64_BIT_INODE 1 +#endif + /* Number of bits in a file offset, on hosts where this is settable. */ #undef _FILE_OFFSET_BITS diff -ruN openssh-9.4p1/config.sub openssh-9.4p1+x509-14.2.1/config.sub --- openssh-9.4p1/config.sub 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/config.sub 2023-08-20 10:07:00.000000000 +0300 @@ -1,10 +1,10 @@ #! /bin/sh # Configuration validation subroutine script. -# Copyright 1992-2022 Free Software Foundation, Inc. +# Copyright 1992-2023 Free Software Foundation, Inc. # shellcheck disable=SC2006,SC2268 # see below for rationale -timestamp='2022-09-17' +timestamp='2023-07-31' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by @@ -76,13 +76,13 @@ version="\ GNU config.sub ($timestamp) -Copyright 1992-2022 Free Software Foundation, Inc. +Copyright 1992-2023 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" -Try \`$me --help' for more information." +Try '$me --help' for more information." # Parse command line while test $# -gt 0 ; do @@ -130,7 +130,7 @@ # Separate into logical components for further validation case $1 in *-*-*-*-*) - echo Invalid configuration \`"$1"\': more than four components >&2 + echo "Invalid configuration '$1': more than four components" >&2 exit 1 ;; *-*-*-*) @@ -145,7 +145,8 @@ nto-qnx* | linux-* | uclinux-uclibc* \ | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* \ | netbsd*-eabi* | kopensolaris*-gnu* | cloudabi*-eabi* \ - | storm-chaos* | os2-emx* | rtmk-nova* | managarm-*) + | storm-chaos* | os2-emx* | rtmk-nova* | managarm-* \ + | windows-* ) basic_machine=$field1 basic_os=$maybe_os ;; @@ -943,7 +944,7 @@ EOF IFS=$saved_IFS ;; - # We use `pc' rather than `unknown' + # We use 'pc' rather than 'unknown' # because (1) that's what they normally are, and # (2) the word "unknown" tends to confuse beginning users. i*86 | x86_64) @@ -1075,7 +1076,7 @@ pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) cpu=i586 ;; - pentiumpro-* | p6-* | 6x86-* | athlon-* | athalon_*-*) + pentiumpro-* | p6-* | 6x86-* | athlon-* | athlon_*-*) cpu=i686 ;; pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) @@ -1205,6 +1206,7 @@ | i370 | i*86 | i860 | i960 | ia16 | ia64 \ | ip2k | iq2000 \ | k1om \ + | kvx \ | le32 | le64 \ | lm32 \ | loongarch32 | loongarch64 \ @@ -1213,31 +1215,7 @@ | m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x \ | m88110 | m88k | maxq | mb | mcore | mep | metag \ | microblaze | microblazeel \ - | mips | mipsbe | mipseb | mipsel | mipsle \ - | mips16 \ - | mips64 | mips64eb | mips64el \ - | mips64octeon | mips64octeonel \ - | mips64orion | mips64orionel \ - | mips64r5900 | mips64r5900el \ - | mips64vr | mips64vrel \ - | mips64vr4100 | mips64vr4100el \ - | mips64vr4300 | mips64vr4300el \ - | mips64vr5000 | mips64vr5000el \ - | mips64vr5900 | mips64vr5900el \ - | mipsisa32 | mipsisa32el \ - | mipsisa32r2 | mipsisa32r2el \ - | mipsisa32r3 | mipsisa32r3el \ - | mipsisa32r5 | mipsisa32r5el \ - | mipsisa32r6 | mipsisa32r6el \ - | mipsisa64 | mipsisa64el \ - | mipsisa64r2 | mipsisa64r2el \ - | mipsisa64r3 | mipsisa64r3el \ - | mipsisa64r5 | mipsisa64r5el \ - | mipsisa64r6 | mipsisa64r6el \ - | mipsisa64sb1 | mipsisa64sb1el \ - | mipsisa64sr71k | mipsisa64sr71kel \ - | mipsr5900 | mipsr5900el \ - | mipstx39 | mipstx39el \ + | mips* \ | mmix \ | mn10200 | mn10300 \ | moxie \ @@ -1285,7 +1263,7 @@ ;; *) - echo Invalid configuration \`"$1"\': machine \`"$cpu-$vendor"\' not recognized 1>&2 + echo "Invalid configuration '$1': machine '$cpu-$vendor' not recognized" 1>&2 exit 1 ;; esac @@ -1732,7 +1710,7 @@ | hpux* | unos* | osf* | luna* | dgux* | auroraux* | solaris* \ | sym* | plan9* | psp* | sim* | xray* | os68k* | v88r* \ | hiux* | abug | nacl* | netware* | windows* \ - | os9* | macos* | osx* | ios* \ + | os9* | macos* | osx* | ios* | tvos* | watchos* \ | mpw* | magic* | mmixware* | mon960* | lnews* \ | amigaos* | amigados* | msdos* | newsos* | unicos* | aof* \ | aos* | aros* | cloudabi* | sortix* | twizzler* \ @@ -1758,7 +1736,7 @@ | onefs* | tirtos* | phoenix* | fuchsia* | redox* | bme* \ | midnightbsd* | amdhsa* | unleashed* | emscripten* | wasi* \ | nsk* | powerunix* | genode* | zvmoe* | qnx* | emx* | zephyr* \ - | fiwix* | mlibc* ) + | fiwix* | mlibc* | cos* | mbr* ) ;; # This one is extra strict with allowed versions sco3.2v2 | sco3.2v[4-9]* | sco5v6*) @@ -1766,11 +1744,11 @@ ;; none) ;; - kernel* ) + kernel* | msvc* ) # Restricted further below ;; *) - echo Invalid configuration \`"$1"\': OS \`"$os"\' not recognized 1>&2 + echo "Invalid configuration '$1': OS '$os' not recognized" 1>&2 exit 1 ;; esac @@ -1785,18 +1763,24 @@ ;; managarm-mlibc* | managarm-kernel* ) ;; + windows*-gnu* | windows*-msvc*) + ;; -dietlibc* | -newlib* | -musl* | -relibc* | -uclibc* | -mlibc* ) # These are just libc implementations, not actual OSes, and thus # require a kernel. - echo "Invalid configuration \`$1': libc \`$os' needs explicit kernel." 1>&2 + echo "Invalid configuration '$1': libc '$os' needs explicit kernel." 1>&2 exit 1 ;; -kernel* ) - echo "Invalid configuration \`$1': \`$os' needs explicit kernel." 1>&2 + echo "Invalid configuration '$1': '$os' needs explicit kernel." 1>&2 exit 1 ;; *-kernel* ) - echo "Invalid configuration \`$1': \`$kernel' does not support \`$os'." 1>&2 + echo "Invalid configuration '$1': '$kernel' does not support '$os'." 1>&2 + exit 1 + ;; + *-msvc* ) + echo "Invalid configuration '$1': '$os' needs 'windows'." 1>&2 exit 1 ;; kfreebsd*-gnu* | kopensolaris*-gnu*) @@ -1809,11 +1793,15 @@ ;; *-eabi* | *-gnueabi*) ;; + none-coff* | none-elf*) + # None (no kernel, i.e. freestanding / bare metal), + # can be paired with an output format "OS" + ;; -*) # Blank kernel with real OS is always fine. ;; *-*) - echo "Invalid configuration \`$1': Kernel \`$kernel' not known to work with OS \`$os'." 1>&2 + echo "Invalid configuration '$1': Kernel '$kernel' not known to work with OS '$os'." 1>&2 exit 1 ;; esac diff -ruN openssh-9.4p1/configure openssh-9.4p1+x509-14.2.1/configure --- openssh-9.4p1/configure 2023-08-10 04:11:59.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/configure 2023-08-20 10:07:02.000000000 +0300 @@ -1,12 +1,11 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.71 for OpenSSH Portable. +# Generated by GNU Autoconf 2.69 for PKIX-SSH 14.2.1. # -# Report bugs to . +# Report bugs to . # # -# Copyright (C) 1992-1996, 1998-2017, 2020-2021 Free Software Foundation, -# Inc. +# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. # # # This configure script is free software; the Free Software Foundation @@ -17,16 +16,14 @@ # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh -as_nop=: -if test ${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1 -then : +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST -else $as_nop +else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( @@ -36,46 +33,46 @@ fi - -# Reset variables that may have inherited troublesome values from -# the environment. - -# IFS needs to be set, to space, tab, and newline, in precisely that order. -# (If _AS_PATH_WALK were called with IFS unset, it would have the -# side effect of setting IFS to empty, thus disabling word splitting.) -# Quoting is to prevent editors from complaining about space-tab. as_nl=' ' export as_nl -IFS=" "" $as_nl" - -PS1='$ ' -PS2='> ' -PS4='+ ' - -# Ensure predictable behavior from utilities with locale-dependent output. -LC_ALL=C -export LC_ALL -LANGUAGE=C -export LANGUAGE - -# We cannot yet rely on "unset" to work, but we need these variables -# to be unset--not just set to an empty or harmless value--now, to -# avoid bugs in old shells (e.g. pre-3.0 UWIN ksh). This construct -# also avoids known problems related to "unset" and subshell syntax -# in other old shells (e.g. bash 2.01 and pdksh 5.2.14). -for as_var in BASH_ENV ENV MAIL MAILPATH CDPATH -do eval test \${$as_var+y} \ - && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : -done - -# Ensure that fds 0, 1, and 2 are open. -if (exec 3>&0) 2>/dev/null; then :; else exec 0&1) 2>/dev/null; then :; else exec 1>/dev/null; fi -if (exec 3>&2) ; then :; else exec 2>/dev/null; fi +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi # The user is always right. -if ${PATH_SEPARATOR+false} :; then +if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || @@ -84,6 +81,13 @@ fi +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( @@ -92,12 +96,8 @@ for as_dir in $PATH do IFS=$as_save_IFS - case $as_dir in #((( - '') as_dir=./ ;; - */) ;; - *) as_dir=$as_dir/ ;; - esac - test -r "$as_dir$0" && as_myself=$as_dir$0 && break + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS @@ -109,10 +109,30 @@ as_myself=$0 fi if test ! -f "$as_myself"; then - printf "%s\n" "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH # Use a proper internal environment variable to ensure we don't fall # into an infinite loop, continuously re-executing ourselves. @@ -134,22 +154,20 @@ exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. -printf "%s\n" "$0: could not re-execute with $CONFIG_SHELL" >&2 -exit 255 +$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 +as_fn_exit 255 fi # We don't want this to propagate to other subprocesses. { _as_can_reexec=; unset _as_can_reexec;} if test "x$CONFIG_SHELL" = x; then - as_bourne_compatible="as_nop=: -if test \${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1 -then : + as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which # is contrary to our usage. Disable this feature. alias -g '\${1+\"\$@\"}'='\"\$@\"' setopt NO_GLOB_SUBST -else \$as_nop +else case \`(set -o) 2>/dev/null\` in #( *posix*) : set -o posix ;; #( @@ -169,53 +187,42 @@ as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } -if ( set x; as_fn_ret_success y && test x = \"\$1\" ) -then : +if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : -else \$as_nop +else exitcode=1; echo positional parameters were not saved. fi test x\$exitcode = x0 || exit 1 -blah=\$(echo \$(echo blah)) -test x\"\$blah\" = xblah || exit 1 test -x / || exit 1" as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 test \$(( 1 + 1 )) = 2 || exit 1" - if (eval "$as_required") 2>/dev/null -then : + if (eval "$as_required") 2>/dev/null; then : as_have_required=yes -else $as_nop +else as_have_required=no fi - if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null -then : + if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : -else $as_nop +else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_found=false for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS - case $as_dir in #((( - '') as_dir=./ ;; - */) ;; - *) as_dir=$as_dir/ ;; - esac + test -z "$as_dir" && as_dir=. as_found=: case $as_dir in #( /*) for as_base in sh bash ksh sh5; do # Try only shells that exist, to save several forks. - as_shell=$as_dir$as_base + as_shell=$as_dir/$as_base if { test -f "$as_shell" || test -f "$as_shell.exe"; } && - as_run=a "$as_shell" -c "$as_bourne_compatible""$as_required" 2>/dev/null -then : + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : CONFIG_SHELL=$as_shell as_have_required=yes - if as_run=a "$as_shell" -c "$as_bourne_compatible""$as_suggested" 2>/dev/null -then : + if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : break 2 fi fi @@ -223,21 +230,14 @@ esac as_found=false done -IFS=$as_save_IFS -if $as_found -then : - -else $as_nop - if { test -f "$SHELL" || test -f "$SHELL.exe"; } && - as_run=a "$SHELL" -c "$as_bourne_compatible""$as_required" 2>/dev/null -then : +$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : CONFIG_SHELL=$SHELL as_have_required=yes -fi -fi +fi; } +IFS=$as_save_IFS - if test "x$CONFIG_SHELL" != x -then : + if test "x$CONFIG_SHELL" != x; then : export CONFIG_SHELL # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also @@ -255,23 +255,22 @@ exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. -printf "%s\n" "$0: could not re-execute with $CONFIG_SHELL" >&2 +$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 exit 255 fi - if test x$as_have_required = xno -then : - printf "%s\n" "$0: This script requires a shell more modern than all" - printf "%s\n" "$0: the shells that I found on your system." - if test ${ZSH_VERSION+y} ; then - printf "%s\n" "$0: In particular, zsh $ZSH_VERSION has bugs and should" - printf "%s\n" "$0: be upgraded to zsh 4.3.4 or later." + if test x$as_have_required = xno; then : + $as_echo "$0: This script requires a shell more modern than all" + $as_echo "$0: the shells that I found on your system." + if test x${ZSH_VERSION+set} = xset ; then + $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" + $as_echo "$0: be upgraded to zsh 4.3.4 or later." else - printf "%s\n" "$0: Please tell bug-autoconf@gnu.org and -$0: openssh-unix-dev@mindrot.org about your system, -$0: including any error possibly output before this -$0: message. Then install a modern shell, or manually run -$0: the script under such a shell if you do have one." + $as_echo "$0: Please tell bug-autoconf@gnu.org and ssh_x509@roumenpetrov.info +$0: about your system, including any error possibly output +$0: before this message. Then install a modern shell, or +$0: manually run the script under such a shell if you do +$0: have one." fi exit 1 fi @@ -295,7 +294,6 @@ } as_unset=as_fn_unset - # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. @@ -313,14 +311,6 @@ as_fn_set_status $1 exit $1 } # as_fn_exit -# as_fn_nop -# --------- -# Do nothing but, unlike ":", preserve the value of $?. -as_fn_nop () -{ - return $? -} -as_nop=as_fn_nop # as_fn_mkdir_p # ------------- @@ -335,7 +325,7 @@ as_dirs= while :; do case $as_dir in #( - *\'*) as_qdir=`printf "%s\n" "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" @@ -344,7 +334,7 @@ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || -printf "%s\n" X"$as_dir" | +$as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q @@ -383,13 +373,12 @@ # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. -if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null -then : +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' -else $as_nop +else as_fn_append () { eval $1=\$$1\$2 @@ -401,27 +390,18 @@ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. -if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null -then : +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' -else $as_nop +else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith -# as_fn_nop -# --------- -# Do nothing but, unlike ":", preserve the value of $?. -as_fn_nop () -{ - return $? -} -as_nop=as_fn_nop # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- @@ -433,9 +413,9 @@ as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi - printf "%s\n" "$as_me: error: $2" >&2 + $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error @@ -462,7 +442,7 @@ $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || -printf "%s\n" X/"$0" | +$as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q @@ -506,7 +486,7 @@ s/-\n.*// ' >$as_me.lineno && chmod +x "$as_me.lineno" || - { printf "%s\n" "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } + { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } # If we had to re-execute with $CONFIG_SHELL, we're ensured to have # already done that, so ensure we don't try to do so again and fall @@ -520,10 +500,6 @@ exit } - -# Determine whether it's possible to make 'echo' print without a newline. -# These variables are no longer used directly by Autoconf, but are AC_SUBSTed -# for compatibility with existing Makefiles. ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) @@ -537,13 +513,6 @@ ECHO_N='-n';; esac -# For backward compatibility with old third-party macros, we provide -# the shell variables $as_echo and $as_echo_n. New code should use -# AS_ECHO(["message"]) and AS_ECHO_N(["message"]), respectively. -as_echo='printf %s\n' -as_echo_n='printf %s' - - rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file @@ -609,55 +578,65 @@ MAKEFLAGS= # Identity of this package. -PACKAGE_NAME='OpenSSH' +PACKAGE_NAME='PKIX-SSH' PACKAGE_TARNAME='openssh' -PACKAGE_VERSION='Portable' -PACKAGE_STRING='OpenSSH Portable' -PACKAGE_BUGREPORT='openssh-unix-dev@mindrot.org' -PACKAGE_URL='' +PACKAGE_VERSION='14.2.1' +PACKAGE_STRING='PKIX-SSH 14.2.1' +PACKAGE_BUGREPORT='ssh_x509@roumenpetrov.info' +PACKAGE_URL='https://roumenpetrov.info/secsh' ac_unique_file="ssh.c" # Factoring default headers for most tests. ac_includes_default="\ -#include -#ifdef HAVE_STDIO_H -# include +#include +#ifdef HAVE_SYS_TYPES_H +# include #endif -#ifdef HAVE_STDLIB_H +#ifdef HAVE_SYS_STAT_H +# include +#endif +#ifdef STDC_HEADERS # include +# include +#else +# ifdef HAVE_STDLIB_H +# include +# endif #endif #ifdef HAVE_STRING_H +# if !defined STDC_HEADERS && defined HAVE_MEMORY_H +# include +# endif # include #endif +#ifdef HAVE_STRINGS_H +# include +#endif #ifdef HAVE_INTTYPES_H # include #endif #ifdef HAVE_STDINT_H # include #endif -#ifdef HAVE_STRINGS_H -# include -#endif -#ifdef HAVE_SYS_TYPES_H -# include -#endif -#ifdef HAVE_SYS_STAT_H -# include -#endif #ifdef HAVE_UNISTD_H # include #endif" -ac_header_c_list= ac_subst_vars='LTLIBOBJS -CFLAGS_NOPIE -LDFLAGS_NOPIE -DEPEND UNSUPPORTED_ALGORITHMS TEST_MALLOC_OPTIONS TEST_SSH_UTF8 TEST_SSH_IPV6 piddir +LDAPADD +LDAP_OFF +LDAP_ON +LDAP_LIBS +LDAP_CPPFLAGS +LDAP_LDFLAGS +LDAP_SYSCONFDIR +LDAP_LIBEXECDIR +LDAP_BINDIR user_path mansubdir MANTYPE @@ -665,20 +644,31 @@ STRIP_OPT xauth_path PRIVSEP_PATH -CHANNELLIBS +OCSP_OFF +OCSP_ON +LIBOCSP K5LIBS GSSLIBS KRB5CONF SSHDLIBS SSH_PRIVSEP_USER -LIBFIDO2 -SK_DUMMY_LIBRARY -OPENSSL_BIN -openssl_bin -PICFLAG +FIPSHMAC +FIPS_LIBS +OPENSSL_FIPS_MODE +FIPSLD_CC +USE_OPENSSL_STORE2 +COMMENT_OUT_ED25519 +COMMENT_OUT_ECC521 +COMMENT_OUT_ECC384 +COMMENT_OUT_ECC256 +COMMENT_OUT_ECC +COMMENT_OUT_DSA +sshcadir LIBEDIT -LDNSCONFIG LIBOBJS +TEST_SHELL +XDEPLIBS +XLDFLAGS LD PATH_PASSWD_PROG STARTUP_SCRIPT_SHELL @@ -686,27 +676,31 @@ PATH_USERADD_PROG PATH_GROUPADD_PROG MANFMT -TEST_SHELL PKGCONFIG MANDOC NROFF GROFF SH -TEST_MINUS_S_SH SED KILL CAT ac_ct_AR AR -MKDIR_P -EGREP -GREP INSTALL_DATA INSTALL_SCRIPT INSTALL_PROGRAM RANLIB -CPP AWK +EGREP +GREP +CPP +OBJEXT +EXEEXT +ac_ct_CC +CPPFLAGS +LDFLAGS +CFLAGS +CC host_os host_vendor host_cpu @@ -715,13 +709,6 @@ build_vendor build_cpu build -OBJEXT -EXEEXT -ac_ct_CC -CPPFLAGS -LDFLAGS -CFLAGS -CC target_alias host_alias build_alias @@ -741,7 +728,6 @@ docdir oldincludedir includedir -runstatedir localstatedir sharedstatedir sysconfdir @@ -782,16 +768,18 @@ with_osfsia with_zlib with_zlib_version_check +with_tcp_wrappers with_ldns with_libedit with_audit with_pie enable_pkcs11 -enable_security_key -with_security_key_builtin with_ssl_dir with_openssl_header_check with_ssl_engine +enable_ocsp +with_sshca_dir +enable_openssl_fips with_prngd_port with_prngd_socket with_pam @@ -805,6 +793,7 @@ enable_strip with_maildir with_mantype +with_md5_passwords with_shadow with_ipaddr_display enable_etc_default_login @@ -812,6 +801,14 @@ with_superuser_path with_4in6 with_bsd_auth +enable_ldap +with_ldap_prefix +with_ldap_bindir +with_ldap_libexecdir +with_ldap_sysconfdir +with_ldap_libdir +with_ldap_includedir +with_ldap_libs with_pid_dir enable_lastlog enable_utmp @@ -831,7 +828,9 @@ LDFLAGS LIBS CPPFLAGS -CPP' +CPP +MANFMT +FIPSLD_CC' # Initialize some variables set by options. @@ -870,7 +869,6 @@ sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' -runstatedir='${localstatedir}/run' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' @@ -900,6 +898,8 @@ *) ac_optarg=yes ;; esac + # Accept the important Cygnus configure options, so we can diagnose typos. + case $ac_dashdash$ac_option in --) ac_dashdash=yes ;; @@ -940,9 +940,9 @@ ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && - as_fn_error $? "invalid feature name: \`$ac_useropt'" + as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt - ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'` + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" @@ -966,9 +966,9 @@ ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && - as_fn_error $? "invalid feature name: \`$ac_useropt'" + as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt - ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'` + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" @@ -1121,15 +1121,6 @@ | -silent | --silent | --silen | --sile | --sil) silent=yes ;; - -runstatedir | --runstatedir | --runstatedi | --runstated \ - | --runstate | --runstat | --runsta | --runst | --runs \ - | --run | --ru | --r) - ac_prev=runstatedir ;; - -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \ - | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \ - | --run=* | --ru=* | --r=*) - runstatedir=$ac_optarg ;; - -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ @@ -1179,9 +1170,9 @@ ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && - as_fn_error $? "invalid package name: \`$ac_useropt'" + as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt - ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'` + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" @@ -1195,9 +1186,9 @@ ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && - as_fn_error $? "invalid package name: \`$ac_useropt'" + as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt - ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'` + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" @@ -1241,9 +1232,9 @@ *) # FIXME: should be removed in autoconf 3.0. - printf "%s\n" "$as_me: WARNING: you should use --build, --host, --target" >&2 + $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && - printf "%s\n" "$as_me: WARNING: invalid host type: $ac_option" >&2 + $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" ;; @@ -1259,7 +1250,7 @@ case $enable_option_checking in no) ;; fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; - *) printf "%s\n" "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; + *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; esac fi @@ -1267,7 +1258,7 @@ for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ - libdir localedir mandir runstatedir + libdir localedir mandir do eval ac_val=\$$ac_var # Remove trailing slashes. @@ -1323,7 +1314,7 @@ X"$as_myself" : 'X\(//\)[^/]' \| \ X"$as_myself" : 'X\(//\)$' \| \ X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || -printf "%s\n" X"$as_myself" | +$as_echo X"$as_myself" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q @@ -1380,7 +1371,7 @@ # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures OpenSSH Portable to adapt to many kinds of systems. +\`configure' configures PKIX-SSH 14.2.1 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1420,7 +1411,6 @@ --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] - --runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] @@ -1446,7 +1436,7 @@ if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of OpenSSH Portable:";; + short | recursive ) echo "Configuration of PKIX-SSH 14.2.1:";; esac cat <<\_ACEOF @@ -1455,26 +1445,29 @@ --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) --enable-FEATURE[=ARG] include FEATURE [ARG=yes] --disable-largefile omit support for large files - --disable-pkcs11 disable PKCS#11 support code [no] - --disable-security-key disable U2F/FIDO support code no + --disable-pkcs11 disable PKCS#11 support code [=no] + --disable-ocsp Disable OCSP validation + --enable-openssl-fips Enable build with FIPS-enabled openssl --disable-strip Disable calling strip(1) on install --disable-etc-default-login Disable using PATH from /etc/default/login no + --enable-ldap Enable LDAP queries --disable-lastlog disable use of lastlog even if detected no --disable-utmp disable use of utmp even if detected no --disable-utmpx disable use of utmpx even if detected no --disable-wtmp disable use of wtmp even if detected no --disable-wtmpx disable use of wtmpx even if detected no --disable-libutil disable use of libutil (login() etc.) no - --disable-pututline disable use of pututline() etc. (uwtmp) no + --disable-pututline disable use of pututline() etc. ([uw]tmp) [no] --disable-pututxline disable use of pututxline() etc. (uwtmpx) no Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) - --without-openssl Disable use of OpenSSL; use only limited internal crypto **EXPERIMENTAL** + --without-openssl Disable use of OpenSSL; use only limited internal + crypto **EXPERIMENTAL** --without-stackprotect Don't use compiler's stack protection --without-hardening Don't use toolchain hardening flags - --without-rpath Disable auto-added -R linker paths + --with-rpath=FLAG Use runtime library search path (by default -R flag) --with-cflags Specify additional flags to pass to compiler --with-cflags-after Specify additional flags to pass to compiler after configure --with-cppflags Specify additional flags to pass to preprocessor @@ -1486,16 +1479,18 @@ --with-solaris-projects Enable Solaris projects (experimental) --with-solaris-privs Enable Solaris/Illumos privileges (experimental) --with-osfsia Enable Digital Unix SIA - --with-zlib=PATH Use zlib in PATH + --with-zlib[=PATH] Use zlib for compression(optionally in PATH) --without-zlib-version-check Disable zlib version check + --with-tcp-wrappers[=PATH] + Enable tcpwrappers support (optionally in PATH) --with-ldns[=PATH] Use ldns for DNSSEC support (optionally in PATH) --with-libedit[=PATH] Enable libedit support for sftp --with-audit=module Enable audit support (modules=debug,bsm,linux) --with-pie Build Position Independent Executables if possible - --with-security-key-builtin include builtin U2F/FIDO support --with-ssl-dir=PATH Specify path to OpenSSL installation --without-openssl-header-check Disable OpenSSL version consistency check --with-ssl-engine Enable OpenSSL (hardware) ENGINE support + --with-sshca-dir=DIR Specify location of ssh CA root --with-prngd-port=PORT read entropy from PRNGD/EGD TCP localhost:PORT --with-prngd-socket=FILE read entropy from PRNGD/EGD socket FILE (default=/var/run/egd-pool) --with-pam Enable PAM support @@ -1503,17 +1498,33 @@ --with-privsep-user=user Specify non-privileged user for privilege separation --with-sandbox=style Specify privilege separation sandbox (no, capsicum, darwin, rlimit, seccomp_filter, systrace, pledge) --with-selinux Enable SELinux support - --with-kerberos5=PATH Enable Kerberos 5 support + --with-kerberos5[=PATH] Enable Kerberos 5 support --with-privsep-path=xxx Path for privilege separation chroot (default=/var/empty) --with-xauth=PATH Specify path to xauth program --with-maildir=/path/to/mail Specify your system mail directory --with-mantype=man|cat|doc Set man page type + --with-md5-passwords Enable use of MD5 passwords --without-shadow Disable shadow password support --with-ipaddr-display Use ip address instead of hostname in $DISPLAY --with-default-path= Specify default $PATH environment for server --with-superuser-path= Specify different path for super-user --with-4in6 Check for and convert IPv4 in IPv6 mapped addresses --with-bsd-auth Enable BSD auth support + --with-ldap-prefix=PATH Prefix where LDAP is installed (optional) + --with-ldap-bindir=PATH Prefix where LDAP user executables are installed + (optional) + --with-ldap-libexecdir=PATH + Prefix where LDAP program executables are installed + (optional) + --with-ldap-sysconfdir=PATH + Prefix where LDAP single-machine data are installed + (optional) + --with-ldap-libdir=PATH Prefix where LDAP libraries are installed (optional) + --with-ldap-includedir=PATH + Prefix where LDAP header files are installed + (optional) + --with-ldap-libs=LIBS Specify LDAP libraries to link with (default is + -lldap -llber -lssl -lcrypto) --with-pid-dir=PATH Specify location of sshd.pid file --with-lastlog=FILE|DIR specify lastlog location common locations @@ -1526,11 +1537,14 @@ CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if you have headers in a nonstandard directory CPP C preprocessor + MANFMT manpage formatter + FIPSLD_CC actual compiler to be used by openssl fips compiler Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. -Report bugs to . +Report bugs to . +PKIX-SSH home page: . _ACEOF ac_status=$? fi @@ -1546,9 +1560,9 @@ case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) - ac_dir_suffix=/`printf "%s\n" "$ac_dir" | sed 's|^\.[\\/]||'` + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. - ac_top_builddir_sub=`printf "%s\n" "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; @@ -1576,8 +1590,7 @@ ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix cd "$ac_dir" || { ac_status=$?; continue; } - # Check for configure.gnu first; this name is used for a wrapper for - # Metaconfig's "Configure" on case-insensitive file systems. + # Check for guested configure. if test -f "$ac_srcdir/configure.gnu"; then echo && $SHELL "$ac_srcdir/configure.gnu" --help=recursive @@ -1585,7 +1598,7 @@ echo && $SHELL "$ac_srcdir/configure" --help=recursive else - printf "%s\n" "$as_me: WARNING: no configuration information is in $ac_dir" >&2 + $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 fi || ac_status=$? cd "$ac_pwd" || { ac_status=$?; break; } done @@ -1594,10 +1607,10 @@ test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -OpenSSH configure Portable -generated by GNU Autoconf 2.71 +PKIX-SSH configure 14.2.1 +generated by GNU Autoconf 2.69 -Copyright (C) 2021 Free Software Foundation, Inc. +Copyright (C) 2012 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF @@ -1614,14 +1627,14 @@ ac_fn_c_try_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - rm -f conftest.$ac_objext conftest.beam + rm -f conftest.$ac_objext if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -printf "%s\n" "$ac_try_echo"; } >&5 +$as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>conftest.err ac_status=$? if test -s conftest.err; then @@ -1629,15 +1642,14 @@ cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi - printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err - } && test -s conftest.$ac_objext -then : + } && test -s conftest.$ac_objext; then : ac_retval=0 -else $as_nop - printf "%s\n" "$as_me: failed program was:" >&5 +else + $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 @@ -1649,8 +1661,8 @@ # ac_fn_c_try_run LINENO # ---------------------- -# Try to run conftest.$ac_ext, and return whether this succeeded. Assumes that -# executables *can* be run. +# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes +# that executables *can* be run. ac_fn_c_try_run () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack @@ -1660,26 +1672,25 @@ *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -printf "%s\n" "$ac_try_echo"; } >&5 +$as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? - printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -printf "%s\n" "$ac_try_echo"; } >&5 +$as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? - printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; } -then : + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then : ac_retval=0 -else $as_nop - printf "%s\n" "$as_me: program exited with status $ac_status" >&5 - printf "%s\n" "$as_me: failed program was:" >&5 +else + $as_echo "$as_me: program exited with status $ac_status" >&5 + $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=$ac_status @@ -1690,39 +1701,6 @@ } # ac_fn_c_try_run -# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES -# ------------------------------------------------------- -# Tests whether HEADER exists and can be compiled using the include files in -# INCLUDES, setting the cache variable VAR accordingly. -ac_fn_c_check_header_compile () -{ - as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 -printf %s "checking for $2... " >&6; } -if eval test \${$3+y} -then : - printf %s "(cached) " >&6 -else $as_nop - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -$4 -#include <$2> -_ACEOF -if ac_fn_c_try_compile "$LINENO" -then : - eval "$3=yes" -else $as_nop - eval "$3=no" -fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext -fi -eval ac_res=\$$3 - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 -printf "%s\n" "$ac_res" >&6; } - eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno - -} # ac_fn_c_check_header_compile - # ac_fn_c_try_cpp LINENO # ---------------------- # Try to preprocess conftest.$ac_ext, and return whether this succeeded. @@ -1735,7 +1713,7 @@ *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -printf "%s\n" "$ac_try_echo"; } >&5 +$as_echo "$ac_try_echo"; } >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err ac_status=$? if test -s conftest.err; then @@ -1743,15 +1721,14 @@ cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi - printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } > conftest.i && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err - } -then : + }; then : ac_retval=0 -else $as_nop - printf "%s\n" "$as_me: failed program was:" >&5 +else + $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 @@ -1761,28 +1738,56 @@ } # ac_fn_c_try_cpp -# ac_fn_check_decl LINENO SYMBOL VAR INCLUDES EXTRA-OPTIONS FLAG-VAR -# ------------------------------------------------------------------ +# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES +# ------------------------------------------------------- +# Tests whether HEADER exists and can be compiled using the include files in +# INCLUDES, setting the cache variable VAR accordingly. +ac_fn_c_check_header_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +#include <$2> +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_header_compile + +# ac_fn_c_check_decl LINENO SYMBOL VAR INCLUDES +# --------------------------------------------- # Tests whether SYMBOL is declared in INCLUDES, setting cache variable VAR -# accordingly. Pass EXTRA-OPTIONS to the compiler, using FLAG-VAR. -ac_fn_check_decl () +# accordingly. +ac_fn_c_check_decl () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack as_decl_name=`echo $2|sed 's/ *(.*//'` - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $as_decl_name is declared" >&5 -printf %s "checking whether $as_decl_name is declared... " >&6; } -if eval test \${$3+y} -then : - printf %s "(cached) " >&6 -else $as_nop as_decl_use=`echo $2|sed -e 's/(/((/' -e 's/)/) 0&/' -e 's/,/) 0& (/g'` - eval ac_save_FLAGS=\$$6 - as_fn_append $6 " $5" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $as_decl_name is declared" >&5 +$as_echo_n "checking whether $as_decl_name is declared... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int -main (void) +main () { #ifndef $as_decl_name #ifdef __cplusplus @@ -1796,22 +1801,19 @@ return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO" -then : +if ac_fn_c_try_compile "$LINENO"; then : eval "$3=yes" -else $as_nop +else eval "$3=no" fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext - eval $6=\$ac_save_FLAGS - +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi eval ac_res=\$$3 - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 -printf "%s\n" "$ac_res" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno -} # ac_fn_check_decl +} # ac_fn_c_check_decl # ac_fn_c_try_link LINENO # ----------------------- @@ -1819,14 +1821,14 @@ ac_fn_c_try_link () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - rm -f conftest.$ac_objext conftest.beam conftest$ac_exeext + rm -f conftest.$ac_objext conftest$ac_exeext if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -printf "%s\n" "$ac_try_echo"; } >&5 +$as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>conftest.err ac_status=$? if test -s conftest.err; then @@ -1834,18 +1836,17 @@ cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi - printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || test -x conftest$ac_exeext - } -then : + }; then : ac_retval=0 -else $as_nop - printf "%s\n" "$as_me: failed program was:" >&5 +else + $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 @@ -1860,18 +1861,108 @@ } # ac_fn_c_try_link +# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES +# ------------------------------------------------------- +# Tests whether HEADER exists, giving a warning if it cannot be compiled using +# the include files in INCLUDES and setting the cache variable VAR +# accordingly. +ac_fn_c_check_header_mongrel () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if eval \${$3+:} false; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +else + # Is the header compilable? +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 +$as_echo_n "checking $2 usability... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +#include <$2> +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_header_compiler=yes +else + ac_header_compiler=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 +$as_echo "$ac_header_compiler" >&6; } + +# Is the header present? +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 +$as_echo_n "checking $2 presence... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <$2> +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + ac_header_preproc=yes +else + ac_header_preproc=no +fi +rm -f conftest.err conftest.i conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 +$as_echo "$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #(( + yes:no: ) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 +$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} + ;; + no:yes:* ) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 +$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 +$as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 +$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 +$as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} +( $as_echo "## ----------------------------------------- ## +## Report this to ssh_x509@roumenpetrov.info ## +## ----------------------------------------- ##" + ) | sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + eval "$3=\$ac_header_compiler" +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_header_mongrel + # ac_fn_c_check_func LINENO FUNC VAR # ---------------------------------- # Tests whether FUNC exists, setting the cache variable VAR accordingly ac_fn_c_check_func () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 -printf %s "checking for $2... " >&6; } -if eval test \${$3+y} -then : - printf %s "(cached) " >&6 -else $as_nop + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Define $2 to an innocuous variant, in case declares $2. @@ -1879,9 +1970,16 @@ #define $2 innocuous_$2 /* System header to define __stub macros and hopefully few prototypes, - which can conflict with char $2 (); below. */ + which can conflict with char $2 (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif -#include #undef $2 /* Override any GCC internal prototype to avoid an error. @@ -1899,25 +1997,24 @@ #endif int -main (void) +main () { return $2 (); ; return 0; } _ACEOF -if ac_fn_c_try_link "$LINENO" -then : +if ac_fn_c_try_link "$LINENO"; then : eval "$3=yes" -else $as_nop +else eval "$3=no" fi -rm -f core conftest.err conftest.$ac_objext conftest.beam \ +rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi eval ac_res=\$$3 - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 -printf "%s\n" "$ac_res" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_func @@ -1929,18 +2026,17 @@ ac_fn_c_check_type () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 -printf %s "checking for $2... " >&6; } -if eval test \${$3+y} -then : - printf %s "(cached) " >&6 -else $as_nop + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else eval "$3=no" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int -main (void) +main () { if (sizeof ($2)) return 0; @@ -1948,13 +2044,12 @@ return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO" -then : +if ac_fn_c_try_compile "$LINENO"; then : cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int -main (void) +main () { if (sizeof (($2))) return 0; @@ -1962,19 +2057,18 @@ return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO" -then : +if ac_fn_c_try_compile "$LINENO"; then : -else $as_nop +else eval "$3=yes" fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi eval ac_res=\$$3 - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 -printf "%s\n" "$ac_res" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_type @@ -1986,17 +2080,16 @@ ac_fn_c_check_member () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $2.$3" >&5 -printf %s "checking for $2.$3... " >&6; } -if eval test \${$4+y} -then : - printf %s "(cached) " >&6 -else $as_nop + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2.$3" >&5 +$as_echo_n "checking for $2.$3... " >&6; } +if eval \${$4+:} false; then : + $as_echo_n "(cached) " >&6 +else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $5 int -main (void) +main () { static $2 ac_aggr; if (ac_aggr.$3) @@ -2005,15 +2098,14 @@ return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO" -then : +if ac_fn_c_try_compile "$LINENO"; then : eval "$4=yes" -else $as_nop +else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $5 int -main (void) +main () { static $2 ac_aggr; if (sizeof ac_aggr.$3) @@ -2022,19 +2114,18 @@ return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO" -then : +if ac_fn_c_try_compile "$LINENO"; then : eval "$4=yes" -else $as_nop +else eval "$4=no" fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi eval ac_res=\$$4 - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 -printf "%s\n" "$ac_res" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_member @@ -2053,7 +2144,7 @@ /* end confdefs.h. */ $4 int -main (void) +main () { static int test_array [1 - 2 * !(($2) >= 0)]; test_array [0] = 0; @@ -2063,15 +2154,14 @@ return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO" -then : +if ac_fn_c_try_compile "$LINENO"; then : ac_lo=0 ac_mid=0 while :; do cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int -main (void) +main () { static int test_array [1 - 2 * !(($2) <= $ac_mid)]; test_array [0] = 0; @@ -2081,10 +2171,9 @@ return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO" -then : +if ac_fn_c_try_compile "$LINENO"; then : ac_hi=$ac_mid; break -else $as_nop +else as_fn_arith $ac_mid + 1 && ac_lo=$as_val if test $ac_lo -le $ac_mid; then ac_lo= ac_hi= @@ -2092,14 +2181,14 @@ fi as_fn_arith 2 '*' $ac_mid + 1 && ac_mid=$as_val fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext done -else $as_nop +else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int -main (void) +main () { static int test_array [1 - 2 * !(($2) < 0)]; test_array [0] = 0; @@ -2109,15 +2198,14 @@ return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO" -then : +if ac_fn_c_try_compile "$LINENO"; then : ac_hi=-1 ac_mid=-1 while :; do cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int -main (void) +main () { static int test_array [1 - 2 * !(($2) >= $ac_mid)]; test_array [0] = 0; @@ -2127,10 +2215,9 @@ return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO" -then : +if ac_fn_c_try_compile "$LINENO"; then : ac_lo=$ac_mid; break -else $as_nop +else as_fn_arith '(' $ac_mid ')' - 1 && ac_hi=$as_val if test $ac_mid -le $ac_hi; then ac_lo= ac_hi= @@ -2138,14 +2225,14 @@ fi as_fn_arith 2 '*' $ac_mid && ac_mid=$as_val fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext done -else $as_nop +else ac_lo= ac_hi= fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext # Binary search between lo and hi bounds. while test "x$ac_lo" != "x$ac_hi"; do as_fn_arith '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo && ac_mid=$as_val @@ -2153,7 +2240,7 @@ /* end confdefs.h. */ $4 int -main (void) +main () { static int test_array [1 - 2 * !(($2) <= $ac_mid)]; test_array [0] = 0; @@ -2163,13 +2250,12 @@ return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO" -then : +if ac_fn_c_try_compile "$LINENO"; then : ac_hi=$ac_mid -else $as_nop +else as_fn_arith '(' $ac_mid ')' + 1 && ac_lo=$as_val fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext done case $ac_lo in #(( ?*) eval "$3=\$ac_lo"; ac_retval=0 ;; @@ -2179,12 +2265,12 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 -static long int longval (void) { return $2; } -static unsigned long int ulongval (void) { return $2; } +static long int longval () { return $2; } +static unsigned long int ulongval () { return $2; } #include #include int -main (void) +main () { FILE *f = fopen ("conftest.val", "w"); @@ -2212,10 +2298,9 @@ return 0; } _ACEOF -if ac_fn_c_try_run "$LINENO" -then : +if ac_fn_c_try_run "$LINENO"; then : echo >>conftest.val; read $3 config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by OpenSSH $as_me Portable, which was -generated by GNU Autoconf 2.71. Invocation command line was +It was created by PKIX-SSH $as_me 14.2.1, which was +generated by GNU Autoconf 2.69. Invocation command line was - $ $0$ac_configure_args_raw + $ $0 $@ _ACEOF exec 5>>config.log @@ -2287,12 +2352,8 @@ for as_dir in $PATH do IFS=$as_save_IFS - case $as_dir in #((( - '') as_dir=./ ;; - */) ;; - *) as_dir=$as_dir/ ;; - esac - printf "%s\n" "PATH: $as_dir" + test -z "$as_dir" && as_dir=. + $as_echo "PATH: $as_dir" done IFS=$as_save_IFS @@ -2327,7 +2388,7 @@ | -silent | --silent | --silen | --sile | --sil) continue ;; *\'*) - ac_arg=`printf "%s\n" "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac case $ac_pass in 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; @@ -2362,13 +2423,11 @@ # WARNING: Use '\'' to represent an apostrophe within the trap. # WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. trap 'exit_status=$? - # Sanitize IFS. - IFS=" "" $as_nl" # Save into config.log some information that might help in debugging. { echo - printf "%s\n" "## ---------------- ## + $as_echo "## ---------------- ## ## Cache variables. ## ## ---------------- ##" echo @@ -2379,8 +2438,8 @@ case $ac_val in #( *${as_nl}*) case $ac_var in #( - *_cv_*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 -printf "%s\n" "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( @@ -2404,7 +2463,7 @@ ) echo - printf "%s\n" "## ----------------- ## + $as_echo "## ----------------- ## ## Output variables. ## ## ----------------- ##" echo @@ -2412,14 +2471,14 @@ do eval ac_val=\$$ac_var case $ac_val in - *\'\''*) ac_val=`printf "%s\n" "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac - printf "%s\n" "$ac_var='\''$ac_val'\''" + $as_echo "$ac_var='\''$ac_val'\''" done | sort echo if test -n "$ac_subst_files"; then - printf "%s\n" "## ------------------- ## + $as_echo "## ------------------- ## ## File substitutions. ## ## ------------------- ##" echo @@ -2427,15 +2486,15 @@ do eval ac_val=\$$ac_var case $ac_val in - *\'\''*) ac_val=`printf "%s\n" "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac - printf "%s\n" "$ac_var='\''$ac_val'\''" + $as_echo "$ac_var='\''$ac_val'\''" done | sort echo fi if test -s confdefs.h; then - printf "%s\n" "## ----------- ## + $as_echo "## ----------- ## ## confdefs.h. ## ## ----------- ##" echo @@ -2443,8 +2502,8 @@ echo fi test "$ac_signal" != 0 && - printf "%s\n" "$as_me: caught signal $ac_signal" - printf "%s\n" "$as_me: exit $exit_status" + $as_echo "$as_me: caught signal $ac_signal" + $as_echo "$as_me: exit $exit_status" } >&5 rm -f core *.core core.conftest.* && rm -f -r conftest* confdefs* conf$$* $ac_clean_files && @@ -2458,48 +2517,63 @@ # confdefs.h avoids OS command line length limits that DEFS can exceed. rm -f -r conftest* confdefs.h -printf "%s\n" "/* confdefs.h */" > confdefs.h +$as_echo "/* confdefs.h */" > confdefs.h # Predefined preprocessor variables. -printf "%s\n" "#define PACKAGE_NAME \"$PACKAGE_NAME\"" >>confdefs.h +cat >>confdefs.h <<_ACEOF +#define PACKAGE_NAME "$PACKAGE_NAME" +_ACEOF -printf "%s\n" "#define PACKAGE_TARNAME \"$PACKAGE_TARNAME\"" >>confdefs.h +cat >>confdefs.h <<_ACEOF +#define PACKAGE_TARNAME "$PACKAGE_TARNAME" +_ACEOF -printf "%s\n" "#define PACKAGE_VERSION \"$PACKAGE_VERSION\"" >>confdefs.h +cat >>confdefs.h <<_ACEOF +#define PACKAGE_VERSION "$PACKAGE_VERSION" +_ACEOF -printf "%s\n" "#define PACKAGE_STRING \"$PACKAGE_STRING\"" >>confdefs.h +cat >>confdefs.h <<_ACEOF +#define PACKAGE_STRING "$PACKAGE_STRING" +_ACEOF -printf "%s\n" "#define PACKAGE_BUGREPORT \"$PACKAGE_BUGREPORT\"" >>confdefs.h +cat >>confdefs.h <<_ACEOF +#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" +_ACEOF -printf "%s\n" "#define PACKAGE_URL \"$PACKAGE_URL\"" >>confdefs.h +cat >>confdefs.h <<_ACEOF +#define PACKAGE_URL "$PACKAGE_URL" +_ACEOF # Let the site file select an alternate cache file if it wants to. # Prefer an explicitly selected file to automatically selected ones. +ac_site_file1=NONE +ac_site_file2=NONE if test -n "$CONFIG_SITE"; then - ac_site_files="$CONFIG_SITE" + # We do not want a PATH search for config.site. + case $CONFIG_SITE in #(( + -*) ac_site_file1=./$CONFIG_SITE;; + */*) ac_site_file1=$CONFIG_SITE;; + *) ac_site_file1=./$CONFIG_SITE;; + esac elif test "x$prefix" != xNONE; then - ac_site_files="$prefix/share/config.site $prefix/etc/config.site" + ac_site_file1=$prefix/share/config.site + ac_site_file2=$prefix/etc/config.site else - ac_site_files="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" + ac_site_file1=$ac_default_prefix/share/config.site + ac_site_file2=$ac_default_prefix/etc/config.site fi - -for ac_site_file in $ac_site_files +for ac_site_file in "$ac_site_file1" "$ac_site_file2" do - case $ac_site_file in #( - */*) : - ;; #( - *) : - ac_site_file=./$ac_site_file ;; -esac - if test -f "$ac_site_file" && test -r "$ac_site_file"; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 -printf "%s\n" "$as_me: loading site script $ac_site_file" >&6;} + test "x$ac_site_file" = xNONE && continue + if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 +$as_echo "$as_me: loading site script $ac_site_file" >&6;} sed 's/^/| /' "$ac_site_file" >&5 . "$ac_site_file" \ - || { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} + || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "failed to load site script $ac_site_file See \`config.log' for more details" "$LINENO" 5; } fi @@ -2509,434 +2583,19 @@ # Some versions of bash will fail to source /dev/null (special files # actually), so we avoid doing that. DJGPP emulates it as a regular file. if test /dev/null != "$cache_file" && test -f "$cache_file"; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 -printf "%s\n" "$as_me: loading cache $cache_file" >&6;} + { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 +$as_echo "$as_me: loading cache $cache_file" >&6;} case $cache_file in [\\/]* | ?:[\\/]* ) . "$cache_file";; *) . "./$cache_file";; esac fi else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 -printf "%s\n" "$as_me: creating cache $cache_file" >&6;} + { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 +$as_echo "$as_me: creating cache $cache_file" >&6;} >$cache_file fi -# Test code for whether the C compiler supports C89 (global declarations) -ac_c_conftest_c89_globals=' -/* Does the compiler advertise C89 conformance? - Do not test the value of __STDC__, because some compilers set it to 0 - while being otherwise adequately conformant. */ -#if !defined __STDC__ -# error "Compiler does not advertise C89 conformance" -#endif - -#include -#include -struct stat; -/* Most of the following tests are stolen from RCS 5.7 src/conf.sh. */ -struct buf { int x; }; -struct buf * (*rcsopen) (struct buf *, struct stat *, int); -static char *e (p, i) - char **p; - int i; -{ - return p[i]; -} -static char *f (char * (*g) (char **, int), char **p, ...) -{ - char *s; - va_list v; - va_start (v,p); - s = g (p, va_arg (v,int)); - va_end (v); - return s; -} - -/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has - function prototypes and stuff, but not \xHH hex character constants. - These do not provoke an error unfortunately, instead are silently treated - as an "x". The following induces an error, until -std is added to get - proper ANSI mode. Curiously \x00 != x always comes out true, for an - array size at least. It is necessary to write \x00 == 0 to get something - that is true only with -std. */ -int osf4_cc_array ['\''\x00'\'' == 0 ? 1 : -1]; - -/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters - inside strings and character constants. */ -#define FOO(x) '\''x'\'' -int xlc6_cc_array[FOO(a) == '\''x'\'' ? 1 : -1]; - -int test (int i, double x); -struct s1 {int (*f) (int a);}; -struct s2 {int (*f) (double a);}; -int pairnames (int, char **, int *(*)(struct buf *, struct stat *, int), - int, int);' - -# Test code for whether the C compiler supports C89 (body of main). -ac_c_conftest_c89_main=' -ok |= (argc == 0 || f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]); -' - -# Test code for whether the C compiler supports C99 (global declarations) -ac_c_conftest_c99_globals=' -// Does the compiler advertise C99 conformance? -#if !defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L -# error "Compiler does not advertise C99 conformance" -#endif - -#include -extern int puts (const char *); -extern int printf (const char *, ...); -extern int dprintf (int, const char *, ...); -extern void *malloc (size_t); - -// Check varargs macros. These examples are taken from C99 6.10.3.5. -// dprintf is used instead of fprintf to avoid needing to declare -// FILE and stderr. -#define debug(...) dprintf (2, __VA_ARGS__) -#define showlist(...) puts (#__VA_ARGS__) -#define report(test,...) ((test) ? puts (#test) : printf (__VA_ARGS__)) -static void -test_varargs_macros (void) -{ - int x = 1234; - int y = 5678; - debug ("Flag"); - debug ("X = %d\n", x); - showlist (The first, second, and third items.); - report (x>y, "x is %d but y is %d", x, y); -} - -// Check long long types. -#define BIG64 18446744073709551615ull -#define BIG32 4294967295ul -#define BIG_OK (BIG64 / BIG32 == 4294967297ull && BIG64 % BIG32 == 0) -#if !BIG_OK - #error "your preprocessor is broken" -#endif -#if BIG_OK -#else - #error "your preprocessor is broken" -#endif -static long long int bignum = -9223372036854775807LL; -static unsigned long long int ubignum = BIG64; - -struct incomplete_array -{ - int datasize; - double data[]; -}; - -struct named_init { - int number; - const wchar_t *name; - double average; -}; - -typedef const char *ccp; - -static inline int -test_restrict (ccp restrict text) -{ - // See if C++-style comments work. - // Iterate through items via the restricted pointer. - // Also check for declarations in for loops. - for (unsigned int i = 0; *(text+i) != '\''\0'\''; ++i) - continue; - return 0; -} - -// Check varargs and va_copy. -static bool -test_varargs (const char *format, ...) -{ - va_list args; - va_start (args, format); - va_list args_copy; - va_copy (args_copy, args); - - const char *str = ""; - int number = 0; - float fnumber = 0; - - while (*format) - { - switch (*format++) - { - case '\''s'\'': // string - str = va_arg (args_copy, const char *); - break; - case '\''d'\'': // int - number = va_arg (args_copy, int); - break; - case '\''f'\'': // float - fnumber = va_arg (args_copy, double); - break; - default: - break; - } - } - va_end (args_copy); - va_end (args); - - return *str && number && fnumber; -} -' - -# Test code for whether the C compiler supports C99 (body of main). -ac_c_conftest_c99_main=' - // Check bool. - _Bool success = false; - success |= (argc != 0); - - // Check restrict. - if (test_restrict ("String literal") == 0) - success = true; - char *restrict newvar = "Another string"; - - // Check varargs. - success &= test_varargs ("s, d'\'' f .", "string", 65, 34.234); - test_varargs_macros (); - - // Check flexible array members. - struct incomplete_array *ia = - malloc (sizeof (struct incomplete_array) + (sizeof (double) * 10)); - ia->datasize = 10; - for (int i = 0; i < ia->datasize; ++i) - ia->data[i] = i * 1.234; - - // Check named initializers. - struct named_init ni = { - .number = 34, - .name = L"Test wide string", - .average = 543.34343, - }; - - ni.number = 58; - - int dynamic_array[ni.number]; - dynamic_array[0] = argv[0][0]; - dynamic_array[ni.number - 1] = 543; - - // work around unused variable warnings - ok |= (!success || bignum == 0LL || ubignum == 0uLL || newvar[0] == '\''x'\'' - || dynamic_array[ni.number - 1] != 543); -' - -# Test code for whether the C compiler supports C11 (global declarations) -ac_c_conftest_c11_globals=' -// Does the compiler advertise C11 conformance? -#if !defined __STDC_VERSION__ || __STDC_VERSION__ < 201112L -# error "Compiler does not advertise C11 conformance" -#endif - -// Check _Alignas. -char _Alignas (double) aligned_as_double; -char _Alignas (0) no_special_alignment; -extern char aligned_as_int; -char _Alignas (0) _Alignas (int) aligned_as_int; - -// Check _Alignof. -enum -{ - int_alignment = _Alignof (int), - int_array_alignment = _Alignof (int[100]), - char_alignment = _Alignof (char) -}; -_Static_assert (0 < -_Alignof (int), "_Alignof is signed"); - -// Check _Noreturn. -int _Noreturn does_not_return (void) { for (;;) continue; } - -// Check _Static_assert. -struct test_static_assert -{ - int x; - _Static_assert (sizeof (int) <= sizeof (long int), - "_Static_assert does not work in struct"); - long int y; -}; - -// Check UTF-8 literals. -#define u8 syntax error! -char const utf8_literal[] = u8"happens to be ASCII" "another string"; - -// Check duplicate typedefs. -typedef long *long_ptr; -typedef long int *long_ptr; -typedef long_ptr long_ptr; - -// Anonymous structures and unions -- taken from C11 6.7.2.1 Example 1. -struct anonymous -{ - union { - struct { int i; int j; }; - struct { int k; long int l; } w; - }; - int m; -} v1; -' - -# Test code for whether the C compiler supports C11 (body of main). -ac_c_conftest_c11_main=' - _Static_assert ((offsetof (struct anonymous, i) - == offsetof (struct anonymous, w.k)), - "Anonymous union alignment botch"); - v1.i = 2; - v1.w.k = 5; - ok |= v1.i != 5; -' - -# Test code for whether the C compiler supports C11 (complete). -ac_c_conftest_c11_program="${ac_c_conftest_c89_globals} -${ac_c_conftest_c99_globals} -${ac_c_conftest_c11_globals} - -int -main (int argc, char **argv) -{ - int ok = 0; - ${ac_c_conftest_c89_main} - ${ac_c_conftest_c99_main} - ${ac_c_conftest_c11_main} - return ok; -} -" - -# Test code for whether the C compiler supports C99 (complete). -ac_c_conftest_c99_program="${ac_c_conftest_c89_globals} -${ac_c_conftest_c99_globals} - -int -main (int argc, char **argv) -{ - int ok = 0; - ${ac_c_conftest_c89_main} - ${ac_c_conftest_c99_main} - return ok; -} -" - -# Test code for whether the C compiler supports C89 (complete). -ac_c_conftest_c89_program="${ac_c_conftest_c89_globals} - -int -main (int argc, char **argv) -{ - int ok = 0; - ${ac_c_conftest_c89_main} - return ok; -} -" - -as_fn_append ac_header_c_list " stdio.h stdio_h HAVE_STDIO_H" -as_fn_append ac_header_c_list " stdlib.h stdlib_h HAVE_STDLIB_H" -as_fn_append ac_header_c_list " string.h string_h HAVE_STRING_H" -as_fn_append ac_header_c_list " inttypes.h inttypes_h HAVE_INTTYPES_H" -as_fn_append ac_header_c_list " stdint.h stdint_h HAVE_STDINT_H" -as_fn_append ac_header_c_list " strings.h strings_h HAVE_STRINGS_H" -as_fn_append ac_header_c_list " sys/stat.h sys_stat_h HAVE_SYS_STAT_H" -as_fn_append ac_header_c_list " sys/types.h sys_types_h HAVE_SYS_TYPES_H" -as_fn_append ac_header_c_list " unistd.h unistd_h HAVE_UNISTD_H" - -# Auxiliary files required by this configure script. -ac_aux_files="install-sh config.guess config.sub" - -# Locations in which to look for auxiliary files. -ac_aux_dir_candidates="${srcdir}${PATH_SEPARATOR}${srcdir}/..${PATH_SEPARATOR}${srcdir}/../.." - -# Search for a directory containing all of the required auxiliary files, -# $ac_aux_files, from the $PATH-style list $ac_aux_dir_candidates. -# If we don't find one directory that contains all the files we need, -# we report the set of missing files from the *first* directory in -# $ac_aux_dir_candidates and give up. -ac_missing_aux_files="" -ac_first_candidate=: -printf "%s\n" "$as_me:${as_lineno-$LINENO}: looking for aux files: $ac_aux_files" >&5 -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -as_found=false -for as_dir in $ac_aux_dir_candidates -do - IFS=$as_save_IFS - case $as_dir in #((( - '') as_dir=./ ;; - */) ;; - *) as_dir=$as_dir/ ;; - esac - as_found=: - - printf "%s\n" "$as_me:${as_lineno-$LINENO}: trying $as_dir" >&5 - ac_aux_dir_found=yes - ac_install_sh= - for ac_aux in $ac_aux_files - do - # As a special case, if "install-sh" is required, that requirement - # can be satisfied by any of "install-sh", "install.sh", or "shtool", - # and $ac_install_sh is set appropriately for whichever one is found. - if test x"$ac_aux" = x"install-sh" - then - if test -f "${as_dir}install-sh"; then - printf "%s\n" "$as_me:${as_lineno-$LINENO}: ${as_dir}install-sh found" >&5 - ac_install_sh="${as_dir}install-sh -c" - elif test -f "${as_dir}install.sh"; then - printf "%s\n" "$as_me:${as_lineno-$LINENO}: ${as_dir}install.sh found" >&5 - ac_install_sh="${as_dir}install.sh -c" - elif test -f "${as_dir}shtool"; then - printf "%s\n" "$as_me:${as_lineno-$LINENO}: ${as_dir}shtool found" >&5 - ac_install_sh="${as_dir}shtool install -c" - else - ac_aux_dir_found=no - if $ac_first_candidate; then - ac_missing_aux_files="${ac_missing_aux_files} install-sh" - else - break - fi - fi - else - if test -f "${as_dir}${ac_aux}"; then - printf "%s\n" "$as_me:${as_lineno-$LINENO}: ${as_dir}${ac_aux} found" >&5 - else - ac_aux_dir_found=no - if $ac_first_candidate; then - ac_missing_aux_files="${ac_missing_aux_files} ${ac_aux}" - else - break - fi - fi - fi - done - if test "$ac_aux_dir_found" = yes; then - ac_aux_dir="$as_dir" - break - fi - ac_first_candidate=false - - as_found=false -done -IFS=$as_save_IFS -if $as_found -then : - -else $as_nop - as_fn_error $? "cannot find required auxiliary files:$ac_missing_aux_files" "$LINENO" 5 -fi - - -# These three variables are undocumented and unsupported, -# and are intended to be withdrawn in a future Autoconf release. -# They can cause serious problems if a builder's source tree is in a directory -# whose full name contains unusual characters. -if test -f "${ac_aux_dir}config.guess"; then - ac_config_guess="$SHELL ${ac_aux_dir}config.guess" -fi -if test -f "${ac_aux_dir}config.sub"; then - ac_config_sub="$SHELL ${ac_aux_dir}config.sub" -fi -if test -f "$ac_aux_dir/configure"; then - ac_configure="$SHELL ${ac_aux_dir}configure" -fi - # Check that the precious variables saved in the cache have kept the same # value. ac_cache_corrupted=false @@ -2947,12 +2606,12 @@ eval ac_new_val=\$ac_env_${ac_var}_value case $ac_old_set,$ac_new_set in set,) - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 -printf "%s\n" "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 +$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} ac_cache_corrupted=: ;; ,set) - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 -printf "%s\n" "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 +$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} ac_cache_corrupted=: ;; ,);; *) @@ -2961,24 +2620,24 @@ ac_old_val_w=`echo x $ac_old_val` ac_new_val_w=`echo x $ac_new_val` if test "$ac_old_val_w" != "$ac_new_val_w"; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 -printf "%s\n" "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 +$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} ac_cache_corrupted=: else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 -printf "%s\n" "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 +$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} eval $ac_var=\$ac_old_val fi - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 -printf "%s\n" "$as_me: former value: \`$ac_old_val'" >&2;} - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 -printf "%s\n" "$as_me: current value: \`$ac_new_val'" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 +$as_echo "$as_me: former value: \`$ac_old_val'" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 +$as_echo "$as_me: current value: \`$ac_new_val'" >&2;} fi;; esac # Pass precious variables to config.status. if test "$ac_new_set" = set; then case $ac_new_val in - *\'*) ac_arg=$ac_var=`printf "%s\n" "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; + *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; *) ac_arg=$ac_var=$ac_new_val ;; esac case " $ac_configure_args " in @@ -2988,12 +2647,11 @@ fi done if $ac_cache_corrupted; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 -printf "%s\n" "$as_me: error: changes in the environment can compromise the build" >&2;} - as_fn_error $? "run \`${MAKE-make} distclean' and/or \`rm $cache_file' - and start over" "$LINENO" 5 + { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 +$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} + as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 fi ## -------------------- ## ## Main body of script. ## @@ -3008,30 +2666,155 @@ +for i in $srcdir/version.m4 $srcdir/m4/*.m4 $srcdir/configure.ac ; do + if test "$i" -nt "$srcdir/configure"; then : -# Check for stale configure as early as possible. -for i in $srcdir/configure.ac $srcdir/m4/*.m4; do - if test "$i" -nt "$srcdir/configure"; then - as_fn_error $? "$i newer than configure, run autoreconf" "$LINENO" 5 - fi + as_fn_error $? "configure older than $i + +*** Please re-genenarate and configure *** + " "$LINENO" 5 + +fi done -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu +# options to check compiler +# +# Author: Roumen Petrov +# Revision: 2022-01-30 +# + + + + + + + + + + + + + + + + + +# Options to build with LDAP +# +# Author: Roumen Petrov +# Revision: 7 Dec 2011 +# + + + + +# AC_LDAP_FUNCS(FUNCTION...) +# -------------------------------- + ac_config_headers="$ac_config_headers config.h" +ac_aux_dir= +for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do + if test -f "$ac_dir/install-sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" + break + elif test -f "$ac_dir/install.sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install.sh -c" + break + elif test -f "$ac_dir/shtool"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/shtool install -c" + break + fi +done +if test -z "$ac_aux_dir"; then + as_fn_error $? "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5 +fi +# These three variables are undocumented and unsupported, +# and are intended to be withdrawn in a future Autoconf release. +# They can cause serious problems if a builder's source tree is in a directory +# whose full name contains unusual characters. +ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. +ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. +ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. +# Make sure we can run config.sub. +$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 || + as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5 + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5 +$as_echo_n "checking build system type... " >&6; } +if ${ac_cv_build+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_build_alias=$build_alias +test "x$ac_build_alias" = x && + ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"` +test "x$ac_build_alias" = x && + as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5 +ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` || + as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5 +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5 +$as_echo "$ac_cv_build" >&6; } +case $ac_cv_build in +*-*-*) ;; +*) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;; +esac +build=$ac_cv_build +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_build +shift +build_cpu=$1 +build_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +build_os=$* +IFS=$ac_save_IFS +case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5 +$as_echo_n "checking host system type... " >&6; } +if ${ac_cv_host+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "x$host_alias" = x; then + ac_cv_host=$ac_cv_build +else + ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` || + as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5 +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5 +$as_echo "$ac_cv_host" >&6; } +case $ac_cv_host in +*-*-*) ;; +*) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;; +esac +host=$ac_cv_host +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_host +shift +host_cpu=$1 +host_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +host_os=$* +IFS=$ac_save_IFS +case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac + ac_ext=c @@ -3040,16 +2823,205 @@ ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then - for ac_prog in cc gcc clang + # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. +set dummy ${ac_tool_prefix}gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +else + CC="$ac_cv_prog_CC" +fi + +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. +set dummy ${ac_tool_prefix}cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + fi +fi +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + ac_prog_rejected=no +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# != 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" + fi +fi +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + for ac_prog in cl.exe do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -printf %s "checking for $ac_word... " >&6; } -if test ${ac_cv_prog_CC+y} -then : - printf %s "(cached) " >&6 -else $as_nop +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else @@ -3057,15 +3029,11 @@ for as_dir in $PATH do IFS=$as_save_IFS - case $as_dir in #((( - '') as_dir=./ ;; - */) ;; - *) as_dir=$as_dir/ ;; - esac + test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" - printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done @@ -3076,11 +3044,11 @@ fi CC=$ac_cv_prog_CC if test -n "$CC"; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 -printf "%s\n" "$CC" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } fi @@ -3089,16 +3057,15 @@ fi if test -z "$CC"; then ac_ct_CC=$CC - for ac_prog in cc gcc clang + for ac_prog in cl.exe do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -printf %s "checking for $ac_word... " >&6; } -if test ${ac_cv_prog_ac_ct_CC+y} -then : - printf %s "(cached) " >&6 -else $as_nop +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else @@ -3106,15 +3073,11 @@ for as_dir in $PATH do IFS=$as_save_IFS - case $as_dir in #((( - '') as_dir=./ ;; - */) ;; - *) as_dir=$as_dir/ ;; - esac + test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="$ac_prog" - printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done @@ -3125,11 +3088,11 @@ fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 -printf "%s\n" "$ac_ct_CC" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } fi @@ -3141,32 +3104,34 @@ else case $cross_compiling:$ac_tool_warned in yes:) -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi fi +fi + -test -z "$CC" && { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} +test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "no acceptable C compiler found in \$PATH See \`config.log' for more details" "$LINENO" 5; } # Provide some information about the compiler. -printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 +$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 set X $ac_compile ac_compiler=$2 -for ac_option in --version -v -V -qversion -version; do +for ac_option in --version -v -V -qversion; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -printf "%s\n" "$ac_try_echo"; } >&5 +$as_echo "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then @@ -3176,7 +3141,7 @@ cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err - printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done @@ -3184,7 +3149,7 @@ /* end confdefs.h. */ int -main (void) +main () { ; @@ -3196,9 +3161,9 @@ # Try to create an executable without -o first, disregard a.out. # It will help us diagnose broken compilers, and finding out an intuition # of exeext. -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 -printf %s "checking whether the C compiler works... " >&6; } -ac_link_default=`printf "%s\n" "$ac_link" | sed 's/ -o *conftest[^ ]*//'` +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 +$as_echo_n "checking whether the C compiler works... " >&6; } +ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` # The possible output files: ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" @@ -3219,12 +3184,11 @@ *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -printf "%s\n" "$ac_try_echo"; } >&5 +$as_echo "$ac_try_echo"; } >&5 (eval "$ac_link_default") 2>&5 ac_status=$? - printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } -then : + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. # So ignore a value of `no', otherwise this would lead to `EXEEXT = no' # in a Makefile. We should not override ac_cv_exeext if it was cached, @@ -3241,7 +3205,7 @@ # certainly right. break;; *.* ) - if test ${ac_cv_exeext+y} && test "$ac_cv_exeext" != no; + if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; then :; else ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` fi @@ -3257,46 +3221,44 @@ done test "$ac_cv_exeext" = no && ac_cv_exeext= -else $as_nop +else ac_file='' fi -if test -z "$ac_file" -then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } -printf "%s\n" "$as_me: failed program was:" >&5 +if test -z "$ac_file"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +$as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 -{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} +{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "C compiler cannot create executables See \`config.log' for more details" "$LINENO" 5; } -else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } -fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 -printf %s "checking for C compiler default output file name... " >&6; } -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 -printf "%s\n" "$ac_file" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 +$as_echo_n "checking for C compiler default output file name... " >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 +$as_echo "$ac_file" >&6; } ac_exeext=$ac_cv_exeext rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out ac_clean_files=$ac_clean_files_save -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 -printf %s "checking for suffix of executables... " >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 +$as_echo_n "checking for suffix of executables... " >&6; } if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -printf "%s\n" "$ac_try_echo"; } >&5 +$as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? - printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } -then : + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : # If both `conftest.exe' and `conftest' are `present' (well, observable) # catch `conftest.exe'. For instance with Cygwin, `ls conftest' will # work properly (i.e., refer to `conftest.exe'), while it won't with @@ -3310,15 +3272,15 @@ * ) break;; esac done -else $as_nop - { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of executables: cannot compile and link See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest conftest$ac_cv_exeext -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 -printf "%s\n" "$ac_cv_exeext" >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 +$as_echo "$ac_cv_exeext" >&6; } rm -f conftest.$ac_ext EXEEXT=$ac_cv_exeext @@ -3327,7 +3289,7 @@ /* end confdefs.h. */ #include int -main (void) +main () { FILE *f = fopen ("conftest.out", "w"); return ferror (f) || fclose (f) != 0; @@ -3339,8 +3301,8 @@ ac_clean_files="$ac_clean_files conftest.out" # Check that the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 -printf %s "checking whether we are cross compiling... " >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 +$as_echo_n "checking whether we are cross compiling... " >&6; } if test "$cross_compiling" != yes; then { { ac_try="$ac_link" case "(($ac_try" in @@ -3348,10 +3310,10 @@ *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -printf "%s\n" "$ac_try_echo"; } >&5 +$as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? - printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if { ac_try='./conftest$ac_cv_exeext' { { case "(($ac_try" in @@ -3359,40 +3321,39 @@ *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -printf "%s\n" "$ac_try_echo"; } >&5 +$as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? - printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then cross_compiling=no else if test "$cross_compiling" = maybe; then cross_compiling=yes else - { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error 77 "cannot run C compiled programs. + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot run C compiled programs. If you meant to cross compile, use \`--host'. See \`config.log' for more details" "$LINENO" 5; } fi fi fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 -printf "%s\n" "$cross_compiling" >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 +$as_echo "$cross_compiling" >&6; } rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out ac_clean_files=$ac_clean_files_save -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 -printf %s "checking for suffix of object files... " >&6; } -if test ${ac_cv_objext+y} -then : - printf %s "(cached) " >&6 -else $as_nop +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 +$as_echo_n "checking for suffix of object files... " >&6; } +if ${ac_cv_objext+:} false; then : + $as_echo_n "(cached) " >&6 +else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int -main (void) +main () { ; @@ -3406,12 +3367,11 @@ *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -printf "%s\n" "$ac_try_echo"; } >&5 +$as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>&5 ac_status=$? - printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } -then : + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : for ac_file in conftest.o conftest.obj conftest.*; do test -f "$ac_file" || continue; case $ac_file in @@ -3420,32 +3380,31 @@ break;; esac done -else $as_nop - printf "%s\n" "$as_me: failed program was:" >&5 +else + $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 -{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} +{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of object files: cannot compile See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest.$ac_cv_objext conftest.$ac_ext fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 -printf "%s\n" "$ac_cv_objext" >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 +$as_echo "$ac_cv_objext" >&6; } OBJEXT=$ac_cv_objext ac_objext=$OBJEXT -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports GNU C" >&5 -printf %s "checking whether the compiler supports GNU C... " >&6; } -if test ${ac_cv_c_compiler_gnu+y} -then : - printf %s "(cached) " >&6 -else $as_nop +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 +$as_echo_n "checking whether we are using the GNU C compiler... " >&6; } +if ${ac_cv_c_compiler_gnu+:} false; then : + $as_echo_n "(cached) " >&6 +else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int -main (void) +main () { #ifndef __GNUC__ choke me @@ -3455,33 +3414,29 @@ return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO" -then : +if ac_fn_c_try_compile "$LINENO"; then : ac_compiler_gnu=yes -else $as_nop +else ac_compiler_gnu=no fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 -printf "%s\n" "$ac_cv_c_compiler_gnu" >&6; } -ac_compiler_gnu=$ac_cv_c_compiler_gnu - +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 +$as_echo "$ac_cv_c_compiler_gnu" >&6; } if test $ac_compiler_gnu = yes; then GCC=yes else GCC= fi -ac_test_CFLAGS=${CFLAGS+y} +ac_test_CFLAGS=${CFLAGS+set} ac_save_CFLAGS=$CFLAGS -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 -printf %s "checking whether $CC accepts -g... " >&6; } -if test ${ac_cv_prog_cc_g+y} -then : - printf %s "(cached) " >&6 -else $as_nop +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 +$as_echo_n "checking whether $CC accepts -g... " >&6; } +if ${ac_cv_prog_cc_g+:} false; then : + $as_echo_n "(cached) " >&6 +else ac_save_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes ac_cv_prog_cc_g=no @@ -3490,60 +3445,57 @@ /* end confdefs.h. */ int -main (void) +main () { ; return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO" -then : +if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes -else $as_nop +else CFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int -main (void) +main () { ; return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO" -then : +if ac_fn_c_try_compile "$LINENO"; then : -else $as_nop +else ac_c_werror_flag=$ac_save_c_werror_flag CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int -main (void) +main () { ; return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO" -then : +if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_c_werror_flag=$ac_save_c_werror_flag fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 -printf "%s\n" "$ac_cv_prog_cc_g" >&6; } -if test $ac_test_CFLAGS; then +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 +$as_echo "$ac_cv_prog_cc_g" >&6; } +if test "$ac_test_CFLAGS" = set; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then @@ -3558,144 +3510,423 @@ CFLAGS= fi fi -ac_prog_cc_stdc=no -if test x$ac_prog_cc_stdc = xno -then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C11 features" >&5 -printf %s "checking for $CC option to enable C11 features... " >&6; } -if test ${ac_cv_prog_cc_c11+y} -then : - printf %s "(cached) " >&6 -else $as_nop - ac_cv_prog_cc_c11=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 +$as_echo_n "checking for $CC option to accept ISO C89... " >&6; } +if ${ac_cv_prog_cc_c89+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_prog_cc_c89=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -$ac_c_conftest_c11_program +#include +#include +struct stat; +/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ +struct buf { int x; }; +FILE * (*rcsopen) (struct buf *, struct stat *, int); +static char *e (p, i) + char **p; + int i; +{ + return p[i]; +} +static char *f (char * (*g) (char **, int), char **p, ...) +{ + char *s; + va_list v; + va_start (v,p); + s = g (p, va_arg (v,int)); + va_end (v); + return s; +} + +/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has + function prototypes and stuff, but not '\xHH' hex character constants. + These don't provoke an error unfortunately, instead are silently treated + as 'x'. The following induces an error, until -std is added to get + proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an + array size at least. It's necessary to write '\x00'==0 to get something + that's true only with -std. */ +int osf4_cc_array ['\x00' == 0 ? 1 : -1]; + +/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters + inside strings and character constants. */ +#define FOO(x) 'x' +int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; + +int test (int i, double x); +struct s1 {int (*f) (int a);}; +struct s2 {int (*f) (double a);}; +int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); +int argc; +char **argv; +int +main () +{ +return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; + ; + return 0; +} _ACEOF -for ac_arg in '' -std=gnu11 +for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ + -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" - if ac_fn_c_try_compile "$LINENO" -then : - ac_cv_prog_cc_c11=$ac_arg + if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_c89=$ac_arg fi -rm -f core conftest.err conftest.$ac_objext conftest.beam - test "x$ac_cv_prog_cc_c11" != "xno" && break +rm -f core conftest.err conftest.$ac_objext + test "x$ac_cv_prog_cc_c89" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC + fi +# AC_CACHE_VAL +case "x$ac_cv_prog_cc_c89" in + x) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 +$as_echo "none needed" >&6; } ;; + xno) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 +$as_echo "unsupported" >&6; } ;; + *) + CC="$CC $ac_cv_prog_cc_c89" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 +$as_echo "$ac_cv_prog_cc_c89" >&6; } ;; +esac +if test "x$ac_cv_prog_cc_c89" != xno; then : -if test "x$ac_cv_prog_cc_c11" = xno -then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 -printf "%s\n" "unsupported" >&6; } -else $as_nop - if test "x$ac_cv_prog_cc_c11" = x -then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 -printf "%s\n" "none needed" >&6; } -else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c11" >&5 -printf "%s\n" "$ac_cv_prog_cc_c11" >&6; } - CC="$CC $ac_cv_prog_cc_c11" -fi - ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c11 - ac_prog_cc_stdc=c11 -fi -fi -if test x$ac_prog_cc_stdc = xno -then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C99 features" >&5 -printf %s "checking for $CC option to enable C99 features... " >&6; } -if test ${ac_cv_prog_cc_c99+y} -then : - printf %s "(cached) " >&6 -else $as_nop +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C99" >&5 +$as_echo_n "checking for $CC option to accept ISO C99... " >&6; } +if ${ac_cv_prog_cc_c99+:} false; then : + $as_echo_n "(cached) " >&6 +else ac_cv_prog_cc_c99=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -$ac_c_conftest_c99_program +#include +#include +#include +#include +#include + +// Check varargs macros. These examples are taken from C99 6.10.3.5. +#define debug(...) fprintf (stderr, __VA_ARGS__) +#define showlist(...) puts (#__VA_ARGS__) +#define report(test,...) ((test) ? puts (#test) : printf (__VA_ARGS__)) +static void +test_varargs_macros (void) +{ + int x = 1234; + int y = 5678; + debug ("Flag"); + debug ("X = %d\n", x); + showlist (The first, second, and third items.); + report (x>y, "x is %d but y is %d", x, y); +} + +// Check long long types. +#define BIG64 18446744073709551615ull +#define BIG32 4294967295ul +#define BIG_OK (BIG64 / BIG32 == 4294967297ull && BIG64 % BIG32 == 0) +#if !BIG_OK + your preprocessor is broken; +#endif +#if BIG_OK +#else + your preprocessor is broken; +#endif +static long long int bignum = -9223372036854775807LL; +static unsigned long long int ubignum = BIG64; + +struct incomplete_array +{ + int datasize; + double data[]; +}; + +struct named_init { + int number; + const wchar_t *name; + double average; +}; + +typedef const char *ccp; + +static inline int +test_restrict (ccp restrict text) +{ + // See if C++-style comments work. + // Iterate through items via the restricted pointer. + // Also check for declarations in for loops. + for (unsigned int i = 0; *(text+i) != '\0'; ++i) + continue; + return 0; +} + +// Check varargs and va_copy. +static void +test_varargs (const char *format, ...) +{ + va_list args; + va_start (args, format); + va_list args_copy; + va_copy (args_copy, args); + + const char *str; + int number; + float fnumber; + + while (*format) + { + switch (*format++) + { + case 's': // string + str = va_arg (args_copy, const char *); + break; + case 'd': // int + number = va_arg (args_copy, int); + break; + case 'f': // float + fnumber = va_arg (args_copy, double); + break; + default: + break; + } + } + va_end (args_copy); + va_end (args); +} + +int +main () +{ + + // Check bool. + _Bool success = false; + + // Check restrict. + if (test_restrict ("String literal") == 0) + success = true; + char *restrict newvar = "Another string"; + + // Check varargs. + test_varargs ("s, d' f .", "string", 65, 34.234); + test_varargs_macros (); + + // Check flexible array members. + struct incomplete_array *ia = + malloc (sizeof (struct incomplete_array) + (sizeof (double) * 10)); + ia->datasize = 10; + for (int i = 0; i < ia->datasize; ++i) + ia->data[i] = i * 1.234; + + // Check named initializers. + struct named_init ni = { + .number = 34, + .name = L"Test wide string", + .average = 543.34343, + }; + + ni.number = 58; + + int dynamic_array[ni.number]; + dynamic_array[ni.number - 1] = 543; + + // work around unused variable warnings + return (!success || bignum == 0LL || ubignum == 0uLL || newvar[0] == 'x' + || dynamic_array[ni.number - 1] != 543); + + ; + return 0; +} _ACEOF -for ac_arg in '' -std=gnu99 -std=c99 -c99 -qlanglvl=extc1x -qlanglvl=extc99 -AC99 -D_STDC_C99= +for ac_arg in '' -std=gnu99 -std=c99 -c99 -AC99 -D_STDC_C99= -qlanglvl=extc99 do CC="$ac_save_CC $ac_arg" - if ac_fn_c_try_compile "$LINENO" -then : + if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_c99=$ac_arg fi -rm -f core conftest.err conftest.$ac_objext conftest.beam +rm -f core conftest.err conftest.$ac_objext test "x$ac_cv_prog_cc_c99" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC + fi +# AC_CACHE_VAL +case "x$ac_cv_prog_cc_c99" in + x) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 +$as_echo "none needed" >&6; } ;; + xno) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 +$as_echo "unsupported" >&6; } ;; + *) + CC="$CC $ac_cv_prog_cc_c99" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c99" >&5 +$as_echo "$ac_cv_prog_cc_c99" >&6; } ;; +esac +if test "x$ac_cv_prog_cc_c99" != xno; then : -if test "x$ac_cv_prog_cc_c99" = xno -then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 -printf "%s\n" "unsupported" >&6; } -else $as_nop - if test "x$ac_cv_prog_cc_c99" = x -then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 -printf "%s\n" "none needed" >&6; } -else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c99" >&5 -printf "%s\n" "$ac_cv_prog_cc_c99" >&6; } - CC="$CC $ac_cv_prog_cc_c99" -fi - ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c99 - ac_prog_cc_stdc=c99 -fi -fi -if test x$ac_prog_cc_stdc = xno -then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C89 features" >&5 -printf %s "checking for $CC option to enable C89 features... " >&6; } -if test ${ac_cv_prog_cc_c89+y} -then : - printf %s "(cached) " >&6 -else $as_nop - ac_cv_prog_cc_c89=no -ac_save_CC=$CC -cat confdefs.h - <<_ACEOF >conftest.$ac_ext +fi + + + + + # check for macro defined in 2.69b + +# Note macro AC_PROG_CC_C99 is added in autoconf 2.60. + + + + +if test "x$ac_cv_prog_cc_c99" = "xno"; then : + + as_fn_error $? "*** $PACKAGE_NAME requires a C99 capable compiler ***" "$LINENO" 5 + +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 +$as_echo_n "checking how to run the C preprocessor... " >&6; } +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then + if ${ac_cv_prog_CPP+:} false; then : + $as_echo_n "(cached) " >&6 +else + # Double quotes because CPP needs to be expanded + for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" + do + ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -$ac_c_conftest_c89_program +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error _ACEOF -for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" -do - CC="$ac_save_CC $ac_arg" - if ac_fn_c_try_compile "$LINENO" -then : - ac_cv_prog_cc_c89=$ac_arg +if ac_fn_c_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue fi -rm -f core conftest.err conftest.$ac_objext conftest.beam - test "x$ac_cv_prog_cc_c89" != "xno" && break +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + done -rm -f conftest.$ac_ext -CC=$ac_save_CC +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + break +fi + + done + ac_cv_prog_CPP=$CPP + +fi + CPP=$ac_cv_prog_CPP +else + ac_cv_prog_CPP=$CPP fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 +$as_echo "$CPP" >&6; } +ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : -if test "x$ac_cv_prog_cc_c89" = xno -then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 -printf "%s\n" "unsupported" >&6; } -else $as_nop - if test "x$ac_cv_prog_cc_c89" = x -then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 -printf "%s\n" "none needed" >&6; } -else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 -printf "%s\n" "$ac_cv_prog_cc_c89" >&6; } - CC="$CC $ac_cv_prog_cc_c89" +else + # Broken: fails on valid input. +continue fi - ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c89 - ac_prog_cc_stdc=c89 +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details" "$LINENO" 5; } fi ac_ext=c @@ -3705,145 +3936,270 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu -# XXX relax this after reimplementing logit() etc. -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $CC supports C99-style variadic macros" >&5 -printf %s "checking if $CC supports C99-style variadic macros... " >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 +$as_echo_n "checking for grep that handles long lines and -e... " >&6; } +if ${ac_cv_path_GREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$GREP"; then + ac_path_GREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in grep ggrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_GREP" || continue +# Check for GNU ac_path_GREP and select it if it is found. + # Check for GNU $ac_path_GREP +case `"$ac_path_GREP" --version 2>&1` in +*GNU*) + ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'GREP' >> "conftest.nl" + "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_GREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_GREP="$ac_path_GREP" + ac_path_GREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_GREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_GREP"; then + as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_GREP=$GREP +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 +$as_echo "$ac_cv_path_GREP" >&6; } + GREP="$ac_cv_path_GREP" + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 +$as_echo_n "checking for egrep... " >&6; } +if ${ac_cv_path_EGREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 + then ac_cv_path_EGREP="$GREP -E" + else + if test -z "$EGREP"; then + ac_path_EGREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in egrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_EGREP" || continue +# Check for GNU ac_path_EGREP and select it if it is found. + # Check for GNU $ac_path_EGREP +case `"$ac_path_EGREP" --version 2>&1` in +*GNU*) + ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'EGREP' >> "conftest.nl" + "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_EGREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_EGREP="$ac_path_EGREP" + ac_path_EGREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_EGREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_EGREP"; then + as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_EGREP=$EGREP +fi + + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 +$as_echo "$ac_cv_path_EGREP" >&6; } + EGREP="$ac_cv_path_EGREP" -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -int f(int a, int b, int c) { return a + b + c; } -#define F(a, ...) f(a, __VA_ARGS__) +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 +$as_echo_n "checking for ANSI C header files... " >&6; } +if ${ac_cv_header_stdc+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#include +#include int -main (void) +main () { -return F(1, 2, -3); + ; return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO" -then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } -else $as_nop - as_fn_error $? "*** OpenSSH requires support for C99-style variadic macros" "$LINENO" 5 - +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_header_stdc=yes +else + ac_cv_header_stdc=no fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext - - +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include - # Make sure we can run config.sub. -$SHELL "${ac_aux_dir}config.sub" sun4 >/dev/null 2>&1 || - as_fn_error $? "cannot run $SHELL ${ac_aux_dir}config.sub" "$LINENO" 5 +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "memchr" >/dev/null 2>&1; then : -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking build system type" >&5 -printf %s "checking build system type... " >&6; } -if test ${ac_cv_build+y} -then : - printf %s "(cached) " >&6 -else $as_nop - ac_build_alias=$build_alias -test "x$ac_build_alias" = x && - ac_build_alias=`$SHELL "${ac_aux_dir}config.guess"` -test "x$ac_build_alias" = x && - as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5 -ac_cv_build=`$SHELL "${ac_aux_dir}config.sub" $ac_build_alias` || - as_fn_error $? "$SHELL ${ac_aux_dir}config.sub $ac_build_alias failed" "$LINENO" 5 +else + ac_cv_header_stdc=no +fi +rm -f conftest* fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5 -printf "%s\n" "$ac_cv_build" >&6; } -case $ac_cv_build in -*-*-*) ;; -*) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;; -esac -build=$ac_cv_build -ac_save_IFS=$IFS; IFS='-' -set x $ac_cv_build -shift -build_cpu=$1 -build_vendor=$2 -shift; shift -# Remember, the first character of IFS is used to create $*, -# except with old shells: -build_os=$* -IFS=$ac_save_IFS -case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "free" >/dev/null 2>&1; then : -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking host system type" >&5 -printf %s "checking host system type... " >&6; } -if test ${ac_cv_host+y} -then : - printf %s "(cached) " >&6 -else $as_nop - if test "x$host_alias" = x; then - ac_cv_host=$ac_cv_build else - ac_cv_host=`$SHELL "${ac_aux_dir}config.sub" $host_alias` || - as_fn_error $? "$SHELL ${ac_aux_dir}config.sub $host_alias failed" "$LINENO" 5 + ac_cv_header_stdc=no fi +rm -f conftest* fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5 -printf "%s\n" "$ac_cv_host" >&6; } -case $ac_cv_host in -*-*-*) ;; -*) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;; -esac -host=$ac_cv_host -ac_save_IFS=$IFS; IFS='-' -set x $ac_cv_host -shift -host_cpu=$1 -host_vendor=$2 -shift; shift -# Remember, the first character of IFS is used to create $*, -# except with old shells: -host_os=$* -IFS=$ac_save_IFS -case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. + if test "$cross_compiling" = yes; then : + : +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#if ((' ' & 0x0FF) == 0x020) +# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#else +# define ISLOWER(c) \ + (('a' <= (c) && (c) <= 'i') \ + || ('j' <= (c) && (c) <= 'r') \ + || ('s' <= (c) && (c) <= 'z')) +# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) +#endif -ac_header= ac_cache= -for ac_item in $ac_header_c_list -do - if test $ac_cache; then - ac_fn_c_check_header_compile "$LINENO" $ac_header ac_cv_header_$ac_cache "$ac_includes_default" - if eval test \"x\$ac_cv_header_$ac_cache\" = xyes; then - printf "%s\n" "#define $ac_item 1" >> confdefs.h - fi - ac_header= ac_cache= - elif test $ac_header; then - ac_cache=$ac_item - else - ac_header=$ac_item - fi -done - +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int +main () +{ + int i; + for (i = 0; i < 256; i++) + if (XOR (islower (i), ISLOWER (i)) + || toupper (i) != TOUPPER (i)) + return 2; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : +else + ac_cv_header_stdc=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 +$as_echo "$ac_cv_header_stdc" >&6; } +if test $ac_cv_header_stdc = yes; then +$as_echo "#define STDC_HEADERS 1" >>confdefs.h +fi +# On IRIX 5.3, sys/types and inttypes.h are conflicting. +for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ + inttypes.h stdint.h unistd.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default +" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF +fi -if test $ac_cv_header_stdlib_h = yes && test $ac_cv_header_string_h = yes -then : +done -printf "%s\n" "#define STDC_HEADERS 1" >>confdefs.h -fi - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether byte ordering is bigendian" >&5 -printf %s "checking whether byte ordering is bigendian... " >&6; } -if test ${ac_cv_c_bigendian+y} -then : - printf %s "(cached) " >&6 -else $as_nop + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether byte ordering is bigendian" >&5 +$as_echo_n "checking whether byte ordering is bigendian... " >&6; } +if ${ac_cv_c_bigendian+:} false; then : + $as_echo_n "(cached) " >&6 +else ac_cv_c_bigendian=unknown # See if we're dealing with a universal compiler. cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -3854,8 +4210,7 @@ typedef int dummy; _ACEOF -if ac_fn_c_try_compile "$LINENO" -then : +if ac_fn_c_try_compile "$LINENO"; then : # Check for potential -arch flags. It is not universal unless # there are at least two -arch flags with different values. @@ -3879,7 +4234,7 @@ fi done fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext if test $ac_cv_c_bigendian = unknown; then # See if sys/param.h defines the BYTE_ORDER macro. cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -3888,7 +4243,7 @@ #include int -main (void) +main () { #if ! (defined BYTE_ORDER && defined BIG_ENDIAN \ && defined LITTLE_ENDIAN && BYTE_ORDER && BIG_ENDIAN \ @@ -3900,8 +4255,7 @@ return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO" -then : +if ac_fn_c_try_compile "$LINENO"; then : # It does; now see whether it defined to BIG_ENDIAN or not. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -3909,7 +4263,7 @@ #include int -main (void) +main () { #if BYTE_ORDER != BIG_ENDIAN not big endian @@ -3919,15 +4273,14 @@ return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO" -then : +if ac_fn_c_try_compile "$LINENO"; then : ac_cv_c_bigendian=yes -else $as_nop +else ac_cv_c_bigendian=no fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi if test $ac_cv_c_bigendian = unknown; then # See if defines _LITTLE_ENDIAN or _BIG_ENDIAN (e.g., Solaris). @@ -3936,7 +4289,7 @@ #include int -main (void) +main () { #if ! (defined _LITTLE_ENDIAN || defined _BIG_ENDIAN) bogus endian macros @@ -3946,15 +4299,14 @@ return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO" -then : +if ac_fn_c_try_compile "$LINENO"; then : # It does; now see whether it defined to _BIG_ENDIAN or not. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int -main (void) +main () { #ifndef _BIG_ENDIAN not big endian @@ -3964,33 +4316,31 @@ return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO" -then : +if ac_fn_c_try_compile "$LINENO"; then : ac_cv_c_bigendian=yes -else $as_nop +else ac_cv_c_bigendian=no fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi if test $ac_cv_c_bigendian = unknown; then # Compile a test program. - if test "$cross_compiling" = yes -then : + if test "$cross_compiling" = yes; then : # Try to guess by grepping values from an object file. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -unsigned short int ascii_mm[] = +short int ascii_mm[] = { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 }; - unsigned short int ascii_ii[] = + short int ascii_ii[] = { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 }; int use_ascii (int i) { return ascii_mm[i] + ascii_ii[i]; } - unsigned short int ebcdic_ii[] = + short int ebcdic_ii[] = { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 }; - unsigned short int ebcdic_mm[] = + short int ebcdic_mm[] = { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 }; int use_ebcdic (int i) { return ebcdic_mm[i] + ebcdic_ii[i]; @@ -3998,15 +4348,14 @@ extern int foo; int -main (void) +main () { return use_ascii (foo) == use_ebcdic (foo); ; return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO" -then : +if ac_fn_c_try_compile "$LINENO"; then : if grep BIGenDianSyS conftest.$ac_objext >/dev/null; then ac_cv_c_bigendian=yes fi @@ -4019,13 +4368,13 @@ fi fi fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext -else $as_nop +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_includes_default int -main (void) +main () { /* Are we little or big endian? From Harbison&Steele. */ @@ -4041,10 +4390,9 @@ return 0; } _ACEOF -if ac_fn_c_try_run "$LINENO" -then : +if ac_fn_c_try_run "$LINENO"; then : ac_cv_c_bigendian=no -else $as_nop +else ac_cv_c_bigendian=yes fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ @@ -4053,17 +4401,17 @@ fi fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_bigendian" >&5 -printf "%s\n" "$ac_cv_c_bigendian" >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_bigendian" >&5 +$as_echo "$ac_cv_c_bigendian" >&6; } case $ac_cv_c_bigendian in #( yes) - printf "%s\n" "#define WORDS_BIGENDIAN 1" >>confdefs.h + $as_echo "#define WORDS_BIGENDIAN 1" >>confdefs.h ;; #( no) ;; #( universal) -printf "%s\n" "#define AC_APPLE_UNIVERSAL_BUILD 1" >>confdefs.h +$as_echo "#define AC_APPLE_UNIVERSAL_BUILD 1" >>confdefs.h ;; #( *) @@ -4077,12 +4425,11 @@ do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -printf %s "checking for $ac_word... " >&6; } -if test ${ac_cv_prog_AWK+y} -then : - printf %s "(cached) " >&6 -else $as_nop +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_AWK+:} false; then : + $as_echo_n "(cached) " >&6 +else if test -n "$AWK"; then ac_cv_prog_AWK="$AWK" # Let the user override the test. else @@ -4090,15 +4437,11 @@ for as_dir in $PATH do IFS=$as_save_IFS - case $as_dir in #((( - '') as_dir=./ ;; - */) ;; - *) as_dir=$as_dir/ ;; - esac + test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_AWK="$ac_prog" - printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done @@ -4109,11 +4452,11 @@ fi AWK=$ac_cv_prog_AWK if test -n "$AWK"; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5 -printf "%s\n" "$AWK" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5 +$as_echo "$AWK" >&6; } else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } fi @@ -4125,36 +4468,40 @@ ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 -printf %s "checking how to run the C preprocessor... " >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 +$as_echo_n "checking how to run the C preprocessor... " >&6; } # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= fi if test -z "$CPP"; then - if test ${ac_cv_prog_CPP+y} -then : - printf %s "(cached) " >&6 -else $as_nop - # Double quotes because $CC needs to be expanded - for CPP in "$CC -E" "$CC -E -traditional-cpp" cpp /lib/cpp + if ${ac_cv_prog_CPP+:} false; then : + $as_echo_n "(cached) " >&6 +else + # Double quotes because CPP needs to be expanded + for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" do ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -#include +#ifdef __STDC__ +# include +#else +# include +#endif Syntax error _ACEOF -if ac_fn_c_try_cpp "$LINENO" -then : +if ac_fn_c_try_cpp "$LINENO"; then : -else $as_nop +else # Broken: fails on valid input. continue fi @@ -4166,11 +4513,10 @@ /* end confdefs.h. */ #include _ACEOF -if ac_fn_c_try_cpp "$LINENO" -then : +if ac_fn_c_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue -else $as_nop +else # Passes both tests. ac_preproc_ok=: break @@ -4180,8 +4526,7 @@ done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext -if $ac_preproc_ok -then : +if $ac_preproc_ok; then : break fi @@ -4193,24 +4538,29 @@ else ac_cv_prog_CPP=$CPP fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 -printf "%s\n" "$CPP" >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 +$as_echo "$CPP" >&6; } ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -#include +#ifdef __STDC__ +# include +#else +# include +#endif Syntax error _ACEOF -if ac_fn_c_try_cpp "$LINENO" -then : +if ac_fn_c_try_cpp "$LINENO"; then : -else $as_nop +else # Broken: fails on valid input. continue fi @@ -4222,11 +4572,10 @@ /* end confdefs.h. */ #include _ACEOF -if ac_fn_c_try_cpp "$LINENO" -then : +if ac_fn_c_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue -else $as_nop +else # Passes both tests. ac_preproc_ok=: break @@ -4236,12 +4585,11 @@ done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext -if $ac_preproc_ok -then : +if $ac_preproc_ok; then : -else $as_nop - { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "C preprocessor \"$CPP\" fails sanity check See \`config.log' for more details" "$LINENO" 5; } fi @@ -4255,12 +4603,11 @@ if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. set dummy ${ac_tool_prefix}ranlib; ac_word=$2 -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -printf %s "checking for $ac_word... " >&6; } -if test ${ac_cv_prog_RANLIB+y} -then : - printf %s "(cached) " >&6 -else $as_nop +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_RANLIB+:} false; then : + $as_echo_n "(cached) " >&6 +else if test -n "$RANLIB"; then ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. else @@ -4268,15 +4615,11 @@ for as_dir in $PATH do IFS=$as_save_IFS - case $as_dir in #((( - '') as_dir=./ ;; - */) ;; - *) as_dir=$as_dir/ ;; - esac + test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" - printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done @@ -4287,11 +4630,11 @@ fi RANLIB=$ac_cv_prog_RANLIB if test -n "$RANLIB"; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5 -printf "%s\n" "$RANLIB" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5 +$as_echo "$RANLIB" >&6; } else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } fi @@ -4300,12 +4643,11 @@ ac_ct_RANLIB=$RANLIB # Extract the first word of "ranlib", so it can be a program name with args. set dummy ranlib; ac_word=$2 -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -printf %s "checking for $ac_word... " >&6; } -if test ${ac_cv_prog_ac_ct_RANLIB+y} -then : - printf %s "(cached) " >&6 -else $as_nop +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_RANLIB+:} false; then : + $as_echo_n "(cached) " >&6 +else if test -n "$ac_ct_RANLIB"; then ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. else @@ -4313,15 +4655,11 @@ for as_dir in $PATH do IFS=$as_save_IFS - case $as_dir in #((( - '') as_dir=./ ;; - */) ;; - *) as_dir=$as_dir/ ;; - esac + test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_RANLIB="ranlib" - printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done @@ -4332,11 +4670,11 @@ fi ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB if test -n "$ac_ct_RANLIB"; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5 -printf "%s\n" "$ac_ct_RANLIB" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5 +$as_echo "$ac_ct_RANLIB" >&6; } else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } fi if test "x$ac_ct_RANLIB" = x; then @@ -4344,8 +4682,8 @@ else case $cross_compiling:$ac_tool_warned in yes:) -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac RANLIB=$ac_ct_RANLIB @@ -4354,8 +4692,7 @@ RANLIB="$ac_cv_prog_RANLIB" fi - - # Find a good install program. We prefer a C program (faster), +# Find a good install program. We prefer a C program (faster), # so one script is as good as another. But avoid the broken or # incompatible versions: # SysV /etc/install, /usr/sbin/install @@ -4369,25 +4706,20 @@ # OS/2's system install, which has a completely different semantic # ./install, which can be erroneously created by make from ./install.sh. # Reject install programs that cannot install multiple files. -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5 -printf %s "checking for a BSD-compatible install... " >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5 +$as_echo_n "checking for a BSD-compatible install... " >&6; } if test -z "$INSTALL"; then -if test ${ac_cv_path_install+y} -then : - printf %s "(cached) " >&6 -else $as_nop +if ${ac_cv_path_install+:} false; then : + $as_echo_n "(cached) " >&6 +else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS - case $as_dir in #((( - '') as_dir=./ ;; - */) ;; - *) as_dir=$as_dir/ ;; - esac - # Account for fact that we put trailing slashes in our PATH walk. -case $as_dir in #(( - ./ | /[cC]/* | \ + test -z "$as_dir" && as_dir=. + # Account for people who put trailing slashes in PATH elements. +case $as_dir/ in #(( + ./ | .// | /[cC]/* | \ /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \ /usr/ucb/* ) ;; @@ -4397,13 +4729,13 @@ # by default. for ac_prog in ginstall scoinst install; do for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir$ac_prog$ac_exec_ext"; then + if as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then if test $ac_prog = install && - grep dspmsg "$as_dir$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # AIX install. It has an incompatible calling convention. : elif test $ac_prog = install && - grep pwplus "$as_dir$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # program-specific install script used by HP pwplus--don't use. : else @@ -4411,12 +4743,12 @@ echo one > conftest.one echo two > conftest.two mkdir conftest.dir - if "$as_dir$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir/" && + if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" && test -s conftest.one && test -s conftest.two && test -s conftest.dir/conftest.one && test -s conftest.dir/conftest.two then - ac_cv_path_install="$as_dir$ac_prog$ac_exec_ext -c" + ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" break 3 fi fi @@ -4432,7 +4764,7 @@ rm -rf conftest.one conftest.two conftest.dir fi - if test ${ac_cv_path_install+y}; then + if test "${ac_cv_path_install+set}" = set; then INSTALL=$ac_cv_path_install else # As a last resort, use the slow shell script. Don't cache a @@ -4442,8 +4774,8 @@ INSTALL=$ac_install_sh fi fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5 -printf "%s\n" "$INSTALL" >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5 +$as_echo "$INSTALL" >&6; } # Use test -z because SunOS4 sh mishandles braces in ${var-val}. # It thinks the first close brace ends the variable substitution. @@ -4453,81 +4785,11 @@ test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 -printf %s "checking for grep that handles long lines and -e... " >&6; } -if test ${ac_cv_path_GREP+y} -then : - printf %s "(cached) " >&6 -else $as_nop - if test -z "$GREP"; then - ac_path_GREP_found=false - # Loop through the user's path and test for each of PROGNAME-LIST - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin -do - IFS=$as_save_IFS - case $as_dir in #((( - '') as_dir=./ ;; - */) ;; - *) as_dir=$as_dir/ ;; - esac - for ac_prog in grep ggrep - do - for ac_exec_ext in '' $ac_executable_extensions; do - ac_path_GREP="$as_dir$ac_prog$ac_exec_ext" - as_fn_executable_p "$ac_path_GREP" || continue -# Check for GNU ac_path_GREP and select it if it is found. - # Check for GNU $ac_path_GREP -case `"$ac_path_GREP" --version 2>&1` in -*GNU*) - ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; -*) - ac_count=0 - printf %s 0123456789 >"conftest.in" - while : - do - cat "conftest.in" "conftest.in" >"conftest.tmp" - mv "conftest.tmp" "conftest.in" - cp "conftest.in" "conftest.nl" - printf "%s\n" 'GREP' >> "conftest.nl" - "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break - diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break - as_fn_arith $ac_count + 1 && ac_count=$as_val - if test $ac_count -gt ${ac_path_GREP_max-0}; then - # Best one so far, save it but keep looking for a better one - ac_cv_path_GREP="$ac_path_GREP" - ac_path_GREP_max=$ac_count - fi - # 10*(2^10) chars as input seems more than enough - test $ac_count -gt 10 && break - done - rm -f conftest.in conftest.tmp conftest.nl conftest.out;; -esac - - $ac_path_GREP_found && break 3 - done - done - done -IFS=$as_save_IFS - if test -z "$ac_cv_path_GREP"; then - as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 - fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 +$as_echo_n "checking for egrep... " >&6; } +if ${ac_cv_path_EGREP+:} false; then : + $as_echo_n "(cached) " >&6 else - ac_cv_path_GREP=$GREP -fi - -fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 -printf "%s\n" "$ac_cv_path_GREP" >&6; } - GREP="$ac_cv_path_GREP" - - -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 -printf %s "checking for egrep... " >&6; } -if test ${ac_cv_path_EGREP+y} -then : - printf %s "(cached) " >&6 -else $as_nop if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 then ac_cv_path_EGREP="$GREP -E" else @@ -4538,15 +4800,10 @@ for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS - case $as_dir in #((( - '') as_dir=./ ;; - */) ;; - *) as_dir=$as_dir/ ;; - esac - for ac_prog in egrep - do + test -z "$as_dir" && as_dir=. + for ac_prog in egrep; do for ac_exec_ext in '' $ac_executable_extensions; do - ac_path_EGREP="$as_dir$ac_prog$ac_exec_ext" + ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_EGREP" || continue # Check for GNU ac_path_EGREP and select it if it is found. # Check for GNU $ac_path_EGREP @@ -4555,13 +4812,13 @@ ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; *) ac_count=0 - printf %s 0123456789 >"conftest.in" + $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" - printf "%s\n" 'EGREP' >> "conftest.nl" + $as_echo 'EGREP' >> "conftest.nl" "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val @@ -4590,70 +4847,21 @@ fi fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 -printf "%s\n" "$ac_cv_path_EGREP" >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 +$as_echo "$ac_cv_path_EGREP" >&6; } EGREP="$ac_cv_path_EGREP" - - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for a race-free mkdir -p" >&5 -printf %s "checking for a race-free mkdir -p... " >&6; } -if test -z "$MKDIR_P"; then - if test ${ac_cv_path_mkdir+y} -then : - printf %s "(cached) " >&6 -else $as_nop - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin -do - IFS=$as_save_IFS - case $as_dir in #((( - '') as_dir=./ ;; - */) ;; - *) as_dir=$as_dir/ ;; - esac - for ac_prog in mkdir gmkdir; do - for ac_exec_ext in '' $ac_executable_extensions; do - as_fn_executable_p "$as_dir$ac_prog$ac_exec_ext" || continue - case `"$as_dir$ac_prog$ac_exec_ext" --version 2>&1` in #( - 'mkdir ('*'coreutils) '* | \ - 'BusyBox '* | \ - 'mkdir (fileutils) '4.1*) - ac_cv_path_mkdir=$as_dir$ac_prog$ac_exec_ext - break 3;; - esac - done - done - done -IFS=$as_save_IFS - -fi - - test -d ./--version && rmdir ./--version - if test ${ac_cv_path_mkdir+y}; then - MKDIR_P="$ac_cv_path_mkdir -p" - else - # As a last resort, use the slow shell script. Don't cache a - # value for MKDIR_P within a source directory, because that will - # break other packages using the cache if that directory is - # removed, or if the value is a relative name. - MKDIR_P="$ac_install_sh -d" - fi -fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $MKDIR_P" >&5 -printf "%s\n" "$MKDIR_P" >&6; } - if test -n "$ac_tool_prefix"; then for ac_prog in ar do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -printf %s "checking for $ac_word... " >&6; } -if test ${ac_cv_prog_AR+y} -then : - printf %s "(cached) " >&6 -else $as_nop +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_AR+:} false; then : + $as_echo_n "(cached) " >&6 +else if test -n "$AR"; then ac_cv_prog_AR="$AR" # Let the user override the test. else @@ -4661,15 +4869,11 @@ for as_dir in $PATH do IFS=$as_save_IFS - case $as_dir in #((( - '') as_dir=./ ;; - */) ;; - *) as_dir=$as_dir/ ;; - esac + test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_AR="$ac_tool_prefix$ac_prog" - printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done @@ -4680,11 +4884,11 @@ fi AR=$ac_cv_prog_AR if test -n "$AR"; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $AR" >&5 -printf "%s\n" "$AR" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5 +$as_echo "$AR" >&6; } else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } fi @@ -4697,12 +4901,11 @@ do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -printf %s "checking for $ac_word... " >&6; } -if test ${ac_cv_prog_ac_ct_AR+y} -then : - printf %s "(cached) " >&6 -else $as_nop +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_AR+:} false; then : + $as_echo_n "(cached) " >&6 +else if test -n "$ac_ct_AR"; then ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test. else @@ -4710,15 +4913,11 @@ for as_dir in $PATH do IFS=$as_save_IFS - case $as_dir in #((( - '') as_dir=./ ;; - */) ;; - *) as_dir=$as_dir/ ;; - esac + test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_AR="$ac_prog" - printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done @@ -4729,11 +4928,11 @@ fi ac_ct_AR=$ac_cv_prog_ac_ct_AR if test -n "$ac_ct_AR"; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5 -printf "%s\n" "$ac_ct_AR" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5 +$as_echo "$ac_ct_AR" >&6; } else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } fi @@ -4745,8 +4944,8 @@ else case $cross_compiling:$ac_tool_warned in yes:) -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac AR=$ac_ct_AR @@ -4755,12 +4954,11 @@ # Extract the first word of "cat", so it can be a program name with args. set dummy cat; ac_word=$2 -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -printf %s "checking for $ac_word... " >&6; } -if test ${ac_cv_path_CAT+y} -then : - printf %s "(cached) " >&6 -else $as_nop +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_CAT+:} false; then : + $as_echo_n "(cached) " >&6 +else case $CAT in [\\/]* | ?:[\\/]*) ac_cv_path_CAT="$CAT" # Let the user override the test with a path. @@ -4770,15 +4968,11 @@ for as_dir in $PATH do IFS=$as_save_IFS - case $as_dir in #((( - '') as_dir=./ ;; - */) ;; - *) as_dir=$as_dir/ ;; - esac + test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then - ac_cv_path_CAT="$as_dir$ac_word$ac_exec_ext" - printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_CAT="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done @@ -4790,22 +4984,21 @@ fi CAT=$ac_cv_path_CAT if test -n "$CAT"; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CAT" >&5 -printf "%s\n" "$CAT" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CAT" >&5 +$as_echo "$CAT" >&6; } else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } fi # Extract the first word of "kill", so it can be a program name with args. set dummy kill; ac_word=$2 -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -printf %s "checking for $ac_word... " >&6; } -if test ${ac_cv_path_KILL+y} -then : - printf %s "(cached) " >&6 -else $as_nop +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_KILL+:} false; then : + $as_echo_n "(cached) " >&6 +else case $KILL in [\\/]* | ?:[\\/]*) ac_cv_path_KILL="$KILL" # Let the user override the test with a path. @@ -4815,15 +5008,11 @@ for as_dir in $PATH do IFS=$as_save_IFS - case $as_dir in #((( - '') as_dir=./ ;; - */) ;; - *) as_dir=$as_dir/ ;; - esac + test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then - ac_cv_path_KILL="$as_dir$ac_word$ac_exec_ext" - printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_KILL="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done @@ -4835,22 +5024,21 @@ fi KILL=$ac_cv_path_KILL if test -n "$KILL"; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $KILL" >&5 -printf "%s\n" "$KILL" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $KILL" >&5 +$as_echo "$KILL" >&6; } else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } fi # Extract the first word of "sed", so it can be a program name with args. set dummy sed; ac_word=$2 -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -printf %s "checking for $ac_word... " >&6; } -if test ${ac_cv_path_SED+y} -then : - printf %s "(cached) " >&6 -else $as_nop +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_SED+:} false; then : + $as_echo_n "(cached) " >&6 +else case $SED in [\\/]* | ?:[\\/]*) ac_cv_path_SED="$SED" # Let the user override the test with a path. @@ -4860,15 +5048,11 @@ for as_dir in $PATH do IFS=$as_save_IFS - case $as_dir in #((( - '') as_dir=./ ;; - */) ;; - *) as_dir=$as_dir/ ;; - esac + test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then - ac_cv_path_SED="$as_dir$ac_word$ac_exec_ext" - printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_SED="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done @@ -4880,202 +5064,21 @@ fi SED=$ac_cv_path_SED if test -n "$SED"; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $SED" >&5 -printf "%s\n" "$SED" >&6; } -else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } -fi - - -# Extract the first word of "bash", so it can be a program name with args. -set dummy bash; ac_word=$2 -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -printf %s "checking for $ac_word... " >&6; } -if test ${ac_cv_path_TEST_MINUS_S_SH+y} -then : - printf %s "(cached) " >&6 -else $as_nop - case $TEST_MINUS_S_SH in - [\\/]* | ?:[\\/]*) - ac_cv_path_TEST_MINUS_S_SH="$TEST_MINUS_S_SH" # Let the user override the test with a path. - ;; - *) - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - case $as_dir in #((( - '') as_dir=./ ;; - */) ;; - *) as_dir=$as_dir/ ;; - esac - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then - ac_cv_path_TEST_MINUS_S_SH="$as_dir$ac_word$ac_exec_ext" - printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - - ;; -esac -fi -TEST_MINUS_S_SH=$ac_cv_path_TEST_MINUS_S_SH -if test -n "$TEST_MINUS_S_SH"; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $TEST_MINUS_S_SH" >&5 -printf "%s\n" "$TEST_MINUS_S_SH" >&6; } -else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } -fi - - -# Extract the first word of "ksh", so it can be a program name with args. -set dummy ksh; ac_word=$2 -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -printf %s "checking for $ac_word... " >&6; } -if test ${ac_cv_path_TEST_MINUS_S_SH+y} -then : - printf %s "(cached) " >&6 -else $as_nop - case $TEST_MINUS_S_SH in - [\\/]* | ?:[\\/]*) - ac_cv_path_TEST_MINUS_S_SH="$TEST_MINUS_S_SH" # Let the user override the test with a path. - ;; - *) - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - case $as_dir in #((( - '') as_dir=./ ;; - */) ;; - *) as_dir=$as_dir/ ;; - esac - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then - ac_cv_path_TEST_MINUS_S_SH="$as_dir$ac_word$ac_exec_ext" - printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - - ;; -esac -fi -TEST_MINUS_S_SH=$ac_cv_path_TEST_MINUS_S_SH -if test -n "$TEST_MINUS_S_SH"; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $TEST_MINUS_S_SH" >&5 -printf "%s\n" "$TEST_MINUS_S_SH" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $SED" >&5 +$as_echo "$SED" >&6; } else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } fi # Extract the first word of "sh", so it can be a program name with args. set dummy sh; ac_word=$2 -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -printf %s "checking for $ac_word... " >&6; } -if test ${ac_cv_path_TEST_MINUS_S_SH+y} -then : - printf %s "(cached) " >&6 -else $as_nop - case $TEST_MINUS_S_SH in - [\\/]* | ?:[\\/]*) - ac_cv_path_TEST_MINUS_S_SH="$TEST_MINUS_S_SH" # Let the user override the test with a path. - ;; - *) - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - case $as_dir in #((( - '') as_dir=./ ;; - */) ;; - *) as_dir=$as_dir/ ;; - esac - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then - ac_cv_path_TEST_MINUS_S_SH="$as_dir$ac_word$ac_exec_ext" - printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - - ;; -esac -fi -TEST_MINUS_S_SH=$ac_cv_path_TEST_MINUS_S_SH -if test -n "$TEST_MINUS_S_SH"; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $TEST_MINUS_S_SH" >&5 -printf "%s\n" "$TEST_MINUS_S_SH" >&6; } -else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } -fi - - -# Extract the first word of "bash", so it can be a program name with args. -set dummy bash; ac_word=$2 -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -printf %s "checking for $ac_word... " >&6; } -if test ${ac_cv_path_SH+y} -then : - printf %s "(cached) " >&6 -else $as_nop - case $SH in - [\\/]* | ?:[\\/]*) - ac_cv_path_SH="$SH" # Let the user override the test with a path. - ;; - *) - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - case $as_dir in #((( - '') as_dir=./ ;; - */) ;; - *) as_dir=$as_dir/ ;; - esac - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then - ac_cv_path_SH="$as_dir$ac_word$ac_exec_ext" - printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - - ;; -esac -fi -SH=$ac_cv_path_SH -if test -n "$SH"; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $SH" >&5 -printf "%s\n" "$SH" >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_SH+:} false; then : + $as_echo_n "(cached) " >&6 else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } -fi - - -# Extract the first word of "ksh", so it can be a program name with args. -set dummy ksh; ac_word=$2 -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -printf %s "checking for $ac_word... " >&6; } -if test ${ac_cv_path_SH+y} -then : - printf %s "(cached) " >&6 -else $as_nop case $SH in [\\/]* | ?:[\\/]*) ac_cv_path_SH="$SH" # Let the user override the test with a path. @@ -5085,15 +5088,11 @@ for as_dir in $PATH do IFS=$as_save_IFS - case $as_dir in #((( - '') as_dir=./ ;; - */) ;; - *) as_dir=$as_dir/ ;; - esac + test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then - ac_cv_path_SH="$as_dir$ac_word$ac_exec_ext" - printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_SH="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done @@ -5105,67 +5104,21 @@ fi SH=$ac_cv_path_SH if test -n "$SH"; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $SH" >&5 -printf "%s\n" "$SH" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $SH" >&5 +$as_echo "$SH" >&6; } else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } -fi - - -# Extract the first word of "sh", so it can be a program name with args. -set dummy sh; ac_word=$2 -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -printf %s "checking for $ac_word... " >&6; } -if test ${ac_cv_path_SH+y} -then : - printf %s "(cached) " >&6 -else $as_nop - case $SH in - [\\/]* | ?:[\\/]*) - ac_cv_path_SH="$SH" # Let the user override the test with a path. - ;; - *) - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - case $as_dir in #((( - '') as_dir=./ ;; - */) ;; - *) as_dir=$as_dir/ ;; - esac - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then - ac_cv_path_SH="$as_dir$ac_word$ac_exec_ext" - printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - - ;; -esac -fi -SH=$ac_cv_path_SH -if test -n "$SH"; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $SH" >&5 -printf "%s\n" "$SH" >&6; } -else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } fi # Extract the first word of "groff", so it can be a program name with args. set dummy groff; ac_word=$2 -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -printf %s "checking for $ac_word... " >&6; } -if test ${ac_cv_path_GROFF+y} -then : - printf %s "(cached) " >&6 -else $as_nop +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_GROFF+:} false; then : + $as_echo_n "(cached) " >&6 +else case $GROFF in [\\/]* | ?:[\\/]*) ac_cv_path_GROFF="$GROFF" # Let the user override the test with a path. @@ -5175,15 +5128,11 @@ for as_dir in $PATH do IFS=$as_save_IFS - case $as_dir in #((( - '') as_dir=./ ;; - */) ;; - *) as_dir=$as_dir/ ;; - esac + test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then - ac_cv_path_GROFF="$as_dir$ac_word$ac_exec_ext" - printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_GROFF="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done @@ -5195,22 +5144,21 @@ fi GROFF=$ac_cv_path_GROFF if test -n "$GROFF"; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $GROFF" >&5 -printf "%s\n" "$GROFF" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GROFF" >&5 +$as_echo "$GROFF" >&6; } else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } fi # Extract the first word of "nroff awf", so it can be a program name with args. set dummy nroff awf; ac_word=$2 -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -printf %s "checking for $ac_word... " >&6; } -if test ${ac_cv_path_NROFF+y} -then : - printf %s "(cached) " >&6 -else $as_nop +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_NROFF+:} false; then : + $as_echo_n "(cached) " >&6 +else case $NROFF in [\\/]* | ?:[\\/]*) ac_cv_path_NROFF="$NROFF" # Let the user override the test with a path. @@ -5220,15 +5168,11 @@ for as_dir in $PATH do IFS=$as_save_IFS - case $as_dir in #((( - '') as_dir=./ ;; - */) ;; - *) as_dir=$as_dir/ ;; - esac + test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then - ac_cv_path_NROFF="$as_dir$ac_word$ac_exec_ext" - printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_NROFF="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done @@ -5240,22 +5184,21 @@ fi NROFF=$ac_cv_path_NROFF if test -n "$NROFF"; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $NROFF" >&5 -printf "%s\n" "$NROFF" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $NROFF" >&5 +$as_echo "$NROFF" >&6; } else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } fi # Extract the first word of "mandoc", so it can be a program name with args. set dummy mandoc; ac_word=$2 -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -printf %s "checking for $ac_word... " >&6; } -if test ${ac_cv_path_MANDOC+y} -then : - printf %s "(cached) " >&6 -else $as_nop +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_MANDOC+:} false; then : + $as_echo_n "(cached) " >&6 +else case $MANDOC in [\\/]* | ?:[\\/]*) ac_cv_path_MANDOC="$MANDOC" # Let the user override the test with a path. @@ -5265,15 +5208,11 @@ for as_dir in $PATH do IFS=$as_save_IFS - case $as_dir in #((( - '') as_dir=./ ;; - */) ;; - *) as_dir=$as_dir/ ;; - esac + test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then - ac_cv_path_MANDOC="$as_dir$ac_word$ac_exec_ext" - printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_MANDOC="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done @@ -5285,23 +5224,22 @@ fi MANDOC=$ac_cv_path_MANDOC if test -n "$MANDOC"; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $MANDOC" >&5 -printf "%s\n" "$MANDOC" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MANDOC" >&5 +$as_echo "$MANDOC" >&6; } else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args. set dummy ${ac_tool_prefix}pkg-config; ac_word=$2 -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -printf %s "checking for $ac_word... " >&6; } -if test ${ac_cv_path_PKGCONFIG+y} -then : - printf %s "(cached) " >&6 -else $as_nop +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_PKGCONFIG+:} false; then : + $as_echo_n "(cached) " >&6 +else case $PKGCONFIG in [\\/]* | ?:[\\/]*) ac_cv_path_PKGCONFIG="$PKGCONFIG" # Let the user override the test with a path. @@ -5311,15 +5249,11 @@ for as_dir in $PATH do IFS=$as_save_IFS - case $as_dir in #((( - '') as_dir=./ ;; - */) ;; - *) as_dir=$as_dir/ ;; - esac + test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then - ac_cv_path_PKGCONFIG="$as_dir$ac_word$ac_exec_ext" - printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_PKGCONFIG="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done @@ -5331,11 +5265,11 @@ fi PKGCONFIG=$ac_cv_path_PKGCONFIG if test -n "$PKGCONFIG"; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $PKGCONFIG" >&5 -printf "%s\n" "$PKGCONFIG" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PKGCONFIG" >&5 +$as_echo "$PKGCONFIG" >&6; } else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } fi @@ -5344,12 +5278,11 @@ ac_pt_PKGCONFIG=$PKGCONFIG # Extract the first word of "pkg-config", so it can be a program name with args. set dummy pkg-config; ac_word=$2 -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -printf %s "checking for $ac_word... " >&6; } -if test ${ac_cv_path_ac_pt_PKGCONFIG+y} -then : - printf %s "(cached) " >&6 -else $as_nop +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_ac_pt_PKGCONFIG+:} false; then : + $as_echo_n "(cached) " >&6 +else case $ac_pt_PKGCONFIG in [\\/]* | ?:[\\/]*) ac_cv_path_ac_pt_PKGCONFIG="$ac_pt_PKGCONFIG" # Let the user override the test with a path. @@ -5359,15 +5292,11 @@ for as_dir in $PATH do IFS=$as_save_IFS - case $as_dir in #((( - '') as_dir=./ ;; - */) ;; - *) as_dir=$as_dir/ ;; - esac + test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then - ac_cv_path_ac_pt_PKGCONFIG="$as_dir$ac_word$ac_exec_ext" - printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_ac_pt_PKGCONFIG="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done @@ -5379,11 +5308,11 @@ fi ac_pt_PKGCONFIG=$ac_cv_path_ac_pt_PKGCONFIG if test -n "$ac_pt_PKGCONFIG"; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_pt_PKGCONFIG" >&5 -printf "%s\n" "$ac_pt_PKGCONFIG" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_PKGCONFIG" >&5 +$as_echo "$ac_pt_PKGCONFIG" >&6; } else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } fi if test "x$ac_pt_PKGCONFIG" = x; then @@ -5391,8 +5320,8 @@ else case $cross_compiling:$ac_tool_warned in yes:) -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac PKGCONFIG=$ac_pt_PKGCONFIG @@ -5401,9 +5330,9 @@ PKGCONFIG="$ac_cv_path_PKGCONFIG" fi -TEST_SHELL=sh +if test -z "$MANFMT" ; then if test "x$MANDOC" != "x" ; then MANFMT="$MANDOC" elif test "x$NROFF" != "x" ; then @@ -5411,20 +5340,19 @@ elif test "x$GROFF" != "x" ; then MANFMT="$GROFF -mandoc -Tascii" else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: no manpage formatter found" >&5 -printf "%s\n" "$as_me: WARNING: no manpage formatter found" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: no manpage formatter found" >&5 +$as_echo "$as_me: WARNING: no manpage formatter found" >&2;} MANFMT="false" fi - +fi # Extract the first word of "groupadd", so it can be a program name with args. set dummy groupadd; ac_word=$2 -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -printf %s "checking for $ac_word... " >&6; } -if test ${ac_cv_path_PATH_GROUPADD_PROG+y} -then : - printf %s "(cached) " >&6 -else $as_nop +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_PATH_GROUPADD_PROG+:} false; then : + $as_echo_n "(cached) " >&6 +else case $PATH_GROUPADD_PROG in [\\/]* | ?:[\\/]*) ac_cv_path_PATH_GROUPADD_PROG="$PATH_GROUPADD_PROG" # Let the user override the test with a path. @@ -5434,15 +5362,11 @@ for as_dir in /usr/sbin${PATH_SEPARATOR}/etc do IFS=$as_save_IFS - case $as_dir in #((( - '') as_dir=./ ;; - */) ;; - *) as_dir=$as_dir/ ;; - esac + test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then - ac_cv_path_PATH_GROUPADD_PROG="$as_dir$ac_word$ac_exec_ext" - printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_PATH_GROUPADD_PROG="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done @@ -5455,22 +5379,21 @@ fi PATH_GROUPADD_PROG=$ac_cv_path_PATH_GROUPADD_PROG if test -n "$PATH_GROUPADD_PROG"; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $PATH_GROUPADD_PROG" >&5 -printf "%s\n" "$PATH_GROUPADD_PROG" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PATH_GROUPADD_PROG" >&5 +$as_echo "$PATH_GROUPADD_PROG" >&6; } else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } fi # Extract the first word of "useradd", so it can be a program name with args. set dummy useradd; ac_word=$2 -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -printf %s "checking for $ac_word... " >&6; } -if test ${ac_cv_path_PATH_USERADD_PROG+y} -then : - printf %s "(cached) " >&6 -else $as_nop +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_PATH_USERADD_PROG+:} false; then : + $as_echo_n "(cached) " >&6 +else case $PATH_USERADD_PROG in [\\/]* | ?:[\\/]*) ac_cv_path_PATH_USERADD_PROG="$PATH_USERADD_PROG" # Let the user override the test with a path. @@ -5480,15 +5403,11 @@ for as_dir in /usr/sbin${PATH_SEPARATOR}/etc do IFS=$as_save_IFS - case $as_dir in #((( - '') as_dir=./ ;; - */) ;; - *) as_dir=$as_dir/ ;; - esac + test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then - ac_cv_path_PATH_USERADD_PROG="$as_dir$ac_word$ac_exec_ext" - printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_PATH_USERADD_PROG="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done @@ -5501,22 +5420,21 @@ fi PATH_USERADD_PROG=$ac_cv_path_PATH_USERADD_PROG if test -n "$PATH_USERADD_PROG"; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $PATH_USERADD_PROG" >&5 -printf "%s\n" "$PATH_USERADD_PROG" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PATH_USERADD_PROG" >&5 +$as_echo "$PATH_USERADD_PROG" >&6; } else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } fi # Extract the first word of "pkgmk", so it can be a program name with args. set dummy pkgmk; ac_word=$2 -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -printf %s "checking for $ac_word... " >&6; } -if test ${ac_cv_prog_MAKE_PACKAGE_SUPPORTED+y} -then : - printf %s "(cached) " >&6 -else $as_nop +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_MAKE_PACKAGE_SUPPORTED+:} false; then : + $as_echo_n "(cached) " >&6 +else if test -n "$MAKE_PACKAGE_SUPPORTED"; then ac_cv_prog_MAKE_PACKAGE_SUPPORTED="$MAKE_PACKAGE_SUPPORTED" # Let the user override the test. else @@ -5524,15 +5442,11 @@ for as_dir in $PATH do IFS=$as_save_IFS - case $as_dir in #((( - '') as_dir=./ ;; - */) ;; - *) as_dir=$as_dir/ ;; - esac + test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_MAKE_PACKAGE_SUPPORTED="yes" - printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done @@ -5544,11 +5458,11 @@ fi MAKE_PACKAGE_SUPPORTED=$ac_cv_prog_MAKE_PACKAGE_SUPPORTED if test -n "$MAKE_PACKAGE_SUPPORTED"; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $MAKE_PACKAGE_SUPPORTED" >&5 -printf "%s\n" "$MAKE_PACKAGE_SUPPORTED" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAKE_PACKAGE_SUPPORTED" >&5 +$as_echo "$MAKE_PACKAGE_SUPPORTED" >&6; } else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } fi @@ -5560,21 +5474,73 @@ fi +# Android configuration settings +# +# Copyright (c) 2018 Roumen Petrov +# Revisions: +# 27 Dec 2018 : refactored from configure.ac +# +# serail 20181217 + + + + +case "$host" in +*-*-linux-android*) + + ac_cv_func_getpagesize=yes + + ac_cv_search_openpty=no + ac_cv_func_openpty=use_port + ac_cv_file__dev_ptmx=yes + + ac_cv_header_sys_statvfs_h=ignore + ac_cv_func_statvfs=use_port + ac_cv_func_fstatvfs=use_port + + ac_cv_func_getsid=yes + + ac_cv_func_mbtowc=use_port + + ac_cv_func_getline=use_port + + ac_cv_sys_file_offset_bits=no + + ac_cv_func_endgrent=yes + + ac_cv_func_getifaddrs=ignore + + ac_cv_func_futimes=ignore + + ac_cv_func_nl_langinfo=ignore + + ac_cv_func_mblen=ignore + + ac_cv_func_getrandom=ignore + + ac_cv_func_getentropy=ignore + + ac_cv_func_glob=ignore + + ac_cv_func_reallocarray=ignore + + ;; +esac + + # System features # Check whether --enable-largefile was given. -if test ${enable_largefile+y} -then : +if test "${enable_largefile+set}" = set; then : enableval=$enable_largefile; fi if test "$enable_largefile" != no; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for special C compiler options needed for large files" >&5 -printf %s "checking for special C compiler options needed for large files... " >&6; } -if test ${ac_cv_sys_largefile_CC+y} -then : - printf %s "(cached) " >&6 -else $as_nop + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for special C compiler options needed for large files" >&5 +$as_echo_n "checking for special C compiler options needed for large files... " >&6; } +if ${ac_cv_sys_largefile_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else ac_cv_sys_largefile_CC=no if test "$GCC" != yes; then ac_save_CC=$CC @@ -5588,47 +5554,44 @@ We can't simply define LARGE_OFF_T to be 9223372036854775807, since some C++ compilers masquerading as C compilers incorrectly reject 9223372036854775807. */ -#define LARGE_OFF_T (((off_t) 1 << 31 << 31) - 1 + ((off_t) 1 << 31 << 31)) +#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1]; int -main (void) +main () { ; return 0; } _ACEOF - if ac_fn_c_try_compile "$LINENO" -then : + if ac_fn_c_try_compile "$LINENO"; then : break fi -rm -f core conftest.err conftest.$ac_objext conftest.beam +rm -f core conftest.err conftest.$ac_objext CC="$CC -n32" - if ac_fn_c_try_compile "$LINENO" -then : + if ac_fn_c_try_compile "$LINENO"; then : ac_cv_sys_largefile_CC=' -n32'; break fi -rm -f core conftest.err conftest.$ac_objext conftest.beam +rm -f core conftest.err conftest.$ac_objext break done CC=$ac_save_CC rm -f conftest.$ac_ext fi fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_largefile_CC" >&5 -printf "%s\n" "$ac_cv_sys_largefile_CC" >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_largefile_CC" >&5 +$as_echo "$ac_cv_sys_largefile_CC" >&6; } if test "$ac_cv_sys_largefile_CC" != no; then CC=$CC$ac_cv_sys_largefile_CC fi - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for _FILE_OFFSET_BITS value needed for large files" >&5 -printf %s "checking for _FILE_OFFSET_BITS value needed for large files... " >&6; } -if test ${ac_cv_sys_file_offset_bits+y} -then : - printf %s "(cached) " >&6 -else $as_nop + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for _FILE_OFFSET_BITS value needed for large files" >&5 +$as_echo_n "checking for _FILE_OFFSET_BITS value needed for large files... " >&6; } +if ${ac_cv_sys_file_offset_bits+:} false; then : + $as_echo_n "(cached) " >&6 +else while :; do cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -5637,23 +5600,22 @@ We can't simply define LARGE_OFF_T to be 9223372036854775807, since some C++ compilers masquerading as C compilers incorrectly reject 9223372036854775807. */ -#define LARGE_OFF_T (((off_t) 1 << 31 << 31) - 1 + ((off_t) 1 << 31 << 31)) +#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1]; int -main (void) +main () { ; return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO" -then : +if ac_fn_c_try_compile "$LINENO"; then : ac_cv_sys_file_offset_bits=no; break fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #define _FILE_OFFSET_BITS 64 @@ -5662,43 +5624,43 @@ We can't simply define LARGE_OFF_T to be 9223372036854775807, since some C++ compilers masquerading as C compilers incorrectly reject 9223372036854775807. */ -#define LARGE_OFF_T (((off_t) 1 << 31 << 31) - 1 + ((off_t) 1 << 31 << 31)) +#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1]; int -main (void) +main () { ; return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO" -then : +if ac_fn_c_try_compile "$LINENO"; then : ac_cv_sys_file_offset_bits=64; break fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_sys_file_offset_bits=unknown break done fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_file_offset_bits" >&5 -printf "%s\n" "$ac_cv_sys_file_offset_bits" >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_file_offset_bits" >&5 +$as_echo "$ac_cv_sys_file_offset_bits" >&6; } case $ac_cv_sys_file_offset_bits in #( no | unknown) ;; *) -printf "%s\n" "#define _FILE_OFFSET_BITS $ac_cv_sys_file_offset_bits" >>confdefs.h +cat >>confdefs.h <<_ACEOF +#define _FILE_OFFSET_BITS $ac_cv_sys_file_offset_bits +_ACEOF ;; esac rm -rf conftest* if test $ac_cv_sys_file_offset_bits = unknown; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for _LARGE_FILES value needed for large files" >&5 -printf %s "checking for _LARGE_FILES value needed for large files... " >&6; } -if test ${ac_cv_sys_large_files+y} -then : - printf %s "(cached) " >&6 -else $as_nop + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for _LARGE_FILES value needed for large files" >&5 +$as_echo_n "checking for _LARGE_FILES value needed for large files... " >&6; } +if ${ac_cv_sys_large_files+:} false; then : + $as_echo_n "(cached) " >&6 +else while :; do cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -5707,23 +5669,22 @@ We can't simply define LARGE_OFF_T to be 9223372036854775807, since some C++ compilers masquerading as C compilers incorrectly reject 9223372036854775807. */ -#define LARGE_OFF_T (((off_t) 1 << 31 << 31) - 1 + ((off_t) 1 << 31 << 31)) +#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1]; int -main (void) +main () { ; return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO" -then : +if ac_fn_c_try_compile "$LINENO"; then : ac_cv_sys_large_files=no; break fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #define _LARGE_FILES 1 @@ -5732,37 +5693,40 @@ We can't simply define LARGE_OFF_T to be 9223372036854775807, since some C++ compilers masquerading as C compilers incorrectly reject 9223372036854775807. */ -#define LARGE_OFF_T (((off_t) 1 << 31 << 31) - 1 + ((off_t) 1 << 31 << 31)) +#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1]; int -main (void) +main () { ; return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO" -then : +if ac_fn_c_try_compile "$LINENO"; then : ac_cv_sys_large_files=1; break fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_sys_large_files=unknown break done fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_large_files" >&5 -printf "%s\n" "$ac_cv_sys_large_files" >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_large_files" >&5 +$as_echo "$ac_cv_sys_large_files" >&6; } case $ac_cv_sys_large_files in #( no | unknown) ;; *) -printf "%s\n" "#define _LARGE_FILES $ac_cv_sys_large_files" >>confdefs.h +cat >>confdefs.h <<_ACEOF +#define _LARGE_FILES $ac_cv_sys_large_files +_ACEOF ;; esac rm -rf conftest* fi + + fi @@ -5772,12 +5736,11 @@ # Extract the first word of "passwd", so it can be a program name with args. set dummy passwd; ac_word=$2 -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -printf %s "checking for $ac_word... " >&6; } -if test ${ac_cv_path_PATH_PASSWD_PROG+y} -then : - printf %s "(cached) " >&6 -else $as_nop +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_PATH_PASSWD_PROG+:} false; then : + $as_echo_n "(cached) " >&6 +else case $PATH_PASSWD_PROG in [\\/]* | ?:[\\/]*) ac_cv_path_PATH_PASSWD_PROG="$PATH_PASSWD_PROG" # Let the user override the test with a path. @@ -5787,15 +5750,11 @@ for as_dir in $PATH do IFS=$as_save_IFS - case $as_dir in #((( - '') as_dir=./ ;; - */) ;; - *) as_dir=$as_dir/ ;; - esac + test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then - ac_cv_path_PATH_PASSWD_PROG="$as_dir$ac_word$ac_exec_ext" - printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_PATH_PASSWD_PROG="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done @@ -5807,51 +5766,51 @@ fi PATH_PASSWD_PROG=$ac_cv_path_PATH_PASSWD_PROG if test -n "$PATH_PASSWD_PROG"; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $PATH_PASSWD_PROG" >&5 -printf "%s\n" "$PATH_PASSWD_PROG" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PATH_PASSWD_PROG" >&5 +$as_echo "$PATH_PASSWD_PROG" >&6; } else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } fi if test ! -z "$PATH_PASSWD_PROG" ; then -printf "%s\n" "#define _PATH_PASSWD_PROG \"$PATH_PASSWD_PROG\"" >>confdefs.h +cat >>confdefs.h <<_ACEOF +#define _PATH_PASSWD_PROG "$PATH_PASSWD_PROG" +_ACEOF fi LD="$CC" -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for inline" >&5 -printf %s "checking for inline... " >&6; } -if test ${ac_cv_c_inline+y} -then : - printf %s "(cached) " >&6 -else $as_nop +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for inline" >&5 +$as_echo_n "checking for inline... " >&6; } +if ${ac_cv_c_inline+:} false; then : + $as_echo_n "(cached) " >&6 +else ac_cv_c_inline=no for ac_kw in inline __inline__ __inline; do cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifndef __cplusplus typedef int foo_t; -static $ac_kw foo_t static_foo (void) {return 0; } -$ac_kw foo_t foo (void) {return 0; } +static $ac_kw foo_t static_foo () {return 0; } +$ac_kw foo_t foo () {return 0; } #endif _ACEOF -if ac_fn_c_try_compile "$LINENO" -then : +if ac_fn_c_try_compile "$LINENO"; then : ac_cv_c_inline=$ac_kw fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext test "$ac_cv_c_inline" != no && break done fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_inline" >&5 -printf "%s\n" "$ac_cv_c_inline" >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_inline" >&5 +$as_echo "$ac_cv_c_inline" >&6; } case $ac_cv_c_inline in inline | yes) ;; @@ -5869,206 +5828,126 @@ esac -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC options needed to detect all undeclared functions" >&5 -printf %s "checking for $CC options needed to detect all undeclared functions... " >&6; } -if test ${ac_cv_c_undeclared_builtin_options+y} -then : - printf %s "(cached) " >&6 -else $as_nop - ac_save_CFLAGS=$CFLAGS - ac_cv_c_undeclared_builtin_options='cannot detect' - for ac_arg in '' -fno-builtin; do - CFLAGS="$ac_save_CFLAGS $ac_arg" - # This test program should *not* compile successfully. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main (void) -{ -(void) strchr; - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO" -then : - -else $as_nop - # This test program should compile successfully. - # No library function is consistently available on - # freestanding implementations, so test against a dummy - # declaration. Include always-available headers on the - # off chance that they somehow elicit warnings. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include -#include -#include -#include -extern void ac_decl (int, char *); - -int -main (void) -{ -(void) ac_decl (0, (char *) 0); - (void) ac_decl; - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO" -then : - if test x"$ac_arg" = x -then : - ac_cv_c_undeclared_builtin_options='none needed' -else $as_nop - ac_cv_c_undeclared_builtin_options=$ac_arg -fi - break -fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +ac_fn_c_check_decl "$LINENO" "LLONG_MAX" "ac_cv_have_decl_LLONG_MAX" "#include +" +if test "x$ac_cv_have_decl_LLONG_MAX" = xyes; then : + have_llong_max=1 fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext - done - CFLAGS=$ac_save_CFLAGS -fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_undeclared_builtin_options" >&5 -printf "%s\n" "$ac_cv_c_undeclared_builtin_options" >&6; } - case $ac_cv_c_undeclared_builtin_options in #( - 'cannot detect') : - { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error $? "cannot make $CC report undeclared builtins -See \`config.log' for more details" "$LINENO" 5; } ;; #( - 'none needed') : - ac_c_undeclared_builtin_options='' ;; #( - *) : - ac_c_undeclared_builtin_options=$ac_cv_c_undeclared_builtin_options ;; -esac -ac_fn_check_decl "$LINENO" "LLONG_MAX" "ac_cv_have_decl_LLONG_MAX" "#include -" "$ac_c_undeclared_builtin_options" "CFLAGS" -if test "x$ac_cv_have_decl_LLONG_MAX" = xyes -then : - have_llong_max=1 -fi -ac_fn_check_decl "$LINENO" "LONG_LONG_MAX" "ac_cv_have_decl_LONG_LONG_MAX" "#include -" "$ac_c_undeclared_builtin_options" "CFLAGS" -if test "x$ac_cv_have_decl_LONG_LONG_MAX" = xyes -then : - have_long_long_max=1 -fi -ac_fn_check_decl "$LINENO" "SYSTR_POLICY_KILL" "ac_cv_have_decl_SYSTR_POLICY_KILL" " +ac_fn_c_check_decl "$LINENO" "SYSTR_POLICY_KILL" "ac_cv_have_decl_SYSTR_POLICY_KILL" " #include #include #include -" "$ac_c_undeclared_builtin_options" "CFLAGS" -if test "x$ac_cv_have_decl_SYSTR_POLICY_KILL" = xyes -then : +" +if test "x$ac_cv_have_decl_SYSTR_POLICY_KILL" = xyes; then : have_systr_policy_kill=1 fi -ac_fn_check_decl "$LINENO" "RLIMIT_NPROC" "ac_cv_have_decl_RLIMIT_NPROC" " + +ac_fn_c_check_decl "$LINENO" "RLIMIT_NPROC" "ac_cv_have_decl_RLIMIT_NPROC" " #include #include -" "$ac_c_undeclared_builtin_options" "CFLAGS" -if test "x$ac_cv_have_decl_RLIMIT_NPROC" = xyes -then : +" +if test "x$ac_cv_have_decl_RLIMIT_NPROC" = xyes; then : -printf "%s\n" "#define HAVE_RLIMIT_NPROC /**/" >>confdefs.h +$as_echo "#define HAVE_RLIMIT_NPROC 1" >>confdefs.h fi -ac_fn_check_decl "$LINENO" "PR_SET_NO_NEW_PRIVS" "ac_cv_have_decl_PR_SET_NO_NEW_PRIVS" " + +ac_fn_c_check_decl "$LINENO" "PR_SET_NO_NEW_PRIVS" "ac_cv_have_decl_PR_SET_NO_NEW_PRIVS" " #include #include -" "$ac_c_undeclared_builtin_options" "CFLAGS" -if test "x$ac_cv_have_decl_PR_SET_NO_NEW_PRIVS" = xyes -then : +" +if test "x$ac_cv_have_decl_PR_SET_NO_NEW_PRIVS" = xyes; then : have_linux_no_new_privs=1 fi -openssl=yes -openssl_bin=openssl + # Check whether --with-openssl was given. -if test ${with_openssl+y} -then : - withval=$with_openssl; if test "x$withval" = "xno" ; then - openssl=no - openssl_bin="" - fi +if test "${with_openssl+set}" = set; then : + withval=$with_openssl; +else + with_openssl=yes +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether OpenSSL will be used for cryptography" >&5 +$as_echo_n "checking whether OpenSSL will be used for cryptography... " >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_openssl" >&5 +$as_echo "$with_openssl" >&6; } +if test "x$with_openssl" != "xyes"; then + as_fn_error $? "build with OpenSSL is required" "$LINENO" 5 fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether OpenSSL will be used for cryptography" >&5 -printf %s "checking whether OpenSSL will be used for cryptography... " >&6; } -if test "x$openssl" = "xyes" ; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } +openssl=yes -printf "%s\n" "#define WITH_OPENSSL 1" >>confdefs.h +cat >>confdefs.h <<_ACEOF +#define WITH_OPENSSL 1 +_ACEOF -else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } -fi -use_stack_protector=1 -use_toolchain_hardening=1 +use_stack_protector=: +use_toolchain_hardening=: # Check whether --with-stackprotect was given. -if test ${with_stackprotect+y} -then : +if test "${with_stackprotect+set}" = set; then : withval=$with_stackprotect; - if test "x$withval" = "xno"; then - use_stack_protector=0 - fi + if test "x$withval" = "xno"; then + use_stack_protector=false + fi + + fi # Check whether --with-hardening was given. -if test ${with_hardening+y} -then : +if test "${with_hardening+set}" = set; then : withval=$with_hardening; - if test "x$withval" = "xno"; then - use_toolchain_hardening=0 - fi + if test "x$withval" = "xno"; then + use_toolchain_hardening=false + fi + + fi # We use -Werror for the tests only so that we catch warnings like "this is # on by default" for things like -fPIE. -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $CC supports -Werror" >&5 -printf %s "checking if $CC supports -Werror... " >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC supports -Werror" >&5 +$as_echo_n "checking if $CC supports -Werror... " >&6; } saved_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -Werror" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -int main(void) { return 0; } + +int +main () +{ + + ; + return 0; +} _ACEOF -if ac_fn_c_try_compile "$LINENO" -then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } +if ac_fn_c_try_compile "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } WERROR="-Werror" -else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } WERROR="" fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext CFLAGS="$saved_CFLAGS" if test "$GCC" = "yes" || test "$GCC" = "egcs"; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking gcc version" >&5 -printf %s "checking gcc version... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking gcc version" >&5 +$as_echo_n "checking gcc version... " >&6; } GCC_VER=`$CC -v 2>&1 | $AWK '/gcc version /{print $3}'` case "$GCC_VER" in 1.*) no_attrib_nonnull=1 ;; @@ -6078,18 +5957,18 @@ 2.*) no_attrib_nonnull=1 ;; *) ;; esac - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $GCC_VER" >&5 -printf "%s\n" "$GCC_VER" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GCC_VER" >&5 +$as_echo "$GCC_VER" >&6; } - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking clang version" >&5 -printf %s "checking clang version... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking clang version" >&5 +$as_echo_n "checking clang version... " >&6; } CLANG_VER=`$CC -v 2>&1 | $AWK '/clang version /{print $3}'` - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CLANG_VER" >&5 -printf "%s\n" "$CLANG_VER" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CLANG_VER" >&5 +$as_echo "$CLANG_VER" >&6; } { - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -pipe" >&5 -printf %s "checking if $CC supports compile flag -pipe... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -pipe" >&5 +$as_echo_n "checking if $CC supports compile flag -pipe... " >&6; } saved_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $WERROR -pipe" _define_flag="" @@ -6097,57 +5976,49 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ + #include #include -/* Trivial function to help test for -fzero-call-used-regs */ -void f(int n) {} -int main(int argc, char **argv) { - (void)argv; +/* Trivial function to help test for flags like -fzero-call-used-regs. +Note compiler does not inform whether this option is supported unless it +runs into the situation where it would need to emit corresponding code.*/ +static int f(int n) {return n;} +int main(int argc, char *argv[]) { /* Some math to catch -ftrapv problems in the toolchain */ int i = 123 * argc, j = 456 + argc, k = 789 - argc; float l = i * 2.1; double m = l / 0.5; long long int n = argc * 12345LL, o = 12345LL * (long long int)argc; - f(0); - printf("%d %d %d %f %f %lld %lld\n", i, j, k, l, m, n, o); - /* - * Test fallthrough behaviour. clang 10's -Wimplicit-fallthrough does - * not understand comments and we don't use the "fallthrough" attribute - * that it's looking for. - */ - switch(i){ - case 0: j += i; - /* FALLTHROUGH */ - default: j += k; - } - exit(0); + long long int p = n * o; + printf("%d %d %d %f %f %lld %lld %lld %d\n", i, j, k, l, m, n, o, p, f(0)); + (void)argv; + return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO" -then : +if ac_fn_c_try_compile "$LINENO"; then : -if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null +if $EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } CFLAGS="$saved_CFLAGS" else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } CFLAGS="$saved_CFLAGS $_define_flag" fi -else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } CFLAGS="$saved_CFLAGS" fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext } { - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -Wunknown-warning-option" >&5 -printf %s "checking if $CC supports compile flag -Wunknown-warning-option... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -Wunknown-warning-option" >&5 +$as_echo_n "checking if $CC supports compile flag -Wunknown-warning-option... " >&6; } saved_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $WERROR -Wunknown-warning-option" _define_flag="" @@ -6155,57 +6026,49 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ + #include #include -/* Trivial function to help test for -fzero-call-used-regs */ -void f(int n) {} -int main(int argc, char **argv) { - (void)argv; +/* Trivial function to help test for flags like -fzero-call-used-regs. +Note compiler does not inform whether this option is supported unless it +runs into the situation where it would need to emit corresponding code.*/ +static int f(int n) {return n;} +int main(int argc, char *argv[]) { /* Some math to catch -ftrapv problems in the toolchain */ int i = 123 * argc, j = 456 + argc, k = 789 - argc; float l = i * 2.1; double m = l / 0.5; long long int n = argc * 12345LL, o = 12345LL * (long long int)argc; - f(0); - printf("%d %d %d %f %f %lld %lld\n", i, j, k, l, m, n, o); - /* - * Test fallthrough behaviour. clang 10's -Wimplicit-fallthrough does - * not understand comments and we don't use the "fallthrough" attribute - * that it's looking for. - */ - switch(i){ - case 0: j += i; - /* FALLTHROUGH */ - default: j += k; - } - exit(0); + long long int p = n * o; + printf("%d %d %d %f %f %lld %lld %lld %d\n", i, j, k, l, m, n, o, p, f(0)); + (void)argv; + return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO" -then : +if ac_fn_c_try_compile "$LINENO"; then : -if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null +if $EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } CFLAGS="$saved_CFLAGS" else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } CFLAGS="$saved_CFLAGS $_define_flag" fi -else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } CFLAGS="$saved_CFLAGS" fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext } { - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -Wno-error=format-truncation" >&5 -printf %s "checking if $CC supports compile flag -Wno-error=format-truncation... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -Wno-error=format-truncation" >&5 +$as_echo_n "checking if $CC supports compile flag -Wno-error=format-truncation... " >&6; } saved_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $WERROR -Wno-error=format-truncation" _define_flag="" @@ -6213,115 +6076,49 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -#include -#include -/* Trivial function to help test for -fzero-call-used-regs */ -void f(int n) {} -int main(int argc, char **argv) { - (void)argv; - /* Some math to catch -ftrapv problems in the toolchain */ - int i = 123 * argc, j = 456 + argc, k = 789 - argc; - float l = i * 2.1; - double m = l / 0.5; - long long int n = argc * 12345LL, o = 12345LL * (long long int)argc; - f(0); - printf("%d %d %d %f %f %lld %lld\n", i, j, k, l, m, n, o); - /* - * Test fallthrough behaviour. clang 10's -Wimplicit-fallthrough does - * not understand comments and we don't use the "fallthrough" attribute - * that it's looking for. - */ - switch(i){ - case 0: j += i; - /* FALLTHROUGH */ - default: j += k; - } - exit(0); -} - -_ACEOF -if ac_fn_c_try_compile "$LINENO" -then : - -if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null -then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } - CFLAGS="$saved_CFLAGS" -else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } - CFLAGS="$saved_CFLAGS $_define_flag" -fi -else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } - CFLAGS="$saved_CFLAGS" - -fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext -} - { - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -Qunused-arguments" >&5 -printf %s "checking if $CC supports compile flag -Qunused-arguments... " >&6; } - saved_CFLAGS="$CFLAGS" - CFLAGS="$CFLAGS $WERROR -Qunused-arguments" - _define_flag="" - test "x$_define_flag" = "x" && _define_flag="-Qunused-arguments" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ #include #include -/* Trivial function to help test for -fzero-call-used-regs */ -void f(int n) {} -int main(int argc, char **argv) { - (void)argv; +/* Trivial function to help test for flags like -fzero-call-used-regs. +Note compiler does not inform whether this option is supported unless it +runs into the situation where it would need to emit corresponding code.*/ +static int f(int n) {return n;} +int main(int argc, char *argv[]) { /* Some math to catch -ftrapv problems in the toolchain */ int i = 123 * argc, j = 456 + argc, k = 789 - argc; float l = i * 2.1; double m = l / 0.5; long long int n = argc * 12345LL, o = 12345LL * (long long int)argc; - f(0); - printf("%d %d %d %f %f %lld %lld\n", i, j, k, l, m, n, o); - /* - * Test fallthrough behaviour. clang 10's -Wimplicit-fallthrough does - * not understand comments and we don't use the "fallthrough" attribute - * that it's looking for. - */ - switch(i){ - case 0: j += i; - /* FALLTHROUGH */ - default: j += k; - } - exit(0); + long long int p = n * o; + printf("%d %d %d %f %f %lld %lld %lld %d\n", i, j, k, l, m, n, o, p, f(0)); + (void)argv; + return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO" -then : +if ac_fn_c_try_compile "$LINENO"; then : -if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null +if $EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } CFLAGS="$saved_CFLAGS" else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } CFLAGS="$saved_CFLAGS $_define_flag" fi -else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } CFLAGS="$saved_CFLAGS" fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext } { - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -Wall" >&5 -printf %s "checking if $CC supports compile flag -Wall... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -Wall" >&5 +$as_echo_n "checking if $CC supports compile flag -Wall... " >&6; } saved_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $WERROR -Wall" _define_flag="" @@ -6329,57 +6126,49 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ + #include #include -/* Trivial function to help test for -fzero-call-used-regs */ -void f(int n) {} -int main(int argc, char **argv) { - (void)argv; +/* Trivial function to help test for flags like -fzero-call-used-regs. +Note compiler does not inform whether this option is supported unless it +runs into the situation where it would need to emit corresponding code.*/ +static int f(int n) {return n;} +int main(int argc, char *argv[]) { /* Some math to catch -ftrapv problems in the toolchain */ int i = 123 * argc, j = 456 + argc, k = 789 - argc; float l = i * 2.1; double m = l / 0.5; long long int n = argc * 12345LL, o = 12345LL * (long long int)argc; - f(0); - printf("%d %d %d %f %f %lld %lld\n", i, j, k, l, m, n, o); - /* - * Test fallthrough behaviour. clang 10's -Wimplicit-fallthrough does - * not understand comments and we don't use the "fallthrough" attribute - * that it's looking for. - */ - switch(i){ - case 0: j += i; - /* FALLTHROUGH */ - default: j += k; - } - exit(0); + long long int p = n * o; + printf("%d %d %d %f %f %lld %lld %lld %d\n", i, j, k, l, m, n, o, p, f(0)); + (void)argv; + return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO" -then : +if ac_fn_c_try_compile "$LINENO"; then : -if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null +if $EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } CFLAGS="$saved_CFLAGS" else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } CFLAGS="$saved_CFLAGS $_define_flag" fi -else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } CFLAGS="$saved_CFLAGS" fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext } { - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -Wextra" >&5 -printf %s "checking if $CC supports compile flag -Wextra... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -Wextra" >&5 +$as_echo_n "checking if $CC supports compile flag -Wextra... " >&6; } saved_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $WERROR -Wextra" _define_flag="" @@ -6387,57 +6176,49 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ + #include #include -/* Trivial function to help test for -fzero-call-used-regs */ -void f(int n) {} -int main(int argc, char **argv) { - (void)argv; +/* Trivial function to help test for flags like -fzero-call-used-regs. +Note compiler does not inform whether this option is supported unless it +runs into the situation where it would need to emit corresponding code.*/ +static int f(int n) {return n;} +int main(int argc, char *argv[]) { /* Some math to catch -ftrapv problems in the toolchain */ int i = 123 * argc, j = 456 + argc, k = 789 - argc; float l = i * 2.1; double m = l / 0.5; long long int n = argc * 12345LL, o = 12345LL * (long long int)argc; - f(0); - printf("%d %d %d %f %f %lld %lld\n", i, j, k, l, m, n, o); - /* - * Test fallthrough behaviour. clang 10's -Wimplicit-fallthrough does - * not understand comments and we don't use the "fallthrough" attribute - * that it's looking for. - */ - switch(i){ - case 0: j += i; - /* FALLTHROUGH */ - default: j += k; - } - exit(0); + long long int p = n * o; + printf("%d %d %d %f %f %lld %lld %lld %d\n", i, j, k, l, m, n, o, p, f(0)); + (void)argv; + return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO" -then : +if ac_fn_c_try_compile "$LINENO"; then : -if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null +if $EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } CFLAGS="$saved_CFLAGS" else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } CFLAGS="$saved_CFLAGS $_define_flag" fi -else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } CFLAGS="$saved_CFLAGS" fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext } { - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -Wpointer-arith" >&5 -printf %s "checking if $CC supports compile flag -Wpointer-arith... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -Wpointer-arith" >&5 +$as_echo_n "checking if $CC supports compile flag -Wpointer-arith... " >&6; } saved_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $WERROR -Wpointer-arith" _define_flag="" @@ -6445,57 +6226,49 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ + #include #include -/* Trivial function to help test for -fzero-call-used-regs */ -void f(int n) {} -int main(int argc, char **argv) { - (void)argv; +/* Trivial function to help test for flags like -fzero-call-used-regs. +Note compiler does not inform whether this option is supported unless it +runs into the situation where it would need to emit corresponding code.*/ +static int f(int n) {return n;} +int main(int argc, char *argv[]) { /* Some math to catch -ftrapv problems in the toolchain */ int i = 123 * argc, j = 456 + argc, k = 789 - argc; float l = i * 2.1; double m = l / 0.5; long long int n = argc * 12345LL, o = 12345LL * (long long int)argc; - f(0); - printf("%d %d %d %f %f %lld %lld\n", i, j, k, l, m, n, o); - /* - * Test fallthrough behaviour. clang 10's -Wimplicit-fallthrough does - * not understand comments and we don't use the "fallthrough" attribute - * that it's looking for. - */ - switch(i){ - case 0: j += i; - /* FALLTHROUGH */ - default: j += k; - } - exit(0); + long long int p = n * o; + printf("%d %d %d %f %f %lld %lld %lld %d\n", i, j, k, l, m, n, o, p, f(0)); + (void)argv; + return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO" -then : +if ac_fn_c_try_compile "$LINENO"; then : -if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null +if $EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } CFLAGS="$saved_CFLAGS" else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } CFLAGS="$saved_CFLAGS $_define_flag" fi -else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } CFLAGS="$saved_CFLAGS" fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext } { - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -Wuninitialized" >&5 -printf %s "checking if $CC supports compile flag -Wuninitialized... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -Wuninitialized" >&5 +$as_echo_n "checking if $CC supports compile flag -Wuninitialized... " >&6; } saved_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $WERROR -Wuninitialized" _define_flag="" @@ -6503,57 +6276,49 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ + #include #include -/* Trivial function to help test for -fzero-call-used-regs */ -void f(int n) {} -int main(int argc, char **argv) { - (void)argv; +/* Trivial function to help test for flags like -fzero-call-used-regs. +Note compiler does not inform whether this option is supported unless it +runs into the situation where it would need to emit corresponding code.*/ +static int f(int n) {return n;} +int main(int argc, char *argv[]) { /* Some math to catch -ftrapv problems in the toolchain */ int i = 123 * argc, j = 456 + argc, k = 789 - argc; float l = i * 2.1; double m = l / 0.5; long long int n = argc * 12345LL, o = 12345LL * (long long int)argc; - f(0); - printf("%d %d %d %f %f %lld %lld\n", i, j, k, l, m, n, o); - /* - * Test fallthrough behaviour. clang 10's -Wimplicit-fallthrough does - * not understand comments and we don't use the "fallthrough" attribute - * that it's looking for. - */ - switch(i){ - case 0: j += i; - /* FALLTHROUGH */ - default: j += k; - } - exit(0); + long long int p = n * o; + printf("%d %d %d %f %f %lld %lld %lld %d\n", i, j, k, l, m, n, o, p, f(0)); + (void)argv; + return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO" -then : +if ac_fn_c_try_compile "$LINENO"; then : -if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null +if $EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } CFLAGS="$saved_CFLAGS" else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } CFLAGS="$saved_CFLAGS $_define_flag" fi -else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } CFLAGS="$saved_CFLAGS" fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext } { - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -Wsign-compare" >&5 -printf %s "checking if $CC supports compile flag -Wsign-compare... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -Wsign-compare" >&5 +$as_echo_n "checking if $CC supports compile flag -Wsign-compare... " >&6; } saved_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $WERROR -Wsign-compare" _define_flag="" @@ -6561,57 +6326,49 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ + #include #include -/* Trivial function to help test for -fzero-call-used-regs */ -void f(int n) {} -int main(int argc, char **argv) { - (void)argv; +/* Trivial function to help test for flags like -fzero-call-used-regs. +Note compiler does not inform whether this option is supported unless it +runs into the situation where it would need to emit corresponding code.*/ +static int f(int n) {return n;} +int main(int argc, char *argv[]) { /* Some math to catch -ftrapv problems in the toolchain */ int i = 123 * argc, j = 456 + argc, k = 789 - argc; float l = i * 2.1; double m = l / 0.5; long long int n = argc * 12345LL, o = 12345LL * (long long int)argc; - f(0); - printf("%d %d %d %f %f %lld %lld\n", i, j, k, l, m, n, o); - /* - * Test fallthrough behaviour. clang 10's -Wimplicit-fallthrough does - * not understand comments and we don't use the "fallthrough" attribute - * that it's looking for. - */ - switch(i){ - case 0: j += i; - /* FALLTHROUGH */ - default: j += k; - } - exit(0); + long long int p = n * o; + printf("%d %d %d %f %f %lld %lld %lld %d\n", i, j, k, l, m, n, o, p, f(0)); + (void)argv; + return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO" -then : +if ac_fn_c_try_compile "$LINENO"; then : -if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null +if $EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } CFLAGS="$saved_CFLAGS" else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } CFLAGS="$saved_CFLAGS $_define_flag" fi -else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } CFLAGS="$saved_CFLAGS" fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext } { - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -Wformat-security" >&5 -printf %s "checking if $CC supports compile flag -Wformat-security... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -Wformat-security" >&5 +$as_echo_n "checking if $CC supports compile flag -Wformat-security... " >&6; } saved_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $WERROR -Wformat-security" _define_flag="" @@ -6619,57 +6376,49 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ + #include #include -/* Trivial function to help test for -fzero-call-used-regs */ -void f(int n) {} -int main(int argc, char **argv) { - (void)argv; +/* Trivial function to help test for flags like -fzero-call-used-regs. +Note compiler does not inform whether this option is supported unless it +runs into the situation where it would need to emit corresponding code.*/ +static int f(int n) {return n;} +int main(int argc, char *argv[]) { /* Some math to catch -ftrapv problems in the toolchain */ int i = 123 * argc, j = 456 + argc, k = 789 - argc; float l = i * 2.1; double m = l / 0.5; long long int n = argc * 12345LL, o = 12345LL * (long long int)argc; - f(0); - printf("%d %d %d %f %f %lld %lld\n", i, j, k, l, m, n, o); - /* - * Test fallthrough behaviour. clang 10's -Wimplicit-fallthrough does - * not understand comments and we don't use the "fallthrough" attribute - * that it's looking for. - */ - switch(i){ - case 0: j += i; - /* FALLTHROUGH */ - default: j += k; - } - exit(0); + long long int p = n * o; + printf("%d %d %d %f %f %lld %lld %lld %d\n", i, j, k, l, m, n, o, p, f(0)); + (void)argv; + return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO" -then : +if ac_fn_c_try_compile "$LINENO"; then : -if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null +if $EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } CFLAGS="$saved_CFLAGS" else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } CFLAGS="$saved_CFLAGS $_define_flag" fi -else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } CFLAGS="$saved_CFLAGS" fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext } { - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -Wsizeof-pointer-memaccess" >&5 -printf %s "checking if $CC supports compile flag -Wsizeof-pointer-memaccess... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -Wsizeof-pointer-memaccess" >&5 +$as_echo_n "checking if $CC supports compile flag -Wsizeof-pointer-memaccess... " >&6; } saved_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $WERROR -Wsizeof-pointer-memaccess" _define_flag="" @@ -6677,57 +6426,49 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ + #include #include -/* Trivial function to help test for -fzero-call-used-regs */ -void f(int n) {} -int main(int argc, char **argv) { - (void)argv; +/* Trivial function to help test for flags like -fzero-call-used-regs. +Note compiler does not inform whether this option is supported unless it +runs into the situation where it would need to emit corresponding code.*/ +static int f(int n) {return n;} +int main(int argc, char *argv[]) { /* Some math to catch -ftrapv problems in the toolchain */ int i = 123 * argc, j = 456 + argc, k = 789 - argc; float l = i * 2.1; double m = l / 0.5; long long int n = argc * 12345LL, o = 12345LL * (long long int)argc; - f(0); - printf("%d %d %d %f %f %lld %lld\n", i, j, k, l, m, n, o); - /* - * Test fallthrough behaviour. clang 10's -Wimplicit-fallthrough does - * not understand comments and we don't use the "fallthrough" attribute - * that it's looking for. - */ - switch(i){ - case 0: j += i; - /* FALLTHROUGH */ - default: j += k; - } - exit(0); + long long int p = n * o; + printf("%d %d %d %f %f %lld %lld %lld %d\n", i, j, k, l, m, n, o, p, f(0)); + (void)argv; + return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO" -then : +if ac_fn_c_try_compile "$LINENO"; then : -if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null +if $EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } CFLAGS="$saved_CFLAGS" else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } CFLAGS="$saved_CFLAGS $_define_flag" fi -else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } CFLAGS="$saved_CFLAGS" fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext } { - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -Wpointer-sign" >&5 -printf %s "checking if $CC supports compile flag -Wpointer-sign... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -Wpointer-sign" >&5 +$as_echo_n "checking if $CC supports compile flag -Wpointer-sign... " >&6; } saved_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $WERROR -Wpointer-sign" _define_flag="-Wno-pointer-sign" @@ -6735,115 +6476,52 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -#include -#include -/* Trivial function to help test for -fzero-call-used-regs */ -void f(int n) {} -int main(int argc, char **argv) { - (void)argv; - /* Some math to catch -ftrapv problems in the toolchain */ - int i = 123 * argc, j = 456 + argc, k = 789 - argc; - float l = i * 2.1; - double m = l / 0.5; - long long int n = argc * 12345LL, o = 12345LL * (long long int)argc; - f(0); - printf("%d %d %d %f %f %lld %lld\n", i, j, k, l, m, n, o); - /* - * Test fallthrough behaviour. clang 10's -Wimplicit-fallthrough does - * not understand comments and we don't use the "fallthrough" attribute - * that it's looking for. - */ - switch(i){ - case 0: j += i; - /* FALLTHROUGH */ - default: j += k; - } - exit(0); -} - -_ACEOF -if ac_fn_c_try_compile "$LINENO" -then : - -if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null -then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } - CFLAGS="$saved_CFLAGS" -else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } - CFLAGS="$saved_CFLAGS $_define_flag" -fi -else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } - CFLAGS="$saved_CFLAGS" - -fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext -} - { - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -Wunused-parameter" >&5 -printf %s "checking if $CC supports compile flag -Wunused-parameter... " >&6; } - saved_CFLAGS="$CFLAGS" - CFLAGS="$CFLAGS $WERROR -Wunused-parameter" - _define_flag="-Wno-unused-parameter" - test "x$_define_flag" = "x" && _define_flag="-Wunused-parameter" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ #include #include -/* Trivial function to help test for -fzero-call-used-regs */ -void f(int n) {} -int main(int argc, char **argv) { - (void)argv; +/* Trivial function to help test for flags like -fzero-call-used-regs. +Note compiler does not inform whether this option is supported unless it +runs into the situation where it would need to emit corresponding code.*/ +static int f(int n) {return n;} +int main(int argc, char *argv[]) { /* Some math to catch -ftrapv problems in the toolchain */ int i = 123 * argc, j = 456 + argc, k = 789 - argc; float l = i * 2.1; double m = l / 0.5; long long int n = argc * 12345LL, o = 12345LL * (long long int)argc; - f(0); - printf("%d %d %d %f %f %lld %lld\n", i, j, k, l, m, n, o); - /* - * Test fallthrough behaviour. clang 10's -Wimplicit-fallthrough does - * not understand comments and we don't use the "fallthrough" attribute - * that it's looking for. - */ - switch(i){ - case 0: j += i; - /* FALLTHROUGH */ - default: j += k; - } - exit(0); + long long int p = n * o; + printf("%d %d %d %f %f %lld %lld %lld %d\n", i, j, k, l, m, n, o, p, f(0)); + (void)argv; + return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO" -then : +if ac_fn_c_try_compile "$LINENO"; then : -if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null +if $EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } CFLAGS="$saved_CFLAGS" else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } CFLAGS="$saved_CFLAGS $_define_flag" fi -else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } CFLAGS="$saved_CFLAGS" fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext } + #unused parameter must be marked explicitly + #OSSH_CHECK_CFLAG_COMPILE([-Wunused-parameter], [-Wno-unused-parameter]) + #OSSH_CHECK_CFLAG_COMPILE([-Qunused-arguments]) { - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -Wunused-result" >&5 -printf %s "checking if $CC supports compile flag -Wunused-result... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -Wunused-result" >&5 +$as_echo_n "checking if $CC supports compile flag -Wunused-result... " >&6; } saved_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $WERROR -Wunused-result" _define_flag="-Wno-unused-result" @@ -6851,231 +6529,51 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -#include -#include -/* Trivial function to help test for -fzero-call-used-regs */ -void f(int n) {} -int main(int argc, char **argv) { - (void)argv; - /* Some math to catch -ftrapv problems in the toolchain */ - int i = 123 * argc, j = 456 + argc, k = 789 - argc; - float l = i * 2.1; - double m = l / 0.5; - long long int n = argc * 12345LL, o = 12345LL * (long long int)argc; - f(0); - printf("%d %d %d %f %f %lld %lld\n", i, j, k, l, m, n, o); - /* - * Test fallthrough behaviour. clang 10's -Wimplicit-fallthrough does - * not understand comments and we don't use the "fallthrough" attribute - * that it's looking for. - */ - switch(i){ - case 0: j += i; - /* FALLTHROUGH */ - default: j += k; - } - exit(0); -} - -_ACEOF -if ac_fn_c_try_compile "$LINENO" -then : - -if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null -then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } - CFLAGS="$saved_CFLAGS" -else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } - CFLAGS="$saved_CFLAGS $_define_flag" -fi -else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } - CFLAGS="$saved_CFLAGS" - -fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext -} - { - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -Wimplicit-fallthrough" >&5 -printf %s "checking if $CC supports compile flag -Wimplicit-fallthrough... " >&6; } - saved_CFLAGS="$CFLAGS" - CFLAGS="$CFLAGS $WERROR -Wimplicit-fallthrough" - _define_flag="" - test "x$_define_flag" = "x" && _define_flag="-Wimplicit-fallthrough" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ #include #include -/* Trivial function to help test for -fzero-call-used-regs */ -void f(int n) {} -int main(int argc, char **argv) { - (void)argv; +/* Trivial function to help test for flags like -fzero-call-used-regs. +Note compiler does not inform whether this option is supported unless it +runs into the situation where it would need to emit corresponding code.*/ +static int f(int n) {return n;} +int main(int argc, char *argv[]) { /* Some math to catch -ftrapv problems in the toolchain */ int i = 123 * argc, j = 456 + argc, k = 789 - argc; float l = i * 2.1; double m = l / 0.5; long long int n = argc * 12345LL, o = 12345LL * (long long int)argc; - f(0); - printf("%d %d %d %f %f %lld %lld\n", i, j, k, l, m, n, o); - /* - * Test fallthrough behaviour. clang 10's -Wimplicit-fallthrough does - * not understand comments and we don't use the "fallthrough" attribute - * that it's looking for. - */ - switch(i){ - case 0: j += i; - /* FALLTHROUGH */ - default: j += k; - } - exit(0); -} - -_ACEOF -if ac_fn_c_try_compile "$LINENO" -then : - -if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null -then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } - CFLAGS="$saved_CFLAGS" -else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } - CFLAGS="$saved_CFLAGS $_define_flag" -fi -else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } - CFLAGS="$saved_CFLAGS" - -fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext -} - { - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -Wmisleading-indentation" >&5 -printf %s "checking if $CC supports compile flag -Wmisleading-indentation... " >&6; } - saved_CFLAGS="$CFLAGS" - CFLAGS="$CFLAGS $WERROR -Wmisleading-indentation" - _define_flag="" - test "x$_define_flag" = "x" && _define_flag="-Wmisleading-indentation" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -#include -#include -/* Trivial function to help test for -fzero-call-used-regs */ -void f(int n) {} -int main(int argc, char **argv) { + long long int p = n * o; + printf("%d %d %d %f %f %lld %lld %lld %d\n", i, j, k, l, m, n, o, p, f(0)); (void)argv; - /* Some math to catch -ftrapv problems in the toolchain */ - int i = 123 * argc, j = 456 + argc, k = 789 - argc; - float l = i * 2.1; - double m = l / 0.5; - long long int n = argc * 12345LL, o = 12345LL * (long long int)argc; - f(0); - printf("%d %d %d %f %f %lld %lld\n", i, j, k, l, m, n, o); - /* - * Test fallthrough behaviour. clang 10's -Wimplicit-fallthrough does - * not understand comments and we don't use the "fallthrough" attribute - * that it's looking for. - */ - switch(i){ - case 0: j += i; - /* FALLTHROUGH */ - default: j += k; - } - exit(0); + return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO" -then : +if ac_fn_c_try_compile "$LINENO"; then : -if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null +if $EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } CFLAGS="$saved_CFLAGS" else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } CFLAGS="$saved_CFLAGS $_define_flag" fi -else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } - CFLAGS="$saved_CFLAGS" - -fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext -} - { - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -Wbitwise-instead-of-logical" >&5 -printf %s "checking if $CC supports compile flag -Wbitwise-instead-of-logical... " >&6; } - saved_CFLAGS="$CFLAGS" - CFLAGS="$CFLAGS $WERROR -Wbitwise-instead-of-logical" - _define_flag="" - test "x$_define_flag" = "x" && _define_flag="-Wbitwise-instead-of-logical" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -#include -#include -/* Trivial function to help test for -fzero-call-used-regs */ -void f(int n) {} -int main(int argc, char **argv) { - (void)argv; - /* Some math to catch -ftrapv problems in the toolchain */ - int i = 123 * argc, j = 456 + argc, k = 789 - argc; - float l = i * 2.1; - double m = l / 0.5; - long long int n = argc * 12345LL, o = 12345LL * (long long int)argc; - f(0); - printf("%d %d %d %f %f %lld %lld\n", i, j, k, l, m, n, o); - /* - * Test fallthrough behaviour. clang 10's -Wimplicit-fallthrough does - * not understand comments and we don't use the "fallthrough" attribute - * that it's looking for. - */ - switch(i){ - case 0: j += i; - /* FALLTHROUGH */ - default: j += k; - } - exit(0); -} - -_ACEOF -if ac_fn_c_try_compile "$LINENO" -then : - -if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null -then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } - CFLAGS="$saved_CFLAGS" else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } - CFLAGS="$saved_CFLAGS $_define_flag" -fi -else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } CFLAGS="$saved_CFLAGS" fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext } + #ignore bogus warnings on some compilers... + #OSSH_CHECK_CFLAG_COMPILE([-Wimplicit-fallthrough]) { - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -fno-strict-aliasing" >&5 -printf %s "checking if $CC supports compile flag -fno-strict-aliasing... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -fno-strict-aliasing" >&5 +$as_echo_n "checking if $CC supports compile flag -fno-strict-aliasing... " >&6; } saved_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $WERROR -fno-strict-aliasing" _define_flag="" @@ -7083,58 +6581,50 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ + #include #include -/* Trivial function to help test for -fzero-call-used-regs */ -void f(int n) {} -int main(int argc, char **argv) { - (void)argv; +/* Trivial function to help test for flags like -fzero-call-used-regs. +Note compiler does not inform whether this option is supported unless it +runs into the situation where it would need to emit corresponding code.*/ +static int f(int n) {return n;} +int main(int argc, char *argv[]) { /* Some math to catch -ftrapv problems in the toolchain */ int i = 123 * argc, j = 456 + argc, k = 789 - argc; float l = i * 2.1; double m = l / 0.5; long long int n = argc * 12345LL, o = 12345LL * (long long int)argc; - f(0); - printf("%d %d %d %f %f %lld %lld\n", i, j, k, l, m, n, o); - /* - * Test fallthrough behaviour. clang 10's -Wimplicit-fallthrough does - * not understand comments and we don't use the "fallthrough" attribute - * that it's looking for. - */ - switch(i){ - case 0: j += i; - /* FALLTHROUGH */ - default: j += k; - } - exit(0); + long long int p = n * o; + printf("%d %d %d %f %f %lld %lld %lld %d\n", i, j, k, l, m, n, o, p, f(0)); + (void)argv; + return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO" -then : +if ac_fn_c_try_compile "$LINENO"; then : -if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null +if $EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } CFLAGS="$saved_CFLAGS" else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } CFLAGS="$saved_CFLAGS $_define_flag" fi -else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } CFLAGS="$saved_CFLAGS" fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext } - if test "x$use_toolchain_hardening" = "x1"; then + if $use_toolchain_hardening ; then { - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -mretpoline" >&5 -printf %s "checking if $CC supports compile flag -mretpoline... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -mretpoline" >&5 +$as_echo_n "checking if $CC supports compile flag -mretpoline... " >&6; } saved_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $WERROR -mretpoline" _define_flag="" @@ -7142,57 +6632,49 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ + #include #include -/* Trivial function to help test for -fzero-call-used-regs */ -void f(int n) {} -int main(int argc, char **argv) { - (void)argv; +/* Trivial function to help test for flags like -fzero-call-used-regs. +Note compiler does not inform whether this option is supported unless it +runs into the situation where it would need to emit corresponding code.*/ +static int f(int n) {return n;} +int main(int argc, char *argv[]) { /* Some math to catch -ftrapv problems in the toolchain */ int i = 123 * argc, j = 456 + argc, k = 789 - argc; float l = i * 2.1; double m = l / 0.5; long long int n = argc * 12345LL, o = 12345LL * (long long int)argc; - f(0); - printf("%d %d %d %f %f %lld %lld\n", i, j, k, l, m, n, o); - /* - * Test fallthrough behaviour. clang 10's -Wimplicit-fallthrough does - * not understand comments and we don't use the "fallthrough" attribute - * that it's looking for. - */ - switch(i){ - case 0: j += i; - /* FALLTHROUGH */ - default: j += k; - } - exit(0); + long long int p = n * o; + printf("%d %d %d %f %f %lld %lld %lld %d\n", i, j, k, l, m, n, o, p, f(0)); + (void)argv; + return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO" -then : +if ac_fn_c_try_compile "$LINENO"; then : -if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null +if $EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } CFLAGS="$saved_CFLAGS" else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } CFLAGS="$saved_CFLAGS $_define_flag" fi -else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } CFLAGS="$saved_CFLAGS" fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext } # clang { - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $LD supports link flag -Wl,-z,retpolineplt" >&5 -printf %s "checking if $LD supports link flag -Wl,-z,retpolineplt... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $LD supports link flag -Wl,-z,retpolineplt" >&5 +$as_echo_n "checking if $LD supports link flag -Wl,-z,retpolineplt... " >&6; } saved_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS $WERROR -Wl,-z,retpolineplt" _define_flag="" @@ -7200,46 +6682,50 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ + #include #include -int main(int argc, char **argv) { - (void)argv; +/* Trivial function to help test for flags like -fzero-call-used-regs. +Note compiler does not inform whether this option is supported unless it +runs into the situation where it would need to emit corresponding code.*/ +static int f(int n) {return n;} +int main(int argc, char *argv[]) { /* Some math to catch -ftrapv problems in the toolchain */ int i = 123 * argc, j = 456 + argc, k = 789 - argc; float l = i * 2.1; double m = l / 0.5; long long int n = argc * 12345LL, o = 12345LL * (long long int)argc; - long long p = n * o; - printf("%d %d %d %f %f %lld %lld %lld\n", i, j, k, l, m, n, o, p); - exit(0); + long long int p = n * o; + printf("%d %d %d %f %f %lld %lld %lld %d\n", i, j, k, l, m, n, o, p, f(0)); + (void)argv; + return 0; } _ACEOF -if ac_fn_c_try_link "$LINENO" -then : +if ac_fn_c_try_link "$LINENO"; then : -if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null +if $EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } LDFLAGS="$saved_LDFLAGS" else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } LDFLAGS="$saved_LDFLAGS $_define_flag" fi -else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } LDFLAGS="$saved_LDFLAGS" fi -rm -f core conftest.err conftest.$ac_objext conftest.beam \ +rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext } { - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -D_FORTIFY_SOURCE=2" >&5 -printf %s "checking if $CC supports compile flag -D_FORTIFY_SOURCE=2... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -D_FORTIFY_SOURCE=2" >&5 +$as_echo_n "checking if $CC supports compile flag -D_FORTIFY_SOURCE=2... " >&6; } saved_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $WERROR -D_FORTIFY_SOURCE=2" _define_flag="" @@ -7247,57 +6733,49 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ + #include #include -/* Trivial function to help test for -fzero-call-used-regs */ -void f(int n) {} -int main(int argc, char **argv) { - (void)argv; +/* Trivial function to help test for flags like -fzero-call-used-regs. +Note compiler does not inform whether this option is supported unless it +runs into the situation where it would need to emit corresponding code.*/ +static int f(int n) {return n;} +int main(int argc, char *argv[]) { /* Some math to catch -ftrapv problems in the toolchain */ int i = 123 * argc, j = 456 + argc, k = 789 - argc; float l = i * 2.1; double m = l / 0.5; long long int n = argc * 12345LL, o = 12345LL * (long long int)argc; - f(0); - printf("%d %d %d %f %f %lld %lld\n", i, j, k, l, m, n, o); - /* - * Test fallthrough behaviour. clang 10's -Wimplicit-fallthrough does - * not understand comments and we don't use the "fallthrough" attribute - * that it's looking for. - */ - switch(i){ - case 0: j += i; - /* FALLTHROUGH */ - default: j += k; - } - exit(0); + long long int p = n * o; + printf("%d %d %d %f %f %lld %lld %lld %d\n", i, j, k, l, m, n, o, p, f(0)); + (void)argv; + return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO" -then : +if ac_fn_c_try_compile "$LINENO"; then : -if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null +if $EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } CFLAGS="$saved_CFLAGS" else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } CFLAGS="$saved_CFLAGS $_define_flag" fi -else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } CFLAGS="$saved_CFLAGS" fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext } { - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $LD supports link flag -Wl,-z,relro" >&5 -printf %s "checking if $LD supports link flag -Wl,-z,relro... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $LD supports link flag -Wl,-z,relro" >&5 +$as_echo_n "checking if $LD supports link flag -Wl,-z,relro... " >&6; } saved_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS $WERROR -Wl,-z,relro" _define_flag="" @@ -7305,46 +6783,50 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ + #include #include -int main(int argc, char **argv) { - (void)argv; +/* Trivial function to help test for flags like -fzero-call-used-regs. +Note compiler does not inform whether this option is supported unless it +runs into the situation where it would need to emit corresponding code.*/ +static int f(int n) {return n;} +int main(int argc, char *argv[]) { /* Some math to catch -ftrapv problems in the toolchain */ int i = 123 * argc, j = 456 + argc, k = 789 - argc; float l = i * 2.1; double m = l / 0.5; long long int n = argc * 12345LL, o = 12345LL * (long long int)argc; - long long p = n * o; - printf("%d %d %d %f %f %lld %lld %lld\n", i, j, k, l, m, n, o, p); - exit(0); + long long int p = n * o; + printf("%d %d %d %f %f %lld %lld %lld %d\n", i, j, k, l, m, n, o, p, f(0)); + (void)argv; + return 0; } _ACEOF -if ac_fn_c_try_link "$LINENO" -then : +if ac_fn_c_try_link "$LINENO"; then : -if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null +if $EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } LDFLAGS="$saved_LDFLAGS" else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } LDFLAGS="$saved_LDFLAGS $_define_flag" fi -else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } LDFLAGS="$saved_LDFLAGS" fi -rm -f core conftest.err conftest.$ac_objext conftest.beam \ +rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext } { - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $LD supports link flag -Wl,-z,now" >&5 -printf %s "checking if $LD supports link flag -Wl,-z,now... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $LD supports link flag -Wl,-z,now" >&5 +$as_echo_n "checking if $LD supports link flag -Wl,-z,now... " >&6; } saved_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS $WERROR -Wl,-z,now" _define_flag="" @@ -7352,46 +6834,50 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ + #include #include -int main(int argc, char **argv) { - (void)argv; +/* Trivial function to help test for flags like -fzero-call-used-regs. +Note compiler does not inform whether this option is supported unless it +runs into the situation where it would need to emit corresponding code.*/ +static int f(int n) {return n;} +int main(int argc, char *argv[]) { /* Some math to catch -ftrapv problems in the toolchain */ int i = 123 * argc, j = 456 + argc, k = 789 - argc; float l = i * 2.1; double m = l / 0.5; long long int n = argc * 12345LL, o = 12345LL * (long long int)argc; - long long p = n * o; - printf("%d %d %d %f %f %lld %lld %lld\n", i, j, k, l, m, n, o, p); - exit(0); + long long int p = n * o; + printf("%d %d %d %f %f %lld %lld %lld %d\n", i, j, k, l, m, n, o, p, f(0)); + (void)argv; + return 0; } _ACEOF -if ac_fn_c_try_link "$LINENO" -then : +if ac_fn_c_try_link "$LINENO"; then : -if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null +if $EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } LDFLAGS="$saved_LDFLAGS" else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } LDFLAGS="$saved_LDFLAGS $_define_flag" fi -else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } LDFLAGS="$saved_LDFLAGS" fi -rm -f core conftest.err conftest.$ac_objext conftest.beam \ +rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext } { - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $LD supports link flag -Wl,-z,noexecstack" >&5 -printf %s "checking if $LD supports link flag -Wl,-z,noexecstack... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $LD supports link flag -Wl,-z,noexecstack" >&5 +$as_echo_n "checking if $LD supports link flag -Wl,-z,noexecstack... " >&6; } saved_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS $WERROR -Wl,-z,noexecstack" _define_flag="" @@ -7399,41 +6885,45 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ + #include #include -int main(int argc, char **argv) { - (void)argv; +/* Trivial function to help test for flags like -fzero-call-used-regs. +Note compiler does not inform whether this option is supported unless it +runs into the situation where it would need to emit corresponding code.*/ +static int f(int n) {return n;} +int main(int argc, char *argv[]) { /* Some math to catch -ftrapv problems in the toolchain */ int i = 123 * argc, j = 456 + argc, k = 789 - argc; float l = i * 2.1; double m = l / 0.5; long long int n = argc * 12345LL, o = 12345LL * (long long int)argc; - long long p = n * o; - printf("%d %d %d %f %f %lld %lld %lld\n", i, j, k, l, m, n, o, p); - exit(0); + long long int p = n * o; + printf("%d %d %d %f %f %lld %lld %lld %d\n", i, j, k, l, m, n, o, p, f(0)); + (void)argv; + return 0; } _ACEOF -if ac_fn_c_try_link "$LINENO" -then : +if ac_fn_c_try_link "$LINENO"; then : -if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null +if $EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } LDFLAGS="$saved_LDFLAGS" else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } LDFLAGS="$saved_LDFLAGS $_define_flag" fi -else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } LDFLAGS="$saved_LDFLAGS" fi -rm -f core conftest.err conftest.$ac_objext conftest.beam \ +rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext } # NB. -ftrapv expects certain support functions to be present in @@ -7441,270 +6931,59 @@ # that can overflow. We must check that the result of enabling it # actually links. The test program compiled/linked includes a number # of integer operations that should exercise this. - { - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -ftrapv and linking succeeds" >&5 -printf %s "checking if $CC supports compile flag -ftrapv and linking succeeds... " >&6; } - saved_CFLAGS="$CFLAGS" - CFLAGS="$CFLAGS $WERROR -ftrapv" - _define_flag="" - test "x$_define_flag" = "x" && _define_flag="-ftrapv" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ + # + # Remark: Option -ftrapv is not maintained and does not work on + # all platforms. Use -fsanitize=... instead. + #-#OSSH_CHECK_CFLAG_LINK([-ftrapv]) -#include -#include -int main(int argc, char **argv) { - (void)argv; - /* Some math to catch -ftrapv problems in the toolchain */ - int i = 123 * argc, j = 456 + argc, k = 789 - argc; - float l = i * 2.1; - double m = l / 0.5; - long long int n = argc * 12345LL, o = 12345LL * (long long int)argc; - long long int p = n * o; - printf("%d %d %d %f %f %lld %lld %lld\n", i, j, k, l, m, n, o, p); - exit(0); -} - -_ACEOF -if ac_fn_c_try_link "$LINENO" -then : - -if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null -then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } - CFLAGS="$saved_CFLAGS" -else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } - CFLAGS="$saved_CFLAGS $_define_flag" -fi -else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } - CFLAGS="$saved_CFLAGS" - -fi -rm -f core conftest.err conftest.$ac_objext conftest.beam \ - conftest$ac_exeext conftest.$ac_ext -} + # TODO: wipe used registers # clang 15 seems to have a bug in -fzero-call-used-regs=all. See - # https://bugzilla.mindrot.org/show_bug.cgi?id=3475 and # https://github.com/llvm/llvm-project/issues/59242 - case "$CLANG_VER" in - 15.*) { - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -fzero-call-used-regs=used" >&5 -printf %s "checking if $CC supports compile flag -fzero-call-used-regs=used... " >&6; } - saved_CFLAGS="$CFLAGS" - CFLAGS="$CFLAGS $WERROR -fzero-call-used-regs=used" - _define_flag="" - test "x$_define_flag" = "x" && _define_flag="-fzero-call-used-regs=used" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -#include -#include -/* Trivial function to help test for -fzero-call-used-regs */ -void f(int n) {} -int main(int argc, char **argv) { - (void)argv; - /* Some math to catch -ftrapv problems in the toolchain */ - int i = 123 * argc, j = 456 + argc, k = 789 - argc; - float l = i * 2.1; - double m = l / 0.5; - long long int n = argc * 12345LL, o = 12345LL * (long long int)argc; - f(0); - printf("%d %d %d %f %f %lld %lld\n", i, j, k, l, m, n, o); - /* - * Test fallthrough behaviour. clang 10's -Wimplicit-fallthrough does - * not understand comments and we don't use the "fallthrough" attribute - * that it's looking for. - */ - switch(i){ - case 0: j += i; - /* FALLTHROUGH */ - default: j += k; - } - exit(0); -} - -_ACEOF -if ac_fn_c_try_compile "$LINENO" -then : - -if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null -then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } - CFLAGS="$saved_CFLAGS" -else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } - CFLAGS="$saved_CFLAGS $_define_flag" -fi -else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } - CFLAGS="$saved_CFLAGS" - -fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext -} ;; - *) { - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -fzero-call-used-regs=all" >&5 -printf %s "checking if $CC supports compile flag -fzero-call-used-regs=all... " >&6; } - saved_CFLAGS="$CFLAGS" - CFLAGS="$CFLAGS $WERROR -fzero-call-used-regs=all" - _define_flag="" - test "x$_define_flag" = "x" && _define_flag="-fzero-call-used-regs=all" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -#include -#include -/* Trivial function to help test for -fzero-call-used-regs */ -void f(int n) {} -int main(int argc, char **argv) { - (void)argv; - /* Some math to catch -ftrapv problems in the toolchain */ - int i = 123 * argc, j = 456 + argc, k = 789 - argc; - float l = i * 2.1; - double m = l / 0.5; - long long int n = argc * 12345LL, o = 12345LL * (long long int)argc; - f(0); - printf("%d %d %d %f %f %lld %lld\n", i, j, k, l, m, n, o); - /* - * Test fallthrough behaviour. clang 10's -Wimplicit-fallthrough does - * not understand comments and we don't use the "fallthrough" attribute - * that it's looking for. - */ - switch(i){ - case 0: j += i; - /* FALLTHROUGH */ - default: j += k; - } - exit(0); -} - -_ACEOF -if ac_fn_c_try_compile "$LINENO" -then : - -if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null -then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } - CFLAGS="$saved_CFLAGS" -else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } - CFLAGS="$saved_CFLAGS $_define_flag" -fi -else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } - CFLAGS="$saved_CFLAGS" - -fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext -} ;; - esac - { - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -ftrivial-auto-var-init=zero" >&5 -printf %s "checking if $CC supports compile flag -ftrivial-auto-var-init=zero... " >&6; } - saved_CFLAGS="$CFLAGS" - CFLAGS="$CFLAGS $WERROR -ftrivial-auto-var-init=zero" - _define_flag="" - test "x$_define_flag" = "x" && _define_flag="-ftrivial-auto-var-init=zero" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -#include -#include -/* Trivial function to help test for -fzero-call-used-regs */ -void f(int n) {} -int main(int argc, char **argv) { - (void)argv; - /* Some math to catch -ftrapv problems in the toolchain */ - int i = 123 * argc, j = 456 + argc, k = 789 - argc; - float l = i * 2.1; - double m = l / 0.5; - long long int n = argc * 12345LL, o = 12345LL * (long long int)argc; - f(0); - printf("%d %d %d %f %f %lld %lld\n", i, j, k, l, m, n, o); - /* - * Test fallthrough behaviour. clang 10's -Wimplicit-fallthrough does - * not understand comments and we don't use the "fallthrough" attribute - * that it's looking for. - */ - switch(i){ - case 0: j += i; - /* FALLTHROUGH */ - default: j += k; - } - exit(0); -} - -_ACEOF -if ac_fn_c_try_compile "$LINENO" -then : - -if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null -then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } - CFLAGS="$saved_CFLAGS" -else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } - CFLAGS="$saved_CFLAGS $_define_flag" -fi -else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } - CFLAGS="$saved_CFLAGS" - -fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext -} + #case "$CLANG_VER" in + #15.*) OSSH_CHECK_CFLAG_COMPILE([-fzero-call-used-regs=used]) ;; + #*) OSSH_CHECK_CFLAG_COMPILE([-fzero-call-used-regs=all]) ;; + #esac + + # TODO: stack variables auto-initialization + # (see -Wuninitialized) + #-#OSSH_CHECK_CFLAG_COMPILE([-ftrivial-auto-var-init=zero]) fi - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $CC accepts -fno-builtin-memset" >&5 -printf %s "checking if $CC accepts -fno-builtin-memset... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC accepts -fno-builtin-memset" >&5 +$as_echo_n "checking if $CC accepts -fno-builtin-memset... " >&6; } saved_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -fno-builtin-memset" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int -main (void) +main () { char b[10]; memset(b, 0, sizeof(b)); ; return 0; } _ACEOF -if ac_fn_c_try_link "$LINENO" -then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } -else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } +if ac_fn_c_try_link "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } CFLAGS="$saved_CFLAGS" fi -rm -f core conftest.err conftest.$ac_objext conftest.beam \ +rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext # -fstack-protector-all doesn't always work for some GCC versions # and/or platforms, so we test if we can. If it's not supported # on a given platform gcc will emit a warning so we use -Werror. - if test "x$use_stack_protector" = "x1"; then + if $use_stack_protector ; then for t in -fstack-protector-strong -fstack-protector-all \ -fstack-protector; do - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $CC supports $t" >&5 -printf %s "checking if $CC supports $t... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC supports $t" >&5 +$as_echo_n "checking if $CC supports $t... " >&6; } saved_CFLAGS="$CFLAGS" saved_LDFLAGS="$LDFLAGS" CFLAGS="$CFLAGS $t -Werror" @@ -7712,11 +6991,13 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ - #include - int func (int t) {char b[100]; snprintf(b,sizeof b,"%d",t); return t;} +#include + +int func (int t); +int func (int t) {char b[100]; snprintf(b,sizeof b,"%d",t); return t;} int -main (void) +main () { char x[256]; @@ -7726,29 +7007,29 @@ return 0; } _ACEOF -if ac_fn_c_try_link "$LINENO" -then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } +if ac_fn_c_try_link "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } CFLAGS="$saved_CFLAGS $t" LDFLAGS="$saved_LDFLAGS $t" - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $t works" >&5 -printf %s "checking if $t works... " >&6; } - if test "$cross_compiling" = yes -then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: cannot test" >&5 -printf "%s\n" "$as_me: WARNING: cross compiling: cannot test" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $t works" >&5 +$as_echo_n "checking if $t works... " >&6; } + if test "$cross_compiling" = yes; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: cannot test" >&5 +$as_echo "$as_me: WARNING: cross compiling: cannot test" >&2;} break -else $as_nop +else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ - #include - int func (int t) {char b[100]; snprintf(b,sizeof b,"%d",t); return t;} +#include + +int func (int t); +int func (int t) {char b[100]; snprintf(b,sizeof b,"%d",t); return t;} int -main (void) +main () { char x[256]; @@ -7758,177 +7039,162 @@ return 0; } _ACEOF -if ac_fn_c_try_run "$LINENO" -then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } +if ac_fn_c_try_run "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } break -else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi -else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } fi -rm -f core conftest.err conftest.$ac_objext conftest.beam \ +rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext CFLAGS="$saved_CFLAGS" LDFLAGS="$saved_LDFLAGS" done fi + # keep check as C99 is not strictly required if test -z "$have_llong_max"; then # retry LLONG_MAX with -std=gnu99, needed on some Linuxes unset ac_cv_have_decl_LLONG_MAX saved_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -std=gnu99" - ac_fn_check_decl "$LINENO" "LLONG_MAX" "ac_cv_have_decl_LLONG_MAX" "#include + ac_fn_c_check_decl "$LINENO" "LLONG_MAX" "ac_cv_have_decl_LLONG_MAX" "#include -" "$ac_c_undeclared_builtin_options" "CFLAGS" -if test "x$ac_cv_have_decl_LLONG_MAX" = xyes -then : +" +if test "x$ac_cv_have_decl_LLONG_MAX" = xyes; then : have_llong_max=1 -else $as_nop +else CFLAGS="$saved_CFLAGS" fi + fi fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if compiler allows __attribute__ on return types" >&5 -printf %s "checking if compiler allows __attribute__ on return types... " >&6; } -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -#include -__attribute__((__unused__)) static void foo(void){return;} -int -main (void) -{ - exit(0); - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO" -then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } -else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } - -printf "%s\n" "#define NO_ATTRIBUTE_ON_RETURN_TYPE 1" >>confdefs.h +if test -z "$have_llong_max" ; then + ac_fn_c_check_decl "$LINENO" "LONGLONG_MAX" "ac_cv_have_decl_LONGLONG_MAX" "#include +" +if test "x$ac_cv_have_decl_LONGLONG_MAX" = xyes; then : + have_llong_max=1 +fi +fi +if test -z "$have_llong_max" ; then + ac_fn_c_check_decl "$LINENO" "LONG_LONG_MAX" "ac_cv_have_decl_LONG_LONG_MAX" "#include +" +if test "x$ac_cv_have_decl_LONG_LONG_MAX" = xyes; then : + have_llong_max=1 +fi fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if compiler allows __attribute__ prototype args" >&5 -printf %s "checking if compiler allows __attribute__ prototype args... " >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if compiler allows __attribute__ on return types" >&5 +$as_echo_n "checking if compiler allows __attribute__ on return types... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -#include -typedef void foo(const char *, ...) __attribute__((format(printf, 1, 2))); +__attribute__((__unused__)) static void foo(void){return;} int -main (void) +main () { - exit(0); + ; return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO" -then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } -else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } +if ac_fn_c_try_compile "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } -printf "%s\n" "#define NO_ATTRIBUTE_ON_PROTOTYPE_ARGS 1" >>confdefs.h +$as_echo "#define NO_ATTRIBUTE_ON_RETURN_TYPE 1" >>confdefs.h fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if compiler supports variable length arrays" >&5 -printf %s "checking if compiler supports variable length arrays... " >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if compiler allows __attribute__ prototype args" >&5 +$as_echo_n "checking if compiler allows __attribute__ prototype args... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -#include + +typedef void foo(const char *, ...) __attribute__((format(printf, 1, 2))); int -main (void) +main () { - int i; for (i=0; i<3; i++){int a[i]; a[i-1]=0;} exit(0); + ; return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO" -then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } +if ac_fn_c_try_compile "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } -printf "%s\n" "#define VARIABLE_LENGTH_ARRAYS 1" >>confdefs.h +$as_echo "#define NO_ATTRIBUTE_ON_PROTOTYPE_ARGS 1" >>confdefs.h -else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if compiler accepts variable declarations after code" >&5 -printf %s "checking if compiler accepts variable declarations after code... " >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if compiler allows __attribute__ to warn if last parameter is not NULL" >&5 +$as_echo_n "checking if compiler allows __attribute__ to warn if last parameter is not NULL... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -#include + +extern void foo(const char *, ...) __attribute__((__sentinel__)); int -main (void) +main () { - int a; a = 1; int b = 1; exit(a-b); + ; return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO" -then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } +if ac_fn_c_try_compile "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +$as_echo "#define HAVE_ATTRIBUTE__SENTINEL__ 1" >>confdefs.h -printf "%s\n" "#define VARIABLE_DECLARATION_AFTER_CODE 1" >>confdefs.h -else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext if test "x$no_attrib_nonnull" != "x1" ; then -printf "%s\n" "#define HAVE_ATTRIBUTE__NONNULL__ 1" >>confdefs.h +$as_echo "#define HAVE_ATTRIBUTE__NONNULL__ 1" >>confdefs.h fi +rpath_opt= # Check whether --with-rpath was given. -if test ${with_rpath+y} -then : +if test "${with_rpath+set}" = set; then : withval=$with_rpath; - if test "x$withval" = "xno" ; then - rpath_opt="" - elif test "x$withval" = "xyes" ; then + if test "x$withval" = "xyes" ; then rpath_opt="-R" - else + elif test "x$withval" != "xno" ; then rpath_opt="$withval" fi @@ -7939,8 +7205,7 @@ # Allow user to specify flags # Check whether --with-cflags was given. -if test ${with_cflags+y} -then : +if test "${with_cflags+set}" = set; then : withval=$with_cflags; if test -n "$withval" && test "x$withval" != "xno" && \ test "x${withval}" != "xyes"; then @@ -7953,8 +7218,7 @@ # Check whether --with-cflags-after was given. -if test ${with_cflags_after+y} -then : +if test "${with_cflags_after+set}" = set; then : withval=$with_cflags_after; if test -n "$withval" && test "x$withval" != "xno" && \ test "x${withval}" != "xyes"; then @@ -7966,8 +7230,7 @@ # Check whether --with-cppflags was given. -if test ${with_cppflags+y} -then : +if test "${with_cppflags+set}" = set; then : withval=$with_cppflags; if test -n "$withval" && test "x$withval" != "xno" && \ test "x${withval}" != "xyes"; then @@ -7979,8 +7242,7 @@ # Check whether --with-ldflags was given. -if test ${with_ldflags+y} -then : +if test "${with_ldflags+set}" = set; then : withval=$with_ldflags; if test -n "$withval" && test "x$withval" != "xno" && \ test "x${withval}" != "xyes"; then @@ -7992,8 +7254,7 @@ # Check whether --with-ldflags-after was given. -if test ${with_ldflags_after+y} -then : +if test "${with_ldflags_after+set}" = set; then : withval=$with_ldflags_after; if test -n "$withval" && test "x$withval" != "xno" && \ test "x${withval}" != "xyes"; then @@ -8005,8 +7266,7 @@ # Check whether --with-libs was given. -if test ${with_libs+y} -then : +if test "${with_libs+set}" = set; then : withval=$with_libs; if test -n "$withval" && test "x$withval" != "xno" && \ test "x${withval}" != "xyes"; then @@ -8018,8 +7278,7 @@ # Check whether --with-Werror was given. -if test ${with_Werror+y} -then : +if test "${with_Werror+set}" = set; then : withval=$with_Werror; if test -n "$withval" && test "x$withval" != "xno"; then werror_flags="-Werror" @@ -8032,484 +7291,97 @@ fi -if test "x$ac_cv_header_sys_stat_h" != "xyes"; then - unset ac_cv_header_sys_stat_h - ac_fn_c_check_header_compile "$LINENO" "sys/stat.h" "ac_cv_header_sys_stat_h" "$ac_includes_default" -if test "x$ac_cv_header_sys_stat_h" = xyes -then : - printf "%s\n" "#define HAVE_SYS_STAT_H 1" >>confdefs.h - -fi - -fi - -ac_fn_c_check_header_compile "$LINENO" "blf.h" "ac_cv_header_blf_h" "$ac_includes_default" -if test "x$ac_cv_header_blf_h" = xyes -then : - printf "%s\n" "#define HAVE_BLF_H 1" >>confdefs.h - -fi -ac_fn_c_check_header_compile "$LINENO" "bstring.h" "ac_cv_header_bstring_h" "$ac_includes_default" -if test "x$ac_cv_header_bstring_h" = xyes -then : - printf "%s\n" "#define HAVE_BSTRING_H 1" >>confdefs.h - -fi -ac_fn_c_check_header_compile "$LINENO" "crypt.h" "ac_cv_header_crypt_h" "$ac_includes_default" -if test "x$ac_cv_header_crypt_h" = xyes -then : - printf "%s\n" "#define HAVE_CRYPT_H 1" >>confdefs.h - -fi -ac_fn_c_check_header_compile "$LINENO" "crypto/sha2.h" "ac_cv_header_crypto_sha2_h" "$ac_includes_default" -if test "x$ac_cv_header_crypto_sha2_h" = xyes -then : - printf "%s\n" "#define HAVE_CRYPTO_SHA2_H 1" >>confdefs.h - -fi -ac_fn_c_check_header_compile "$LINENO" "dirent.h" "ac_cv_header_dirent_h" "$ac_includes_default" -if test "x$ac_cv_header_dirent_h" = xyes -then : - printf "%s\n" "#define HAVE_DIRENT_H 1" >>confdefs.h - -fi -ac_fn_c_check_header_compile "$LINENO" "endian.h" "ac_cv_header_endian_h" "$ac_includes_default" -if test "x$ac_cv_header_endian_h" = xyes -then : - printf "%s\n" "#define HAVE_ENDIAN_H 1" >>confdefs.h - -fi -ac_fn_c_check_header_compile "$LINENO" "elf.h" "ac_cv_header_elf_h" "$ac_includes_default" -if test "x$ac_cv_header_elf_h" = xyes -then : - printf "%s\n" "#define HAVE_ELF_H 1" >>confdefs.h - -fi -ac_fn_c_check_header_compile "$LINENO" "err.h" "ac_cv_header_err_h" "$ac_includes_default" -if test "x$ac_cv_header_err_h" = xyes -then : - printf "%s\n" "#define HAVE_ERR_H 1" >>confdefs.h - -fi -ac_fn_c_check_header_compile "$LINENO" "features.h" "ac_cv_header_features_h" "$ac_includes_default" -if test "x$ac_cv_header_features_h" = xyes -then : - printf "%s\n" "#define HAVE_FEATURES_H 1" >>confdefs.h - -fi -ac_fn_c_check_header_compile "$LINENO" "fcntl.h" "ac_cv_header_fcntl_h" "$ac_includes_default" -if test "x$ac_cv_header_fcntl_h" = xyes -then : - printf "%s\n" "#define HAVE_FCNTL_H 1" >>confdefs.h - -fi -ac_fn_c_check_header_compile "$LINENO" "floatingpoint.h" "ac_cv_header_floatingpoint_h" "$ac_includes_default" -if test "x$ac_cv_header_floatingpoint_h" = xyes -then : - printf "%s\n" "#define HAVE_FLOATINGPOINT_H 1" >>confdefs.h - -fi -ac_fn_c_check_header_compile "$LINENO" "fnmatch.h" "ac_cv_header_fnmatch_h" "$ac_includes_default" -if test "x$ac_cv_header_fnmatch_h" = xyes -then : - printf "%s\n" "#define HAVE_FNMATCH_H 1" >>confdefs.h - -fi -ac_fn_c_check_header_compile "$LINENO" "getopt.h" "ac_cv_header_getopt_h" "$ac_includes_default" -if test "x$ac_cv_header_getopt_h" = xyes -then : - printf "%s\n" "#define HAVE_GETOPT_H 1" >>confdefs.h - -fi -ac_fn_c_check_header_compile "$LINENO" "glob.h" "ac_cv_header_glob_h" "$ac_includes_default" -if test "x$ac_cv_header_glob_h" = xyes -then : - printf "%s\n" "#define HAVE_GLOB_H 1" >>confdefs.h - -fi -ac_fn_c_check_header_compile "$LINENO" "ia.h" "ac_cv_header_ia_h" "$ac_includes_default" -if test "x$ac_cv_header_ia_h" = xyes -then : - printf "%s\n" "#define HAVE_IA_H 1" >>confdefs.h - -fi -ac_fn_c_check_header_compile "$LINENO" "iaf.h" "ac_cv_header_iaf_h" "$ac_includes_default" -if test "x$ac_cv_header_iaf_h" = xyes -then : - printf "%s\n" "#define HAVE_IAF_H 1" >>confdefs.h - -fi -ac_fn_c_check_header_compile "$LINENO" "ifaddrs.h" "ac_cv_header_ifaddrs_h" "$ac_includes_default" -if test "x$ac_cv_header_ifaddrs_h" = xyes -then : - printf "%s\n" "#define HAVE_IFADDRS_H 1" >>confdefs.h - -fi -ac_fn_c_check_header_compile "$LINENO" "inttypes.h" "ac_cv_header_inttypes_h" "$ac_includes_default" -if test "x$ac_cv_header_inttypes_h" = xyes -then : - printf "%s\n" "#define HAVE_INTTYPES_H 1" >>confdefs.h - -fi -ac_fn_c_check_header_compile "$LINENO" "langinfo.h" "ac_cv_header_langinfo_h" "$ac_includes_default" -if test "x$ac_cv_header_langinfo_h" = xyes -then : - printf "%s\n" "#define HAVE_LANGINFO_H 1" >>confdefs.h - -fi -ac_fn_c_check_header_compile "$LINENO" "limits.h" "ac_cv_header_limits_h" "$ac_includes_default" -if test "x$ac_cv_header_limits_h" = xyes -then : - printf "%s\n" "#define HAVE_LIMITS_H 1" >>confdefs.h - -fi -ac_fn_c_check_header_compile "$LINENO" "locale.h" "ac_cv_header_locale_h" "$ac_includes_default" -if test "x$ac_cv_header_locale_h" = xyes -then : - printf "%s\n" "#define HAVE_LOCALE_H 1" >>confdefs.h - -fi -ac_fn_c_check_header_compile "$LINENO" "login.h" "ac_cv_header_login_h" "$ac_includes_default" -if test "x$ac_cv_header_login_h" = xyes -then : - printf "%s\n" "#define HAVE_LOGIN_H 1" >>confdefs.h - -fi -ac_fn_c_check_header_compile "$LINENO" "maillock.h" "ac_cv_header_maillock_h" "$ac_includes_default" -if test "x$ac_cv_header_maillock_h" = xyes -then : - printf "%s\n" "#define HAVE_MAILLOCK_H 1" >>confdefs.h - -fi -ac_fn_c_check_header_compile "$LINENO" "ndir.h" "ac_cv_header_ndir_h" "$ac_includes_default" -if test "x$ac_cv_header_ndir_h" = xyes -then : - printf "%s\n" "#define HAVE_NDIR_H 1" >>confdefs.h - -fi -ac_fn_c_check_header_compile "$LINENO" "net/if_tun.h" "ac_cv_header_net_if_tun_h" "$ac_includes_default" -if test "x$ac_cv_header_net_if_tun_h" = xyes -then : - printf "%s\n" "#define HAVE_NET_IF_TUN_H 1" >>confdefs.h - -fi -ac_fn_c_check_header_compile "$LINENO" "netdb.h" "ac_cv_header_netdb_h" "$ac_includes_default" -if test "x$ac_cv_header_netdb_h" = xyes -then : - printf "%s\n" "#define HAVE_NETDB_H 1" >>confdefs.h - -fi -ac_fn_c_check_header_compile "$LINENO" "netgroup.h" "ac_cv_header_netgroup_h" "$ac_includes_default" -if test "x$ac_cv_header_netgroup_h" = xyes -then : - printf "%s\n" "#define HAVE_NETGROUP_H 1" >>confdefs.h - -fi -ac_fn_c_check_header_compile "$LINENO" "pam/pam_appl.h" "ac_cv_header_pam_pam_appl_h" "$ac_includes_default" -if test "x$ac_cv_header_pam_pam_appl_h" = xyes -then : - printf "%s\n" "#define HAVE_PAM_PAM_APPL_H 1" >>confdefs.h - -fi -ac_fn_c_check_header_compile "$LINENO" "paths.h" "ac_cv_header_paths_h" "$ac_includes_default" -if test "x$ac_cv_header_paths_h" = xyes -then : - printf "%s\n" "#define HAVE_PATHS_H 1" >>confdefs.h - -fi -ac_fn_c_check_header_compile "$LINENO" "poll.h" "ac_cv_header_poll_h" "$ac_includes_default" -if test "x$ac_cv_header_poll_h" = xyes -then : - printf "%s\n" "#define HAVE_POLL_H 1" >>confdefs.h - -fi -ac_fn_c_check_header_compile "$LINENO" "pty.h" "ac_cv_header_pty_h" "$ac_includes_default" -if test "x$ac_cv_header_pty_h" = xyes -then : - printf "%s\n" "#define HAVE_PTY_H 1" >>confdefs.h - -fi -ac_fn_c_check_header_compile "$LINENO" "readpassphrase.h" "ac_cv_header_readpassphrase_h" "$ac_includes_default" -if test "x$ac_cv_header_readpassphrase_h" = xyes -then : - printf "%s\n" "#define HAVE_READPASSPHRASE_H 1" >>confdefs.h - -fi -ac_fn_c_check_header_compile "$LINENO" "rpc/types.h" "ac_cv_header_rpc_types_h" "$ac_includes_default" -if test "x$ac_cv_header_rpc_types_h" = xyes -then : - printf "%s\n" "#define HAVE_RPC_TYPES_H 1" >>confdefs.h - -fi -ac_fn_c_check_header_compile "$LINENO" "security/pam_appl.h" "ac_cv_header_security_pam_appl_h" "$ac_includes_default" -if test "x$ac_cv_header_security_pam_appl_h" = xyes -then : - printf "%s\n" "#define HAVE_SECURITY_PAM_APPL_H 1" >>confdefs.h - -fi -ac_fn_c_check_header_compile "$LINENO" "sha2.h" "ac_cv_header_sha2_h" "$ac_includes_default" -if test "x$ac_cv_header_sha2_h" = xyes -then : - printf "%s\n" "#define HAVE_SHA2_H 1" >>confdefs.h - -fi -ac_fn_c_check_header_compile "$LINENO" "shadow.h" "ac_cv_header_shadow_h" "$ac_includes_default" -if test "x$ac_cv_header_shadow_h" = xyes -then : - printf "%s\n" "#define HAVE_SHADOW_H 1" >>confdefs.h - -fi -ac_fn_c_check_header_compile "$LINENO" "stddef.h" "ac_cv_header_stddef_h" "$ac_includes_default" -if test "x$ac_cv_header_stddef_h" = xyes -then : - printf "%s\n" "#define HAVE_STDDEF_H 1" >>confdefs.h - -fi -ac_fn_c_check_header_compile "$LINENO" "stdint.h" "ac_cv_header_stdint_h" "$ac_includes_default" -if test "x$ac_cv_header_stdint_h" = xyes -then : - printf "%s\n" "#define HAVE_STDINT_H 1" >>confdefs.h - -fi -ac_fn_c_check_header_compile "$LINENO" "string.h" "ac_cv_header_string_h" "$ac_includes_default" -if test "x$ac_cv_header_string_h" = xyes -then : - printf "%s\n" "#define HAVE_STRING_H 1" >>confdefs.h - -fi -ac_fn_c_check_header_compile "$LINENO" "strings.h" "ac_cv_header_strings_h" "$ac_includes_default" -if test "x$ac_cv_header_strings_h" = xyes -then : - printf "%s\n" "#define HAVE_STRINGS_H 1" >>confdefs.h - -fi -ac_fn_c_check_header_compile "$LINENO" "sys/bitypes.h" "ac_cv_header_sys_bitypes_h" "$ac_includes_default" -if test "x$ac_cv_header_sys_bitypes_h" = xyes -then : - printf "%s\n" "#define HAVE_SYS_BITYPES_H 1" >>confdefs.h - -fi -ac_fn_c_check_header_compile "$LINENO" "sys/byteorder.h" "ac_cv_header_sys_byteorder_h" "$ac_includes_default" -if test "x$ac_cv_header_sys_byteorder_h" = xyes -then : - printf "%s\n" "#define HAVE_SYS_BYTEORDER_H 1" >>confdefs.h - -fi -ac_fn_c_check_header_compile "$LINENO" "sys/bsdtty.h" "ac_cv_header_sys_bsdtty_h" "$ac_includes_default" -if test "x$ac_cv_header_sys_bsdtty_h" = xyes -then : - printf "%s\n" "#define HAVE_SYS_BSDTTY_H 1" >>confdefs.h - -fi -ac_fn_c_check_header_compile "$LINENO" "sys/cdefs.h" "ac_cv_header_sys_cdefs_h" "$ac_includes_default" -if test "x$ac_cv_header_sys_cdefs_h" = xyes -then : - printf "%s\n" "#define HAVE_SYS_CDEFS_H 1" >>confdefs.h - -fi -ac_fn_c_check_header_compile "$LINENO" "sys/dir.h" "ac_cv_header_sys_dir_h" "$ac_includes_default" -if test "x$ac_cv_header_sys_dir_h" = xyes -then : - printf "%s\n" "#define HAVE_SYS_DIR_H 1" >>confdefs.h - -fi -ac_fn_c_check_header_compile "$LINENO" "sys/file.h" "ac_cv_header_sys_file_h" "$ac_includes_default" -if test "x$ac_cv_header_sys_file_h" = xyes -then : - printf "%s\n" "#define HAVE_SYS_FILE_H 1" >>confdefs.h - -fi -ac_fn_c_check_header_compile "$LINENO" "sys/mman.h" "ac_cv_header_sys_mman_h" "$ac_includes_default" -if test "x$ac_cv_header_sys_mman_h" = xyes -then : - printf "%s\n" "#define HAVE_SYS_MMAN_H 1" >>confdefs.h - -fi -ac_fn_c_check_header_compile "$LINENO" "sys/label.h" "ac_cv_header_sys_label_h" "$ac_includes_default" -if test "x$ac_cv_header_sys_label_h" = xyes -then : - printf "%s\n" "#define HAVE_SYS_LABEL_H 1" >>confdefs.h - -fi -ac_fn_c_check_header_compile "$LINENO" "sys/ndir.h" "ac_cv_header_sys_ndir_h" "$ac_includes_default" -if test "x$ac_cv_header_sys_ndir_h" = xyes -then : - printf "%s\n" "#define HAVE_SYS_NDIR_H 1" >>confdefs.h - -fi -ac_fn_c_check_header_compile "$LINENO" "sys/param.h" "ac_cv_header_sys_param_h" "$ac_includes_default" -if test "x$ac_cv_header_sys_param_h" = xyes -then : - printf "%s\n" "#define HAVE_SYS_PARAM_H 1" >>confdefs.h - -fi -ac_fn_c_check_header_compile "$LINENO" "sys/poll.h" "ac_cv_header_sys_poll_h" "$ac_includes_default" -if test "x$ac_cv_header_sys_poll_h" = xyes -then : - printf "%s\n" "#define HAVE_SYS_POLL_H 1" >>confdefs.h - -fi -ac_fn_c_check_header_compile "$LINENO" "sys/prctl.h" "ac_cv_header_sys_prctl_h" "$ac_includes_default" -if test "x$ac_cv_header_sys_prctl_h" = xyes -then : - printf "%s\n" "#define HAVE_SYS_PRCTL_H 1" >>confdefs.h - -fi -ac_fn_c_check_header_compile "$LINENO" "sys/procctl.h" "ac_cv_header_sys_procctl_h" "$ac_includes_default" -if test "x$ac_cv_header_sys_procctl_h" = xyes -then : - printf "%s\n" "#define HAVE_SYS_PROCCTL_H 1" >>confdefs.h - -fi -ac_fn_c_check_header_compile "$LINENO" "sys/pstat.h" "ac_cv_header_sys_pstat_h" "$ac_includes_default" -if test "x$ac_cv_header_sys_pstat_h" = xyes -then : - printf "%s\n" "#define HAVE_SYS_PSTAT_H 1" >>confdefs.h - -fi -ac_fn_c_check_header_compile "$LINENO" "sys/ptrace.h" "ac_cv_header_sys_ptrace_h" "$ac_includes_default" -if test "x$ac_cv_header_sys_ptrace_h" = xyes -then : - printf "%s\n" "#define HAVE_SYS_PTRACE_H 1" >>confdefs.h - -fi -ac_fn_c_check_header_compile "$LINENO" "sys/random.h" "ac_cv_header_sys_random_h" "$ac_includes_default" -if test "x$ac_cv_header_sys_random_h" = xyes -then : - printf "%s\n" "#define HAVE_SYS_RANDOM_H 1" >>confdefs.h - -fi -ac_fn_c_check_header_compile "$LINENO" "sys/select.h" "ac_cv_header_sys_select_h" "$ac_includes_default" -if test "x$ac_cv_header_sys_select_h" = xyes -then : - printf "%s\n" "#define HAVE_SYS_SELECT_H 1" >>confdefs.h - -fi -ac_fn_c_check_header_compile "$LINENO" "sys/stream.h" "ac_cv_header_sys_stream_h" "$ac_includes_default" -if test "x$ac_cv_header_sys_stream_h" = xyes -then : - printf "%s\n" "#define HAVE_SYS_STREAM_H 1" >>confdefs.h +for ac_header in \ + blf.h \ + bstring.h \ + crypt.h \ + dirent.h \ + endian.h \ + elf.h \ + err.h \ + features.h \ + fcntl.h \ + floatingpoint.h \ + fnmatch.h \ + getopt.h \ + glob.h \ + ia.h \ + iaf.h \ + ifaddrs.h \ + langinfo.h \ + limits.h \ + locale.h \ + login.h \ + maillock.h \ + ndir.h \ + net/if_tun.h \ + netdb.h \ + netgroup.h \ + pam/pam_appl.h \ + paths.h \ + poll.h \ + pty.h \ + readpassphrase.h \ + rpc/types.h \ + security/pam_appl.h \ + sha2.h \ + shadow.h \ + stddef.h \ + sys/bitypes.h \ + sys/byteorder.h \ + sys/bsdtty.h \ + sys/cdefs.h \ + sys/dir.h \ + sys/file.h \ + sys/mman.h \ + sys/label.h \ + sys/ndir.h \ + sys/poll.h \ + sys/prctl.h \ + sys/procctl.h \ + sys/pstat.h \ + sys/ptrace.h \ + sys/random.h \ + sys/select.h \ + sys/stream.h \ + sys/stropts.h \ + sys/strtio.h \ + sys/statfs.h \ + sys/statvfs.h \ + sys/sysmacros.h \ + sys/time.h \ + sys/timers.h \ + sys/vfs.h \ + time.h \ + tmpdir.h \ + ttyent.h \ + ucred.h \ + usersec.h \ + util.h \ + utime.h \ + utmp.h \ + utmpx.h \ + vis.h \ + wchar.h \ -fi -ac_fn_c_check_header_compile "$LINENO" "sys/stropts.h" "ac_cv_header_sys_stropts_h" "$ac_includes_default" -if test "x$ac_cv_header_sys_stropts_h" = xyes -then : - printf "%s\n" "#define HAVE_SYS_STROPTS_H 1" >>confdefs.h - -fi -ac_fn_c_check_header_compile "$LINENO" "sys/strtio.h" "ac_cv_header_sys_strtio_h" "$ac_includes_default" -if test "x$ac_cv_header_sys_strtio_h" = xyes -then : - printf "%s\n" "#define HAVE_SYS_STRTIO_H 1" >>confdefs.h - -fi -ac_fn_c_check_header_compile "$LINENO" "sys/statvfs.h" "ac_cv_header_sys_statvfs_h" "$ac_includes_default" -if test "x$ac_cv_header_sys_statvfs_h" = xyes -then : - printf "%s\n" "#define HAVE_SYS_STATVFS_H 1" >>confdefs.h - -fi -ac_fn_c_check_header_compile "$LINENO" "sys/sysmacros.h" "ac_cv_header_sys_sysmacros_h" "$ac_includes_default" -if test "x$ac_cv_header_sys_sysmacros_h" = xyes -then : - printf "%s\n" "#define HAVE_SYS_SYSMACROS_H 1" >>confdefs.h - -fi -ac_fn_c_check_header_compile "$LINENO" "sys/time.h" "ac_cv_header_sys_time_h" "$ac_includes_default" -if test "x$ac_cv_header_sys_time_h" = xyes -then : - printf "%s\n" "#define HAVE_SYS_TIME_H 1" >>confdefs.h - -fi -ac_fn_c_check_header_compile "$LINENO" "sys/timers.h" "ac_cv_header_sys_timers_h" "$ac_includes_default" -if test "x$ac_cv_header_sys_timers_h" = xyes -then : - printf "%s\n" "#define HAVE_SYS_TIMERS_H 1" >>confdefs.h - -fi -ac_fn_c_check_header_compile "$LINENO" "sys/vfs.h" "ac_cv_header_sys_vfs_h" "$ac_includes_default" -if test "x$ac_cv_header_sys_vfs_h" = xyes -then : - printf "%s\n" "#define HAVE_SYS_VFS_H 1" >>confdefs.h - -fi -ac_fn_c_check_header_compile "$LINENO" "time.h" "ac_cv_header_time_h" "$ac_includes_default" -if test "x$ac_cv_header_time_h" = xyes -then : - printf "%s\n" "#define HAVE_TIME_H 1" >>confdefs.h - -fi -ac_fn_c_check_header_compile "$LINENO" "tmpdir.h" "ac_cv_header_tmpdir_h" "$ac_includes_default" -if test "x$ac_cv_header_tmpdir_h" = xyes -then : - printf "%s\n" "#define HAVE_TMPDIR_H 1" >>confdefs.h - -fi -ac_fn_c_check_header_compile "$LINENO" "ttyent.h" "ac_cv_header_ttyent_h" "$ac_includes_default" -if test "x$ac_cv_header_ttyent_h" = xyes -then : - printf "%s\n" "#define HAVE_TTYENT_H 1" >>confdefs.h - -fi -ac_fn_c_check_header_compile "$LINENO" "ucred.h" "ac_cv_header_ucred_h" "$ac_includes_default" -if test "x$ac_cv_header_ucred_h" = xyes -then : - printf "%s\n" "#define HAVE_UCRED_H 1" >>confdefs.h - -fi -ac_fn_c_check_header_compile "$LINENO" "unistd.h" "ac_cv_header_unistd_h" "$ac_includes_default" -if test "x$ac_cv_header_unistd_h" = xyes -then : - printf "%s\n" "#define HAVE_UNISTD_H 1" >>confdefs.h - -fi -ac_fn_c_check_header_compile "$LINENO" "usersec.h" "ac_cv_header_usersec_h" "$ac_includes_default" -if test "x$ac_cv_header_usersec_h" = xyes -then : - printf "%s\n" "#define HAVE_USERSEC_H 1" >>confdefs.h - -fi -ac_fn_c_check_header_compile "$LINENO" "util.h" "ac_cv_header_util_h" "$ac_includes_default" -if test "x$ac_cv_header_util_h" = xyes -then : - printf "%s\n" "#define HAVE_UTIL_H 1" >>confdefs.h - -fi -ac_fn_c_check_header_compile "$LINENO" "utime.h" "ac_cv_header_utime_h" "$ac_includes_default" -if test "x$ac_cv_header_utime_h" = xyes -then : - printf "%s\n" "#define HAVE_UTIME_H 1" >>confdefs.h - -fi -ac_fn_c_check_header_compile "$LINENO" "utmp.h" "ac_cv_header_utmp_h" "$ac_includes_default" -if test "x$ac_cv_header_utmp_h" = xyes -then : - printf "%s\n" "#define HAVE_UTMP_H 1" >>confdefs.h - -fi -ac_fn_c_check_header_compile "$LINENO" "utmpx.h" "ac_cv_header_utmpx_h" "$ac_includes_default" -if test "x$ac_cv_header_utmpx_h" = xyes -then : - printf "%s\n" "#define HAVE_UTMPX_H 1" >>confdefs.h - -fi -ac_fn_c_check_header_compile "$LINENO" "vis.h" "ac_cv_header_vis_h" "$ac_includes_default" -if test "x$ac_cv_header_vis_h" = xyes -then : - printf "%s\n" "#define HAVE_VIS_H 1" >>confdefs.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF fi -ac_fn_c_check_header_compile "$LINENO" "wchar.h" "ac_cv_header_wchar_h" "$ac_includes_default" -if test "x$ac_cv_header_wchar_h" = xyes -then : - printf "%s\n" "#define HAVE_WCHAR_H 1" >>confdefs.h -fi +done # On some platforms (eg SunOS4) sys/audit.h requires sys/[time|types|label.h] # to be included first. -ac_fn_c_check_header_compile "$LINENO" "sys/audit.h" "ac_cv_header_sys_audit_h" " +for ac_header in sys/audit.h +do : + ac_fn_c_check_header_compile "$LINENO" "sys/audit.h" "ac_cv_header_sys_audit_h" " #ifdef HAVE_SYS_TIME_H # include #endif @@ -8521,71 +7393,71 @@ #endif " -if test "x$ac_cv_header_sys_audit_h" = xyes -then : - printf "%s\n" "#define HAVE_SYS_AUDIT_H 1" >>confdefs.h +if test "x$ac_cv_header_sys_audit_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_SYS_AUDIT_H 1 +_ACEOF fi +done + # sys/capsicum.h requires sys/types.h -ac_fn_c_check_header_compile "$LINENO" "sys/capsicum.h" "ac_cv_header_sys_capsicum_h" " +for ac_header in sys/capsicum.h capsicum_helpers.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" " #ifdef HAVE_SYS_TYPES_H # include #endif " -if test "x$ac_cv_header_sys_capsicum_h" = xyes -then : - printf "%s\n" "#define HAVE_SYS_CAPSICUM_H 1" >>confdefs.h +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF fi -ac_fn_c_check_header_compile "$LINENO" "capsicum_helpers.h" "ac_cv_header_capsicum_helpers_h" " -#ifdef HAVE_SYS_TYPES_H -# include -#endif -" -if test "x$ac_cv_header_capsicum_helpers_h" = xyes -then : - printf "%s\n" "#define HAVE_CAPSICUM_HELPERS_H 1" >>confdefs.h - -fi +done -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for caph_cache_tzdata" >&5 -printf %s "checking for caph_cache_tzdata... " >&6; } +# caph_cache_tzdata() is defined as inline in capsicum_helpers.h +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for caph_cache_tzdata" >&5 +$as_echo_n "checking for caph_cache_tzdata... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int -main (void) +main () { caph_cache_tzdata(); ; return 0; } _ACEOF -if ac_fn_c_try_link "$LINENO" -then : +if ac_fn_c_try_link "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } +$as_echo "#define HAVE_CAPH_CACHE_TZDATA 1" >>confdefs.h -printf "%s\n" "#define HAVE_CAPH_CACHE_TZDATA 1" >>confdefs.h - -else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } fi -rm -f core conftest.err conftest.$ac_objext conftest.beam \ +rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext # net/route.h requires sys/socket.h and sys/types.h. # sys/sysctl.h also requires sys/param.h -ac_fn_c_check_header_compile "$LINENO" "net/route.h" "ac_cv_header_net_route_h" " +for ac_header in net/route.h sys/sysctl.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" " #ifdef HAVE_SYS_TYPES_H # include #endif @@ -8593,90 +7465,123 @@ #include " -if test "x$ac_cv_header_net_route_h" = xyes -then : - printf "%s\n" "#define HAVE_NET_ROUTE_H 1" >>confdefs.h +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF fi -ac_fn_c_check_header_compile "$LINENO" "sys/sysctl.h" "ac_cv_header_sys_sysctl_h" " -#ifdef HAVE_SYS_TYPES_H -# include -#endif -#include -#include - -" -if test "x$ac_cv_header_sys_sysctl_h" = xyes -then : - printf "%s\n" "#define HAVE_SYS_SYSCTL_H 1" >>confdefs.h -fi +done # lastlog.h requires sys/time.h to be included first on Solaris -ac_fn_c_check_header_compile "$LINENO" "lastlog.h" "ac_cv_header_lastlog_h" " +for ac_header in lastlog.h +do : + ac_fn_c_check_header_compile "$LINENO" "lastlog.h" "ac_cv_header_lastlog_h" " #ifdef HAVE_SYS_TIME_H # include #endif " -if test "x$ac_cv_header_lastlog_h" = xyes -then : - printf "%s\n" "#define HAVE_LASTLOG_H 1" >>confdefs.h +if test "x$ac_cv_header_lastlog_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LASTLOG_H 1 +_ACEOF fi +done + # sys/ptms.h requires sys/stream.h to be included first on Solaris -ac_fn_c_check_header_compile "$LINENO" "sys/ptms.h" "ac_cv_header_sys_ptms_h" " +for ac_header in sys/ptms.h +do : + ac_fn_c_check_header_compile "$LINENO" "sys/ptms.h" "ac_cv_header_sys_ptms_h" " #ifdef HAVE_SYS_STREAM_H # include #endif " -if test "x$ac_cv_header_sys_ptms_h" = xyes -then : - printf "%s\n" "#define HAVE_SYS_PTMS_H 1" >>confdefs.h +if test "x$ac_cv_header_sys_ptms_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_SYS_PTMS_H 1 +_ACEOF fi +done + # login_cap.h requires sys/types.h on NetBSD -ac_fn_c_check_header_compile "$LINENO" "login_cap.h" "ac_cv_header_login_cap_h" " +for ac_header in login_cap.h +do : + ac_fn_c_check_header_compile "$LINENO" "login_cap.h" "ac_cv_header_login_cap_h" " #include " -if test "x$ac_cv_header_login_cap_h" = xyes -then : - printf "%s\n" "#define HAVE_LOGIN_CAP_H 1" >>confdefs.h +if test "x$ac_cv_header_login_cap_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LOGIN_CAP_H 1 +_ACEOF fi +done + # older BSDs need sys/param.h before sys/mount.h -ac_fn_c_check_header_compile "$LINENO" "sys/mount.h" "ac_cv_header_sys_mount_h" " +for ac_header in sys/mount.h +do : + ac_fn_c_check_header_compile "$LINENO" "sys/mount.h" "ac_cv_header_sys_mount_h" " #include " -if test "x$ac_cv_header_sys_mount_h" = xyes -then : - printf "%s\n" "#define HAVE_SYS_MOUNT_H 1" >>confdefs.h +if test "x$ac_cv_header_sys_mount_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_SYS_MOUNT_H 1 +_ACEOF fi +done + # Android requires sys/socket.h to be included before sys/un.h -ac_fn_c_check_header_compile "$LINENO" "sys/un.h" "ac_cv_header_sys_un_h" " +for ac_header in sys/un.h +do : + ac_fn_c_check_header_compile "$LINENO" "sys/un.h" "ac_cv_header_sys_un_h" " #include #include " -if test "x$ac_cv_header_sys_un_h" = xyes -then : - printf "%s\n" "#define HAVE_SYS_UN_H 1" >>confdefs.h +if test "x$ac_cv_header_sys_un_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_SYS_UN_H 1 +_ACEOF fi +done + + + +# templates for target-specific defines + + + + +# For instance inet_ntoa(3) Irix gcc issue: + + + + + + +# For instance unexpected glob(3) functionality on FreeBSD and OS X + + + # Messages for features tested for in target-specific section SIA_MSG="no" @@ -8689,6 +7594,9 @@ SOLARIS_PRIVS="no" # Check for some target-specific stuff + + +ssh_disable_utmpx=no case "$host" in *-*-aix*) # Some versions of VAC won't allow macro redefinitions at @@ -8696,38 +7604,39 @@ # particularly with older versions of vac or xlc. # It also throws errors about null macro arguments, but these are # not fatal. - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if compiler allows macro redefinitions" >&5 -printf %s "checking if compiler allows macro redefinitions... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if compiler allows macro redefinitions" >&5 +$as_echo_n "checking if compiler allows macro redefinitions... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #define testmacro foo #define testmacro bar + int -main (void) +main () { - exit(0); + + ; return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO" -then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } -else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } +if ac_fn_c_try_compile "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } CC="`echo $CC | sed 's/-qlanglvl\=ansi//g'`" CFLAGS="`echo $CFLAGS | sed 's/-qlanglvl\=ansi//g'`" CPPFLAGS="`echo $CPPFLAGS | sed 's/-qlanglvl\=ansi//g'`" fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking how to specify blibpath for linker ($LD)" >&5 -printf %s "checking how to specify blibpath for linker ($LD)... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to specify blibpath for linker ($LD)" >&5 +$as_echo_n "checking how to specify blibpath for linker ($LD)... " >&6; } if (test -z "$blibpath"); then blibpath="/usr/lib:/lib" fi @@ -8744,43 +7653,40 @@ /* end confdefs.h. */ int -main (void) +main () { ; return 0; } _ACEOF -if ac_fn_c_try_link "$LINENO" -then : +if ac_fn_c_try_link "$LINENO"; then : blibflags=$tryflags fi -rm -f core conftest.err conftest.$ac_objext conftest.beam \ +rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi done if (test -z "$blibflags"); then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: not found" >&5 -printf "%s\n" "not found" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5 +$as_echo "not found" >&6; } as_fn_error $? "*** must be able to specify blibpath on AIX - check config.log" "$LINENO" 5 else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $blibflags" >&5 -printf "%s\n" "$blibflags" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $blibflags" >&5 +$as_echo "$blibflags" >&6; } fi LDFLAGS="$saved_LDFLAGS" ac_fn_c_check_func "$LINENO" "authenticate" "ac_cv_func_authenticate" -if test "x$ac_cv_func_authenticate" = xyes -then : +if test "x$ac_cv_func_authenticate" = xyes; then : -printf "%s\n" "#define WITH_AIXAUTHENTICATE 1" >>confdefs.h +$as_echo "#define WITH_AIXAUTHENTICATE 1" >>confdefs.h -else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for authenticate in -ls" >&5 -printf %s "checking for authenticate in -ls... " >&6; } -if test ${ac_cv_lib_s_authenticate+y} -then : - printf %s "(cached) " >&6 -else $as_nop +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for authenticate in -ls" >&5 +$as_echo_n "checking for authenticate in -ls... " >&6; } +if ${ac_cv_lib_s_authenticate+:} false; then : + $as_echo_n "(cached) " >&6 +else ac_check_lib_save_LIBS=$LIBS LIBS="-ls $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -8789,30 +7695,31 @@ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif char authenticate (); int -main (void) +main () { return authenticate (); ; return 0; } _ACEOF -if ac_fn_c_try_link "$LINENO" -then : +if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_s_authenticate=yes -else $as_nop +else ac_cv_lib_s_authenticate=no fi -rm -f core conftest.err conftest.$ac_objext conftest.beam \ +rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_s_authenticate" >&5 -printf "%s\n" "$ac_cv_lib_s_authenticate" >&6; } -if test "x$ac_cv_lib_s_authenticate" = xyes -then : - printf "%s\n" "#define WITH_AIXAUTHENTICATE 1" >>confdefs.h +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_s_authenticate" >&5 +$as_echo "$ac_cv_lib_s_authenticate" >&6; } +if test "x$ac_cv_lib_s_authenticate" = xyes; then : + $as_echo "#define WITH_AIXAUTHENTICATE 1" >>confdefs.h LIBS="$LIBS -ls" @@ -8821,189 +7728,184 @@ fi - ac_fn_check_decl "$LINENO" "authenticate" "ac_cv_have_decl_authenticate" "#include -" "$ac_c_undeclared_builtin_options" "CFLAGS" -if test "x$ac_cv_have_decl_authenticate" = xyes -then : + ac_fn_c_check_decl "$LINENO" "authenticate" "ac_cv_have_decl_authenticate" "#include +" +if test "x$ac_cv_have_decl_authenticate" = xyes; then : ac_have_decl=1 -else $as_nop +else ac_have_decl=0 fi -printf "%s\n" "#define HAVE_DECL_AUTHENTICATE $ac_have_decl" >>confdefs.h -ac_fn_check_decl "$LINENO" "loginrestrictions" "ac_cv_have_decl_loginrestrictions" "#include -" "$ac_c_undeclared_builtin_options" "CFLAGS" -if test "x$ac_cv_have_decl_loginrestrictions" = xyes -then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_AUTHENTICATE $ac_have_decl +_ACEOF +ac_fn_c_check_decl "$LINENO" "loginrestrictions" "ac_cv_have_decl_loginrestrictions" "#include +" +if test "x$ac_cv_have_decl_loginrestrictions" = xyes; then : ac_have_decl=1 -else $as_nop +else ac_have_decl=0 fi -printf "%s\n" "#define HAVE_DECL_LOGINRESTRICTIONS $ac_have_decl" >>confdefs.h -ac_fn_check_decl "$LINENO" "loginsuccess" "ac_cv_have_decl_loginsuccess" "#include -" "$ac_c_undeclared_builtin_options" "CFLAGS" -if test "x$ac_cv_have_decl_loginsuccess" = xyes -then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_LOGINRESTRICTIONS $ac_have_decl +_ACEOF +ac_fn_c_check_decl "$LINENO" "loginsuccess" "ac_cv_have_decl_loginsuccess" "#include +" +if test "x$ac_cv_have_decl_loginsuccess" = xyes; then : ac_have_decl=1 -else $as_nop +else ac_have_decl=0 fi -printf "%s\n" "#define HAVE_DECL_LOGINSUCCESS $ac_have_decl" >>confdefs.h -ac_fn_check_decl "$LINENO" "passwdexpired" "ac_cv_have_decl_passwdexpired" "#include -" "$ac_c_undeclared_builtin_options" "CFLAGS" -if test "x$ac_cv_have_decl_passwdexpired" = xyes -then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_LOGINSUCCESS $ac_have_decl +_ACEOF +ac_fn_c_check_decl "$LINENO" "passwdexpired" "ac_cv_have_decl_passwdexpired" "#include +" +if test "x$ac_cv_have_decl_passwdexpired" = xyes; then : ac_have_decl=1 -else $as_nop +else ac_have_decl=0 fi -printf "%s\n" "#define HAVE_DECL_PASSWDEXPIRED $ac_have_decl" >>confdefs.h -ac_fn_check_decl "$LINENO" "setauthdb" "ac_cv_have_decl_setauthdb" "#include -" "$ac_c_undeclared_builtin_options" "CFLAGS" -if test "x$ac_cv_have_decl_setauthdb" = xyes -then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_PASSWDEXPIRED $ac_have_decl +_ACEOF +ac_fn_c_check_decl "$LINENO" "setauthdb" "ac_cv_have_decl_setauthdb" "#include +" +if test "x$ac_cv_have_decl_setauthdb" = xyes; then : ac_have_decl=1 -else $as_nop +else ac_have_decl=0 fi -printf "%s\n" "#define HAVE_DECL_SETAUTHDB $ac_have_decl" >>confdefs.h - ac_fn_check_decl "$LINENO" "loginfailed" "ac_cv_have_decl_loginfailed" "#include +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_SETAUTHDB $ac_have_decl +_ACEOF + + ac_fn_c_check_decl "$LINENO" "loginfailed" "ac_cv_have_decl_loginfailed" "#include -" "$ac_c_undeclared_builtin_options" "CFLAGS" -if test "x$ac_cv_have_decl_loginfailed" = xyes -then : +" +if test "x$ac_cv_have_decl_loginfailed" = xyes; then : ac_have_decl=1 -else $as_nop +else ac_have_decl=0 fi -printf "%s\n" "#define HAVE_DECL_LOGINFAILED $ac_have_decl" >>confdefs.h -if test $ac_have_decl = 1 -then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if loginfailed takes 4 arguments" >&5 -printf %s "checking if loginfailed takes 4 arguments... " >&6; } + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_LOGINFAILED $ac_have_decl +_ACEOF +if test $ac_have_decl = 1; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if loginfailed takes 4 arguments" >&5 +$as_echo_n "checking if loginfailed takes 4 arguments... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int -main (void) +main () { (void)loginfailed("user","host","tty",0); ; return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO" -then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } +if ac_fn_c_try_compile "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } -printf "%s\n" "#define AIX_LOGINFAILED_4ARG 1" >>confdefs.h +$as_echo "#define AIX_LOGINFAILED_4ARG 1" >>confdefs.h -else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi - ac_fn_c_check_func "$LINENO" "getgrset" "ac_cv_func_getgrset" -if test "x$ac_cv_func_getgrset" = xyes -then : - printf "%s\n" "#define HAVE_GETGRSET 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "setauthdb" "ac_cv_func_setauthdb" -if test "x$ac_cv_func_setauthdb" = xyes -then : - printf "%s\n" "#define HAVE_SETAUTHDB 1" >>confdefs.h + for ac_func in getgrset setauthdb +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF fi +done - ac_fn_check_decl "$LINENO" "F_CLOSEM" "ac_cv_have_decl_F_CLOSEM" " #include + ac_fn_c_check_decl "$LINENO" "F_CLOSEM" "ac_cv_have_decl_F_CLOSEM" " #include #include -" "$ac_c_undeclared_builtin_options" "CFLAGS" -if test "x$ac_cv_have_decl_F_CLOSEM" = xyes -then : +" +if test "x$ac_cv_have_decl_F_CLOSEM" = xyes; then : -printf "%s\n" "#define HAVE_FCNTL_CLOSEM 1" >>confdefs.h +$as_echo "#define HAVE_FCNTL_CLOSEM 1" >>confdefs.h fi - check_for_aix_broken_getaddrinfo=1 - -printf "%s\n" "#define SETEUID_BREAKS_SETUID 1" >>confdefs.h - - -printf "%s\n" "#define BROKEN_SETREUID 1" >>confdefs.h - - -printf "%s\n" "#define BROKEN_SETREGID 1" >>confdefs.h + check_for_aix_broken_getaddrinfo=1 -printf "%s\n" "#define DISABLE_LASTLOG 1" >>confdefs.h +$as_echo "#define SETEUID_BREAKS_SETUID 1" >>confdefs.h + $as_echo "#define BROKEN_SETREUID 1" >>confdefs.h -printf "%s\n" "#define LOGIN_NEEDS_UTMPX 1" >>confdefs.h + $as_echo "#define BROKEN_SETREGID 1" >>confdefs.h -printf "%s\n" "#define SPT_TYPE SPT_REUSEARGV" >>confdefs.h +$as_echo "#define DISABLE_LASTLOG 1" >>confdefs.h -printf "%s\n" "#define SSHPAM_CHAUTHTOK_NEEDS_RUID 1" >>confdefs.h +$as_echo "#define LOGIN_NEEDS_UTMPX 1" >>confdefs.h -printf "%s\n" "#define PTY_ZEROREAD 1" >>confdefs.h +$as_echo "#define SPT_TYPE SPT_REUSEARGV" >>confdefs.h -printf "%s\n" "#define PLATFORM_SYS_DIR_UID 2" >>confdefs.h +$as_echo "#define SSHPAM_CHAUTHTOK_NEEDS_RUID 1" >>confdefs.h -printf "%s\n" "#define BROKEN_STRNDUP 1" >>confdefs.h +$as_echo "#define PTY_ZEROREAD 1" >>confdefs.h -printf "%s\n" "#define BROKEN_STRNLEN 1" >>confdefs.h +$as_echo "#define PLATFORM_SYS_DIR_UID 2" >>confdefs.h - ;; -*-*-android*) -printf "%s\n" "#define DISABLE_UTMP 1" >>confdefs.h +$as_echo "#define BROKEN_STRNDUP 1" >>confdefs.h -printf "%s\n" "#define DISABLE_WTMP 1" >>confdefs.h +$as_echo "#define BROKEN_STRNLEN 1" >>confdefs.h ;; *-*-cygwin*) LIBS="$LIBS /usr/lib/textreadmode.o" -printf "%s\n" "#define HAVE_CYGWIN 1" >>confdefs.h - - -printf "%s\n" "#define USE_PIPES 1" >>confdefs.h +$as_echo "#define HAVE_CYGWIN 1" >>confdefs.h -printf "%s\n" "#define NO_UID_RESTORATION_TEST 1" >>confdefs.h +$as_echo "#define USE_PIPES 1" >>confdefs.h -printf "%s\n" "#define DISABLE_SHADOW 1" >>confdefs.h +$as_echo "#define NO_UID_RESTORATION_TEST 1" >>confdefs.h -printf "%s\n" "#define NO_X11_UNIX_SOCKETS 1" >>confdefs.h +$as_echo "#define DISABLE_SHADOW 1" >>confdefs.h -printf "%s\n" "#define DISABLE_FD_PASSING 1" >>confdefs.h +$as_echo "#define NO_X11_UNIX_SOCKETS 1" >>confdefs.h + $as_echo "#define DISABLE_FD_PASSING 1" >>confdefs.h -printf "%s\n" "#define SSH_IOBUFSZ 65535" >>confdefs.h - -printf "%s\n" "#define FILESYSTEM_NO_BACKSLASH 1" >>confdefs.h +$as_echo "#define FILESYSTEM_NO_BACKSLASH 1" >>confdefs.h # Cygwin defines optargs, optargs as declspec(dllimport) for historical # reasons which cause compile warnings, so we disable those warnings. { - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -Wno-attributes" >&5 -printf %s "checking if $CC supports compile flag -Wno-attributes... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -Wno-attributes" >&5 +$as_echo_n "checking if $CC supports compile flag -Wno-attributes... " >&6; } saved_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $WERROR -Wno-attributes" _define_flag="" @@ -9011,96 +7913,89 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ + #include #include -/* Trivial function to help test for -fzero-call-used-regs */ -void f(int n) {} -int main(int argc, char **argv) { - (void)argv; +/* Trivial function to help test for flags like -fzero-call-used-regs. +Note compiler does not inform whether this option is supported unless it +runs into the situation where it would need to emit corresponding code.*/ +static int f(int n) {return n;} +int main(int argc, char *argv[]) { /* Some math to catch -ftrapv problems in the toolchain */ int i = 123 * argc, j = 456 + argc, k = 789 - argc; float l = i * 2.1; double m = l / 0.5; long long int n = argc * 12345LL, o = 12345LL * (long long int)argc; - f(0); - printf("%d %d %d %f %f %lld %lld\n", i, j, k, l, m, n, o); - /* - * Test fallthrough behaviour. clang 10's -Wimplicit-fallthrough does - * not understand comments and we don't use the "fallthrough" attribute - * that it's looking for. - */ - switch(i){ - case 0: j += i; - /* FALLTHROUGH */ - default: j += k; - } - exit(0); + long long int p = n * o; + printf("%d %d %d %f %f %lld %lld %lld %d\n", i, j, k, l, m, n, o, p, f(0)); + (void)argv; + return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO" -then : +if ac_fn_c_try_compile "$LINENO"; then : -if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null +if $EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } CFLAGS="$saved_CFLAGS" else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } CFLAGS="$saved_CFLAGS $_define_flag" fi -else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } CFLAGS="$saved_CFLAGS" fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext } ;; *-*-dgux*) -printf "%s\n" "#define IP_TOS_IS_BROKEN 1" >>confdefs.h +$as_echo "#define IP_TOS_IS_BROKEN 1" >>confdefs.h - printf "%s\n" "#define SETEUID_BREAKS_SETUID 1" >>confdefs.h + $as_echo "#define SETEUID_BREAKS_SETUID 1" >>confdefs.h - printf "%s\n" "#define BROKEN_SETREUID 1" >>confdefs.h + $as_echo "#define BROKEN_SETREUID 1" >>confdefs.h - printf "%s\n" "#define BROKEN_SETREGID 1" >>confdefs.h + $as_echo "#define BROKEN_SETREGID 1" >>confdefs.h ;; *-*-darwin*) use_pie=auto - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if we have working getaddrinfo" >&5 -printf %s "checking if we have working getaddrinfo... " >&6; } - if test "$cross_compiling" = yes -then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: assume it is working" >&5 -printf "%s\n" "assume it is working" >&6; } -else $as_nop + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we have working getaddrinfo" >&5 +$as_echo_n "checking if we have working getaddrinfo... " >&6; } + if test "$cross_compiling" = yes; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: assume it is working" >&5 +$as_echo "assume it is working" >&6; } +else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include -#include -int main(void) { if (NSVersionOfRunTimeLibrary("System") >= (60 << 16)) - exit(0); - else - exit(1); -} -_ACEOF -if ac_fn_c_try_run "$LINENO" -then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: working" >&5 -printf "%s\n" "working" >&6; } -else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: buggy" >&5 -printf "%s\n" "buggy" >&6; } +int +main () +{ -printf "%s\n" "#define BROKEN_GETADDRINFO 1" >>confdefs.h + if (NSVersionOfRunTimeLibrary("System") < (60 << 16)) + return 1; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: working" >&5 +$as_echo "working" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: buggy" >&5 +$as_echo "buggy" >&6; } + $as_echo "#define BROKEN_GETADDRINFO 1" >>confdefs.h fi @@ -9108,65 +8003,92 @@ conftest.$ac_objext conftest.beam conftest.$ac_ext fi - printf "%s\n" "#define SETEUID_BREAKS_SETUID 1" >>confdefs.h + $as_echo "#define SETEUID_BREAKS_SETUID 1" >>confdefs.h - printf "%s\n" "#define BROKEN_SETREUID 1" >>confdefs.h + $as_echo "#define BROKEN_SETREUID 1" >>confdefs.h - printf "%s\n" "#define BROKEN_SETREGID 1" >>confdefs.h + $as_echo "#define BROKEN_SETREGID 1" >>confdefs.h + $as_echo "#define BROKEN_GLOB 1" >>confdefs.h + + +cat >>confdefs.h <<_ACEOF +#define BIND_8_COMPAT 1 +_ACEOF + + for ac_header in net/if_utun.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "net/if_utun.h" "ac_cv_header_net_if_utun_h" "$ac_includes_default" +if test "x$ac_cv_header_net_if_utun_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_NET_IF_UTUN_H 1 +_ACEOF + +fi -printf "%s\n" "#define BROKEN_GLOB 1" >>confdefs.h +done + if test "x$ac_cv_header_net_if_utun_h" = "xyes" ; then -printf "%s\n" "#define BIND_8_COMPAT 1" >>confdefs.h +$as_echo "#define SSH_TUN_DARWIN 1" >>confdefs.h + else -printf "%s\n" "#define SSH_TUN_FREEBSD 1" >>confdefs.h +$as_echo "#define SSH_TUN_FREEBSD 1" >>confdefs.h -printf "%s\n" "#define SSH_TUN_COMPAT_AF 1" >>confdefs.h +$as_echo "#define SSH_TUN_PREPEND_AF 1" >>confdefs.h -printf "%s\n" "#define SSH_TUN_PREPEND_AF 1" >>confdefs.h +$as_echo "#define SSH_TUN_COMPAT_AF 1" >>confdefs.h + fi - ac_fn_check_decl "$LINENO" "AU_IPv4" "ac_cv_have_decl_AU_IPv4" "$ac_includes_default" "$ac_c_undeclared_builtin_options" "CFLAGS" -if test "x$ac_cv_have_decl_AU_IPv4" = xyes -then : + ac_fn_c_check_decl "$LINENO" "AU_IPv4" "ac_cv_have_decl_AU_IPv4" "$ac_includes_default" +if test "x$ac_cv_have_decl_AU_IPv4" = xyes; then : -else $as_nop +else -printf "%s\n" "#define AU_IPv4 0" >>confdefs.h +$as_echo "#define AU_IPv4 0" >>confdefs.h #include -printf "%s\n" "#define LASTLOG_WRITE_PUTUTXLINE 1" >>confdefs.h +$as_echo "#define LASTLOG_WRITE_PUTUTXLINE 1" >>confdefs.h fi -printf "%s\n" "#define SPT_TYPE SPT_REUSEARGV" >>confdefs.h - ac_fn_c_check_func "$LINENO" "sandbox_init" "ac_cv_func_sandbox_init" -if test "x$ac_cv_func_sandbox_init" = xyes -then : - printf "%s\n" "#define HAVE_SANDBOX_INIT 1" >>confdefs.h +$as_echo "#define SPT_TYPE SPT_REUSEARGV" >>confdefs.h + + for ac_func in sandbox_init +do : + ac_fn_c_check_func "$LINENO" "sandbox_init" "ac_cv_func_sandbox_init" +if test "x$ac_cv_func_sandbox_init" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_SANDBOX_INIT 1 +_ACEOF fi +done - ac_fn_c_check_header_compile "$LINENO" "sandbox.h" "ac_cv_header_sandbox_h" "$ac_includes_default" -if test "x$ac_cv_header_sandbox_h" = xyes -then : - printf "%s\n" "#define HAVE_SANDBOX_H 1" >>confdefs.h + for ac_header in sandbox.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "sandbox.h" "ac_cv_header_sandbox_h" "$ac_includes_default" +if test "x$ac_cv_header_sandbox_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_SANDBOX_H 1 +_ACEOF fi - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for sandbox_apply in -lsandbox" >&5 -printf %s "checking for sandbox_apply in -lsandbox... " >&6; } -if test ${ac_cv_lib_sandbox_sandbox_apply+y} -then : - printf %s "(cached) " >&6 -else $as_nop +done + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for sandbox_apply in -lsandbox" >&5 +$as_echo_n "checking for sandbox_apply in -lsandbox... " >&6; } +if ${ac_cv_lib_sandbox_sandbox_apply+:} false; then : + $as_echo_n "(cached) " >&6 +else ac_check_lib_save_LIBS=$LIBS LIBS="-lsandbox $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -9175,68 +8097,75 @@ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif char sandbox_apply (); int -main (void) +main () { return sandbox_apply (); ; return 0; } _ACEOF -if ac_fn_c_try_link "$LINENO" -then : +if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_sandbox_sandbox_apply=yes -else $as_nop +else ac_cv_lib_sandbox_sandbox_apply=no fi -rm -f core conftest.err conftest.$ac_objext conftest.beam \ +rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_sandbox_sandbox_apply" >&5 -printf "%s\n" "$ac_cv_lib_sandbox_sandbox_apply" >&6; } -if test "x$ac_cv_lib_sandbox_sandbox_apply" = xyes -then : +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_sandbox_sandbox_apply" >&5 +$as_echo "$ac_cv_lib_sandbox_sandbox_apply" >&6; } +if test "x$ac_cv_lib_sandbox_sandbox_apply" = xyes; then : SSHDLIBS="$SSHDLIBS -lsandbox" fi # proc_pidinfo()-based closefrom() replacement. - ac_fn_c_check_header_compile "$LINENO" "libproc.h" "ac_cv_header_libproc_h" "$ac_includes_default" -if test "x$ac_cv_header_libproc_h" = xyes -then : - printf "%s\n" "#define HAVE_LIBPROC_H 1" >>confdefs.h + for ac_header in libproc.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "libproc.h" "ac_cv_header_libproc_h" "$ac_includes_default" +if test "x$ac_cv_header_libproc_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBPROC_H 1 +_ACEOF fi - ac_fn_c_check_func "$LINENO" "proc_pidinfo" "ac_cv_func_proc_pidinfo" -if test "x$ac_cv_func_proc_pidinfo" = xyes -then : - printf "%s\n" "#define HAVE_PROC_PIDINFO 1" >>confdefs.h +done + + for ac_func in proc_pidinfo +do : + ac_fn_c_check_func "$LINENO" "proc_pidinfo" "ac_cv_func_proc_pidinfo" +if test "x$ac_cv_func_proc_pidinfo" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_PROC_PIDINFO 1 +_ACEOF fi +done # poll(2) is broken for character-special devices (at least). # cf. Apple bug 3710161 (not public, but searchable) - -printf "%s\n" "#define BROKEN_POLL 1" >>confdefs.h + $as_echo "#define BROKEN_POLL 1" >>confdefs.h ;; *-*-dragonfly*) - SSHDLIBS="$SSHDLIBS" TEST_MALLOC_OPTIONS="AFGJPRX" ;; *-*-haiku*) LIBS="$LIBS -lbsd " CFLAGS="$CFLAGS -D_BSD_SOURCE" - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for socket in -lnetwork" >&5 -printf %s "checking for socket in -lnetwork... " >&6; } -if test ${ac_cv_lib_network_socket+y} -then : - printf %s "(cached) " >&6 -else $as_nop + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for socket in -lnetwork" >&5 +$as_echo_n "checking for socket in -lnetwork... " >&6; } +if ${ac_cv_lib_network_socket+:} false; then : + $as_echo_n "(cached) " >&6 +else ac_check_lib_save_LIBS=$LIBS LIBS="-lnetwork $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -9245,66 +8174,66 @@ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif char socket (); int -main (void) +main () { return socket (); ; return 0; } _ACEOF -if ac_fn_c_try_link "$LINENO" -then : +if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_network_socket=yes -else $as_nop +else ac_cv_lib_network_socket=no fi -rm -f core conftest.err conftest.$ac_objext conftest.beam \ +rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_network_socket" >&5 -printf "%s\n" "$ac_cv_lib_network_socket" >&6; } -if test "x$ac_cv_lib_network_socket" = xyes -then : - printf "%s\n" "#define HAVE_LIBNETWORK 1" >>confdefs.h +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_network_socket" >&5 +$as_echo "$ac_cv_lib_network_socket" >&6; } +if test "x$ac_cv_lib_network_socket" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBNETWORK 1 +_ACEOF LIBS="-lnetwork $LIBS" fi - printf "%s\n" "#define HAVE_U_INT64_T 1" >>confdefs.h - - -printf "%s\n" "#define DISABLE_UTMPX 1" >>confdefs.h + $as_echo "#define HAVE_U_INT64_T 1" >>confdefs.h + ssh_disable_utmpx=yes MANTYPE=man ;; *-*-hpux*) # first we define all of the options common to all HP-UX releases CPPFLAGS="$CPPFLAGS -D_HPUX_SOURCE -D_XOPEN_SOURCE -D_XOPEN_SOURCE_EXTENDED=1" IPADDR_IN_DISPLAY=yes - printf "%s\n" "#define USE_PIPES 1" >>confdefs.h + $as_echo "#define USE_PIPES 1" >>confdefs.h - printf "%s\n" "#define LOGIN_NEEDS_UTMPX 1" >>confdefs.h + $as_echo "#define LOGIN_NEEDS_UTMPX 1" >>confdefs.h -printf "%s\n" "#define LOCKED_PASSWD_STRING \"*\"" >>confdefs.h +$as_echo "#define LOCKED_PASSWD_STRING \"*\"" >>confdefs.h - printf "%s\n" "#define SPT_TYPE SPT_PSTAT" >>confdefs.h + $as_echo "#define SPT_TYPE SPT_PSTAT" >>confdefs.h -printf "%s\n" "#define PLATFORM_SYS_DIR_UID 2" >>confdefs.h +$as_echo "#define PLATFORM_SYS_DIR_UID 2" >>confdefs.h maildir="/var/mail" LIBS="$LIBS -lsec" - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for t_error in -lxnet" >&5 -printf %s "checking for t_error in -lxnet... " >&6; } -if test ${ac_cv_lib_xnet_t_error+y} -then : - printf %s "(cached) " >&6 -else $as_nop + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for t_error in -lxnet" >&5 +$as_echo_n "checking for t_error in -lxnet... " >&6; } +if ${ac_cv_lib_xnet_t_error+:} false; then : + $as_echo_n "(cached) " >&6 +else ac_check_lib_save_LIBS=$LIBS LIBS="-lxnet $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -9313,34 +8242,37 @@ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif char t_error (); int -main (void) +main () { return t_error (); ; return 0; } _ACEOF -if ac_fn_c_try_link "$LINENO" -then : +if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_xnet_t_error=yes -else $as_nop +else ac_cv_lib_xnet_t_error=no fi -rm -f core conftest.err conftest.$ac_objext conftest.beam \ +rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_xnet_t_error" >&5 -printf "%s\n" "$ac_cv_lib_xnet_t_error" >&6; } -if test "x$ac_cv_lib_xnet_t_error" = xyes -then : - printf "%s\n" "#define HAVE_LIBXNET 1" >>confdefs.h +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_xnet_t_error" >&5 +$as_echo "$ac_cv_lib_xnet_t_error" >&6; } +if test "x$ac_cv_lib_xnet_t_error" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBXNET 1 +_ACEOF LIBS="-lxnet $LIBS" -else $as_nop +else as_fn_error $? "*** -lxnet needed on HP-UX - check config.log ***" "$LINENO" 5 fi @@ -9352,18 +8284,18 @@ CFLAGS="$CFLAGS -Ae" fi -printf "%s\n" "#define BROKEN_GETLINE 1" >>confdefs.h +$as_echo "#define BROKEN_GETLINE 1" >>confdefs.h ;; *-*-hpux11*) -printf "%s\n" "#define PAM_SUN_CODEBASE 1" >>confdefs.h +$as_echo "#define PAM_SUN_CODEBASE 1" >>confdefs.h -printf "%s\n" "#define DISABLE_UTMP 1" >>confdefs.h +$as_echo "#define DISABLE_UTMP 1" >>confdefs.h -printf "%s\n" "#define USE_BTMP 1" >>confdefs.h +$as_echo "#define USE_BTMP 1" >>confdefs.h check_for_hpux_broken_getaddrinfo=1 check_for_conflicting_getspnam=1 @@ -9374,242 +8306,216 @@ case "$host" in *-*-hpux10.26) -printf "%s\n" "#define HAVE_SECUREWARE 1" >>confdefs.h +$as_echo "#define HAVE_SECUREWARE 1" >>confdefs.h - disable_ptmx_check=yes + ac_cv_file__dev_ptmx=disable LIBS="$LIBS -lsecpw" ;; esac ;; *-*-irix5*) PATH="$PATH:/usr/etc" + $as_echo "#define BROKEN_INET_NTOA 1" >>confdefs.h -printf "%s\n" "#define BROKEN_INET_NTOA 1" >>confdefs.h - - printf "%s\n" "#define SETEUID_BREAKS_SETUID 1" >>confdefs.h + $as_echo "#define SETEUID_BREAKS_SETUID 1" >>confdefs.h - printf "%s\n" "#define BROKEN_SETREUID 1" >>confdefs.h + $as_echo "#define BROKEN_SETREUID 1" >>confdefs.h - printf "%s\n" "#define BROKEN_SETREGID 1" >>confdefs.h + $as_echo "#define BROKEN_SETREGID 1" >>confdefs.h -printf "%s\n" "#define WITH_ABBREV_NO_TTY 1" >>confdefs.h +$as_echo "#define WITH_ABBREV_NO_TTY 1" >>confdefs.h - printf "%s\n" "#define LOCKED_PASSWD_STRING \"*LK*\"" >>confdefs.h + $as_echo "#define LOCKED_PASSWD_STRING \"*LK*\"" >>confdefs.h ;; *-*-irix6*) PATH="$PATH:/usr/etc" -printf "%s\n" "#define WITH_IRIX_ARRAY 1" >>confdefs.h +$as_echo "#define WITH_IRIX_ARRAY 1" >>confdefs.h -printf "%s\n" "#define WITH_IRIX_PROJECT 1" >>confdefs.h +$as_echo "#define WITH_IRIX_PROJECT 1" >>confdefs.h -printf "%s\n" "#define WITH_IRIX_AUDIT 1" >>confdefs.h +$as_echo "#define WITH_IRIX_AUDIT 1" >>confdefs.h ac_fn_c_check_func "$LINENO" "jlimit_startjob" "ac_cv_func_jlimit_startjob" -if test "x$ac_cv_func_jlimit_startjob" = xyes -then : +if test "x$ac_cv_func_jlimit_startjob" = xyes; then : -printf "%s\n" "#define WITH_IRIX_JOBS 1" >>confdefs.h +$as_echo "#define WITH_IRIX_JOBS 1" >>confdefs.h fi - printf "%s\n" "#define BROKEN_INET_NTOA 1" >>confdefs.h + $as_echo "#define BROKEN_INET_NTOA 1" >>confdefs.h - printf "%s\n" "#define SETEUID_BREAKS_SETUID 1" >>confdefs.h + $as_echo "#define SETEUID_BREAKS_SETUID 1" >>confdefs.h - printf "%s\n" "#define BROKEN_SETREUID 1" >>confdefs.h + $as_echo "#define BROKEN_SETREUID 1" >>confdefs.h - printf "%s\n" "#define BROKEN_SETREGID 1" >>confdefs.h + $as_echo "#define BROKEN_SETREGID 1" >>confdefs.h + $as_echo "#define BROKEN_UPDWTMPX 1" >>confdefs.h -printf "%s\n" "#define BROKEN_UPDWTMPX 1" >>confdefs.h + $as_echo "#define WITH_ABBREV_NO_TTY 1" >>confdefs.h - printf "%s\n" "#define WITH_ABBREV_NO_TTY 1" >>confdefs.h - - printf "%s\n" "#define LOCKED_PASSWD_STRING \"*LK*\"" >>confdefs.h + $as_echo "#define LOCKED_PASSWD_STRING \"*LK*\"" >>confdefs.h ;; *-*-k*bsd*-gnu | *-*-kopensolaris*-gnu) - printf "%s\n" "#define PAM_TTY_KLUDGE 1" >>confdefs.h + $as_echo "#define PAM_TTY_KLUDGE 1" >>confdefs.h - printf "%s\n" "#define LOCKED_PASSWD_PREFIX \"!\"" >>confdefs.h + $as_echo "#define LOCKED_PASSWD_PREFIX \"!\"" >>confdefs.h - printf "%s\n" "#define SPT_TYPE SPT_REUSEARGV" >>confdefs.h + $as_echo "#define SPT_TYPE SPT_REUSEARGV" >>confdefs.h -printf "%s\n" "#define _PATH_BTMP \"/var/log/btmp\"" >>confdefs.h +$as_echo "#define _PATH_BTMP \"/var/log/btmp\"" >>confdefs.h -printf "%s\n" "#define USE_BTMP 1" >>confdefs.h +$as_echo "#define USE_BTMP 1" >>confdefs.h ;; *-*-linux*) - no_dev_ptmx=1 + case "$host" in + *-*-linux-android*) ;; + *) + ac_cv_file__dev_ptmx=ignore;; + esac use_pie=auto check_for_openpty_ctty_bug=1 - CPPFLAGS="$CPPFLAGS -D_XOPEN_SOURCE=600 -D_BSD_SOURCE -D_DEFAULT_SOURCE -D_GNU_SOURCE" + CPPFLAGS="$CPPFLAGS -D_XOPEN_SOURCE=600 -D_BSD_SOURCE -D_DEFAULT_SOURCE" -printf "%s\n" "#define BROKEN_CLOSEFROM 1" >>confdefs.h +$as_echo "#define PAM_TTY_KLUDGE 1" >>confdefs.h -printf "%s\n" "#define PAM_TTY_KLUDGE 1" >>confdefs.h +$as_echo "#define LOCKED_PASSWD_PREFIX \"!\"" >>confdefs.h + $as_echo "#define SPT_TYPE SPT_REUSEARGV" >>confdefs.h -printf "%s\n" "#define LOCKED_PASSWD_PREFIX \"!\"" >>confdefs.h - printf "%s\n" "#define SPT_TYPE SPT_REUSEARGV" >>confdefs.h +$as_echo "#define LINK_OPNOTSUPP_ERRNO EPERM" >>confdefs.h + case "$host" in + *-*-linux-android*) ;; + *) -printf "%s\n" "#define LINK_OPNOTSUPP_ERRNO EPERM" >>confdefs.h +$as_echo "#define _PATH_BTMP \"/var/log/btmp\"" >>confdefs.h + $as_echo "#define USE_BTMP 1" >>confdefs.h -printf "%s\n" "#define _PATH_BTMP \"/var/log/btmp\"" >>confdefs.h + ;; + esac - printf "%s\n" "#define USE_BTMP 1" >>confdefs.h +$as_echo "#define LINUX_OOM_ADJUST 1" >>confdefs.h -printf "%s\n" "#define LINUX_OOM_ADJUST 1" >>confdefs.h + case "$host" in + *-*-linux-android*) + LIBS="$LIBS -llog" + XLDFLAGS="$XLDFLAGS -Wl,--wrap=open -Wl,--wrap=fopen" + XLDFLAGS="$XLDFLAGS -Wl,--wrap=rename" + XLDFLAGS="$XLDFLAGS -L. -lappinfo" + XDEPLIBS="$XDEPLIBS libappinfo.so" + ;; + esac inet6_default_4in6=yes case `uname -r` in 1.*|2.0.*) -printf "%s\n" "#define BROKEN_CMSG_TYPE 1" >>confdefs.h +$as_echo "#define BROKEN_CMSG_TYPE 1" >>confdefs.h ;; esac # tun(4) forwarding compat code - ac_fn_c_check_header_compile "$LINENO" "linux/if_tun.h" "ac_cv_header_linux_if_tun_h" "$ac_includes_default" -if test "x$ac_cv_header_linux_if_tun_h" = xyes -then : - printf "%s\n" "#define HAVE_LINUX_IF_TUN_H 1" >>confdefs.h + for ac_header in linux/if_tun.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "linux/if_tun.h" "ac_cv_header_linux_if_tun_h" "$ac_includes_default" +if test "x$ac_cv_header_linux_if_tun_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LINUX_IF_TUN_H 1 +_ACEOF fi +done + if test "x$ac_cv_header_linux_if_tun_h" = "xyes" ; then -printf "%s\n" "#define SSH_TUN_LINUX 1" >>confdefs.h +$as_echo "#define SSH_TUN_LINUX 1" >>confdefs.h -printf "%s\n" "#define SSH_TUN_COMPAT_AF 1" >>confdefs.h +$as_echo "#define SSH_TUN_COMPAT_AF 1" >>confdefs.h -printf "%s\n" "#define SSH_TUN_PREPEND_AF 1" >>confdefs.h +$as_echo "#define SSH_TUN_PREPEND_AF 1" >>confdefs.h fi ac_fn_c_check_header_compile "$LINENO" "linux/if.h" "ac_cv_header_linux_if_h" " -#ifdef HAVE_SYS_TYPES_H -# include -#endif + #ifdef HAVE_SYS_TYPES_H + # include + #endif + #include " -if test "x$ac_cv_header_linux_if_h" = xyes -then : +if test "x$ac_cv_header_linux_if_h" = xyes; then : -printf "%s\n" "#define SYS_RDOMAIN_LINUX 1" >>confdefs.h +$as_echo "#define SYS_RDOMAIN_LINUX 1" >>confdefs.h fi - ac_fn_c_check_header_compile "$LINENO" "linux/seccomp.h" "ac_cv_header_linux_seccomp_h" "#include -" -if test "x$ac_cv_header_linux_seccomp_h" = xyes -then : - printf "%s\n" "#define HAVE_LINUX_SECCOMP_H 1" >>confdefs.h -fi -ac_fn_c_check_header_compile "$LINENO" "linux/filter.h" "ac_cv_header_linux_filter_h" "#include + for ac_header in linux/seccomp.h linux/filter.h linux/audit.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "#include " -if test "x$ac_cv_header_linux_filter_h" = xyes -then : - printf "%s\n" "#define HAVE_LINUX_FILTER_H 1" >>confdefs.h +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF fi -ac_fn_c_check_header_compile "$LINENO" "linux/audit.h" "ac_cv_header_linux_audit_h" "#include -" -if test "x$ac_cv_header_linux_audit_h" = xyes -then : - printf "%s\n" "#define HAVE_LINUX_AUDIT_H 1" >>confdefs.h -fi +done # Obtain MIPS ABI case "$host" in - mips*) + mips64*) cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -#if _MIPS_SIM != _ABIO32 -#error -#endif - -int -main (void) -{ - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO" -then : - mips_abi="o32" -else $as_nop - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - #if _MIPS_SIM != _ABIN32 #error #endif - -int -main (void) -{ - - ; - return 0; -} _ACEOF -if ac_fn_c_try_compile "$LINENO" -then : - mips_abi="n32" -else $as_nop - cat confdefs.h - <<_ACEOF >conftest.$ac_ext +if ac_fn_c_try_compile "$LINENO"; then : + mips64_abi="n32" +else + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #if _MIPS_SIM != _ABI64 #error #endif - -int -main (void) -{ - - ; - return 0; -} _ACEOF -if ac_fn_c_try_compile "$LINENO" -then : - mips_abi="n64" -else $as_nop - as_fn_error $? "unknown MIPS ABI" "$LINENO" 5 +if ac_fn_c_try_compile "$LINENO"; then : + mips64_abi="n64" +else -fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext + as_fn_error $? "unknown MIPS ABI" "$LINENO" 5 fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ;; esac - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for seccomp architecture" >&5 -printf %s "checking for seccomp architecture... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for seccomp architecture" >&5 +$as_echo_n "checking for seccomp architecture... " >&6; } seccomp_audit_arch= case "$host" in x86_64-*) @@ -9646,7 +8552,7 @@ seccomp_audit_arch=AUDIT_ARCH_MIPSEL ;; mips64-*) - case "$mips_abi" in + case "$mips64_abi" in "n32") seccomp_audit_arch=AUDIT_ARCH_MIPS64N32 ;; @@ -9656,7 +8562,7 @@ esac ;; mips64el-*) - case "$mips_abi" in + case "$mips64_abi" in "n32") seccomp_audit_arch=AUDIT_ARCH_MIPSEL64N32 ;; @@ -9670,82 +8576,73 @@ ;; esac if test "x$seccomp_audit_arch" != "x" ; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: \"$seccomp_audit_arch\"" >&5 -printf "%s\n" "\"$seccomp_audit_arch\"" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: \"$seccomp_audit_arch\"" >&5 +$as_echo "\"$seccomp_audit_arch\"" >&6; } -printf "%s\n" "#define SECCOMP_AUDIT_ARCH $seccomp_audit_arch" >>confdefs.h +cat >>confdefs.h <<_ACEOF +#define SECCOMP_AUDIT_ARCH $seccomp_audit_arch +_ACEOF else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: architecture not supported" >&5 -printf "%s\n" "architecture not supported" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: architecture not supported" >&5 +$as_echo "architecture not supported" >&6; } fi ;; *-*-minix) - printf "%s\n" "#define SETEUID_BREAKS_SETUID 1" >>confdefs.h + $as_echo "#define SETEUID_BREAKS_SETUID 1" >>confdefs.h # poll(2) seems to choke on /dev/null; "Bad file descriptor" - -printf "%s\n" "#define BROKEN_POLL 1" >>confdefs.h + $as_echo "#define BROKEN_POLL 1" >>confdefs.h ;; mips-sony-bsd|mips-sony-newsos4) - -printf "%s\n" "#define NEED_SETPGRP 1" >>confdefs.h + $as_echo "#define NEED_SETPGRP 1" >>confdefs.h SONY=1 ;; *-*-netbsd*) - if test "x$withval" != "xno" ; then - rpath_opt="-R" - fi CPPFLAGS="$CPPFLAGS -D_OPENBSD_SOURCE" -printf "%s\n" "#define SSH_TUN_FREEBSD 1" >>confdefs.h +$as_echo "#define SSH_TUN_FREEBSD 1" >>confdefs.h - ac_fn_c_check_header_compile "$LINENO" "net/if_tap.h" "ac_cv_header_net_if_tap_h" "$ac_includes_default" -if test "x$ac_cv_header_net_if_tap_h" = xyes -then : + ac_fn_c_check_header_mongrel "$LINENO" "net/if_tap.h" "ac_cv_header_net_if_tap_h" "$ac_includes_default" +if test "x$ac_cv_header_net_if_tap_h" = xyes; then : -else $as_nop +else -printf "%s\n" "#define SSH_TUN_NO_L2 1" >>confdefs.h +$as_echo "#define SSH_TUN_NO_L2 1" >>confdefs.h fi -printf "%s\n" "#define SSH_TUN_PREPEND_AF 1" >>confdefs.h + +$as_echo "#define SSH_TUN_PREPEND_AF 1" >>confdefs.h TEST_MALLOC_OPTIONS="AJRX" -printf "%s\n" "#define BROKEN_READ_COMPARISON 1" >>confdefs.h +$as_echo "#define BROKEN_READ_COMPARISON 1" >>confdefs.h ;; *-*-freebsd*) -printf "%s\n" "#define LOCKED_PASSWD_PREFIX \"*LOCKED*\"" >>confdefs.h +$as_echo "#define LOCKED_PASSWD_PREFIX \"*LOCKED*\"" >>confdefs.h -printf "%s\n" "#define SSH_TUN_FREEBSD 1" >>confdefs.h +$as_echo "#define SSH_TUN_FREEBSD 1" >>confdefs.h - ac_fn_c_check_header_compile "$LINENO" "net/if_tap.h" "ac_cv_header_net_if_tap_h" "$ac_includes_default" -if test "x$ac_cv_header_net_if_tap_h" = xyes -then : + ac_fn_c_check_header_mongrel "$LINENO" "net/if_tap.h" "ac_cv_header_net_if_tap_h" "$ac_includes_default" +if test "x$ac_cv_header_net_if_tap_h" = xyes; then : -else $as_nop +else -printf "%s\n" "#define SSH_TUN_NO_L2 1" >>confdefs.h +$as_echo "#define SSH_TUN_NO_L2 1" >>confdefs.h fi -printf "%s\n" "#define BROKEN_GLOB 1" >>confdefs.h + $as_echo "#define BROKEN_GLOB 1" >>confdefs.h TEST_MALLOC_OPTIONS="AJRX" - # Preauth crypto occasionally uses file descriptors for crypto offload - # and will crash if they cannot be opened. - -printf "%s\n" "#define SANDBOX_SKIP_RLIMIT_NOFILE 1" >>confdefs.h - case "$host" in *-*-freebsd9.*|*-*-freebsd10.*) # Capsicum on 9 and 10 do not allow ppoll() so don't auto-enable. @@ -9753,11 +8650,11 @@ esac ;; *-*-bsdi*) - printf "%s\n" "#define SETEUID_BREAKS_SETUID 1" >>confdefs.h + $as_echo "#define SETEUID_BREAKS_SETUID 1" >>confdefs.h - printf "%s\n" "#define BROKEN_SETREUID 1" >>confdefs.h + $as_echo "#define BROKEN_SETREUID 1" >>confdefs.h - printf "%s\n" "#define BROKEN_SETREGID 1" >>confdefs.h + $as_echo "#define BROKEN_SETREGID 1" >>confdefs.h ;; *-next-*) @@ -9766,112 +8663,119 @@ conf_wtmp_location=/usr/adm/wtmp maildir=/usr/spool/mail -printf "%s\n" "#define HAVE_NEXT 1" >>confdefs.h +$as_echo "#define HAVE_NEXT 1" >>confdefs.h - printf "%s\n" "#define USE_PIPES 1" >>confdefs.h + $as_echo "#define USE_PIPES 1" >>confdefs.h -printf "%s\n" "#define BROKEN_SAVED_UIDS 1" >>confdefs.h +$as_echo "#define BROKEN_SAVED_UIDS 1" >>confdefs.h ;; *-*-openbsd*) use_pie=auto -printf "%s\n" "#define HAVE_ATTRIBUTE__SENTINEL__ 1" >>confdefs.h - - -printf "%s\n" "#define HAVE_ATTRIBUTE__BOUNDED__ 1" >>confdefs.h +$as_echo "#define HAVE_ATTRIBUTE__BOUNDED__ 1" >>confdefs.h -printf "%s\n" "#define SSH_TUN_OPENBSD 1" >>confdefs.h +$as_echo "#define SSH_TUN_OPENBSD 1" >>confdefs.h -printf "%s\n" "#define SYSLOG_R_SAFE_IN_SIGHAND 1" >>confdefs.h +$as_echo "#define SYSLOG_R_SAFE_IN_SIGHAND 1" >>confdefs.h TEST_MALLOC_OPTIONS="AFGJPRX" ;; *-*-solaris*) - if test "x$withval" != "xno" ; then - rpath_opt="-R" - fi - printf "%s\n" "#define PAM_SUN_CODEBASE 1" >>confdefs.h + $as_echo "#define PAM_SUN_CODEBASE 1" >>confdefs.h - printf "%s\n" "#define LOGIN_NEEDS_UTMPX 1" >>confdefs.h + $as_echo "#define LOGIN_NEEDS_UTMPX 1" >>confdefs.h - printf "%s\n" "#define PAM_TTY_KLUDGE 1" >>confdefs.h + $as_echo "#define PAM_TTY_KLUDGE 1" >>confdefs.h -printf "%s\n" "#define SSHPAM_CHAUTHTOK_NEEDS_RUID 1" >>confdefs.h +$as_echo "#define SSHPAM_CHAUTHTOK_NEEDS_RUID 1" >>confdefs.h - printf "%s\n" "#define LOCKED_PASSWD_STRING \"*LK*\"" >>confdefs.h + $as_echo "#define LOCKED_PASSWD_STRING \"*LK*\"" >>confdefs.h # Pushing STREAMS modules will cause sshd to acquire a controlling tty. + $as_echo "#define SSHD_ACQUIRES_CTTY 1" >>confdefs.h -printf "%s\n" "#define SSHD_ACQUIRES_CTTY 1" >>confdefs.h +$as_echo "#define PASSWD_NEEDS_USERNAME 1" >>confdefs.h -printf "%s\n" "#define PASSWD_NEEDS_USERNAME 1" >>confdefs.h - - -printf "%s\n" "#define BROKEN_TCGETATTR_ICANON 1" >>confdefs.h + $as_echo "#define BROKEN_TCGETATTR_ICANON 1" >>confdefs.h external_path_file=/etc/default/login # hardwire lastlog location (can't detect it on some versions) conf_lastlog_location="/var/adm/lastlog" - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for obsolete utmp and wtmp in solaris2.x" >&5 -printf %s "checking for obsolete utmp and wtmp in solaris2.x... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for obsolete utmp and wtmp in solaris2.x" >&5 +$as_echo_n "checking for obsolete utmp and wtmp in solaris2.x... " >&6; } sol2ver=`echo "$host"| sed -e 's/.*[0-9]\.//'` if test "$sol2ver" -ge 8; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } - printf "%s\n" "#define DISABLE_UTMP 1" >>confdefs.h + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + $as_echo "#define DISABLE_UTMP 1" >>confdefs.h -printf "%s\n" "#define DISABLE_WTMP 1" >>confdefs.h +$as_echo "#define DISABLE_WTMP 1" >>confdefs.h else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } fi - ac_fn_c_check_func "$LINENO" "setpflags" "ac_cv_func_setpflags" -if test "x$ac_cv_func_setpflags" = xyes -then : - printf "%s\n" "#define HAVE_SETPFLAGS 1" >>confdefs.h + for ac_func in setpflags +do : + ac_fn_c_check_func "$LINENO" "setpflags" "ac_cv_func_setpflags" +if test "x$ac_cv_func_setpflags" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_SETPFLAGS 1 +_ACEOF fi +done - ac_fn_c_check_func "$LINENO" "setppriv" "ac_cv_func_setppriv" -if test "x$ac_cv_func_setppriv" = xyes -then : - printf "%s\n" "#define HAVE_SETPPRIV 1" >>confdefs.h + for ac_func in setppriv +do : + ac_fn_c_check_func "$LINENO" "setppriv" "ac_cv_func_setppriv" +if test "x$ac_cv_func_setppriv" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_SETPPRIV 1 +_ACEOF fi +done - ac_fn_c_check_func "$LINENO" "priv_basicset" "ac_cv_func_priv_basicset" -if test "x$ac_cv_func_priv_basicset" = xyes -then : - printf "%s\n" "#define HAVE_PRIV_BASICSET 1" >>confdefs.h + for ac_func in priv_basicset +do : + ac_fn_c_check_func "$LINENO" "priv_basicset" "ac_cv_func_priv_basicset" +if test "x$ac_cv_func_priv_basicset" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_PRIV_BASICSET 1 +_ACEOF fi +done - ac_fn_c_check_header_compile "$LINENO" "priv.h" "ac_cv_header_priv_h" "$ac_includes_default" -if test "x$ac_cv_header_priv_h" = xyes -then : - printf "%s\n" "#define HAVE_PRIV_H 1" >>confdefs.h + for ac_header in priv.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "priv.h" "ac_cv_header_priv_h" "$ac_includes_default" +if test "x$ac_cv_header_priv_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_PRIV_H 1 +_ACEOF fi +done + # Check whether --with-solaris-contracts was given. -if test ${with_solaris_contracts+y} -then : +if test "${with_solaris_contracts+set}" = set; then : withval=$with_solaris_contracts; - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ct_tmpl_activate in -lcontract" >&5 -printf %s "checking for ct_tmpl_activate in -lcontract... " >&6; } -if test ${ac_cv_lib_contract_ct_tmpl_activate+y} -then : - printf %s "(cached) " >&6 -else $as_nop + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ct_tmpl_activate in -lcontract" >&5 +$as_echo_n "checking for ct_tmpl_activate in -lcontract... " >&6; } +if ${ac_cv_lib_contract_ct_tmpl_activate+:} false; then : + $as_echo_n "(cached) " >&6 +else ac_check_lib_save_LIBS=$LIBS LIBS="-lcontract $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -9880,31 +8784,32 @@ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif char ct_tmpl_activate (); int -main (void) +main () { return ct_tmpl_activate (); ; return 0; } _ACEOF -if ac_fn_c_try_link "$LINENO" -then : +if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_contract_ct_tmpl_activate=yes -else $as_nop +else ac_cv_lib_contract_ct_tmpl_activate=no fi -rm -f core conftest.err conftest.$ac_objext conftest.beam \ +rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_contract_ct_tmpl_activate" >&5 -printf "%s\n" "$ac_cv_lib_contract_ct_tmpl_activate" >&6; } -if test "x$ac_cv_lib_contract_ct_tmpl_activate" = xyes -then : +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_contract_ct_tmpl_activate" >&5 +$as_echo "$ac_cv_lib_contract_ct_tmpl_activate" >&6; } +if test "x$ac_cv_lib_contract_ct_tmpl_activate" = xyes; then : -printf "%s\n" "#define USE_SOLARIS_PROCESS_CONTRACTS 1" >>confdefs.h +$as_echo "#define USE_SOLARIS_PROCESS_CONTRACTS 1" >>confdefs.h LIBS="$LIBS -lcontract" SPC_MSG="yes" @@ -9915,15 +8820,13 @@ # Check whether --with-solaris-projects was given. -if test ${with_solaris_projects+y} -then : +if test "${with_solaris_projects+set}" = set; then : withval=$with_solaris_projects; - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for setproject in -lproject" >&5 -printf %s "checking for setproject in -lproject... " >&6; } -if test ${ac_cv_lib_project_setproject+y} -then : - printf %s "(cached) " >&6 -else $as_nop + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for setproject in -lproject" >&5 +$as_echo_n "checking for setproject in -lproject... " >&6; } +if ${ac_cv_lib_project_setproject+:} false; then : + $as_echo_n "(cached) " >&6 +else ac_check_lib_save_LIBS=$LIBS LIBS="-lproject $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -9932,31 +8835,32 @@ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif char setproject (); int -main (void) +main () { return setproject (); ; return 0; } _ACEOF -if ac_fn_c_try_link "$LINENO" -then : +if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_project_setproject=yes -else $as_nop +else ac_cv_lib_project_setproject=no fi -rm -f core conftest.err conftest.$ac_objext conftest.beam \ +rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_project_setproject" >&5 -printf "%s\n" "$ac_cv_lib_project_setproject" >&6; } -if test "x$ac_cv_lib_project_setproject" = xyes -then : +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_project_setproject" >&5 +$as_echo "$ac_cv_lib_project_setproject" >&6; } +if test "x$ac_cv_lib_project_setproject" = xyes; then : -printf "%s\n" "#define USE_SOLARIS_PROJECTS 1" >>confdefs.h +$as_echo "#define USE_SOLARIS_PROJECTS 1" >>confdefs.h LIBS="$LIBS -lproject" SP_MSG="yes" @@ -9967,74 +8871,73 @@ # Check whether --with-solaris-privs was given. -if test ${with_solaris_privs+y} -then : +if test "${with_solaris_privs+set}" = set; then : withval=$with_solaris_privs; - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for Solaris/Illumos privilege support" >&5 -printf %s "checking for Solaris/Illumos privilege support... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Solaris/Illumos privilege support" >&5 +$as_echo_n "checking for Solaris/Illumos privilege support... " >&6; } if test "x$ac_cv_func_setppriv" = "xyes" -a \ "x$ac_cv_header_priv_h" = "xyes" ; then SOLARIS_PRIVS=yes - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: found" >&5 -printf "%s\n" "found" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: found" >&5 +$as_echo "found" >&6; } -printf "%s\n" "#define NO_UID_RESTORATION_TEST 1" >>confdefs.h +$as_echo "#define NO_UID_RESTORATION_TEST 1" >>confdefs.h -printf "%s\n" "#define USE_SOLARIS_PRIVS 1" >>confdefs.h +$as_echo "#define USE_SOLARIS_PRIVS 1" >>confdefs.h SPP_MSG="yes" else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: not found" >&5 -printf "%s\n" "not found" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5 +$as_echo "not found" >&6; } as_fn_error $? "*** must have support for Solaris privileges to use --with-solaris-privs" "$LINENO" 5 fi fi - TEST_SHELL=$SHELL # let configure find us a capable shell ;; *-*-sunos4*) CPPFLAGS="$CPPFLAGS -DSUNOS4" - ac_fn_c_check_func "$LINENO" "getpwanam" "ac_cv_func_getpwanam" -if test "x$ac_cv_func_getpwanam" = xyes -then : - printf "%s\n" "#define HAVE_GETPWANAM 1" >>confdefs.h + for ac_func in getpwanam +do : + ac_fn_c_check_func "$LINENO" "getpwanam" "ac_cv_func_getpwanam" +if test "x$ac_cv_func_getpwanam" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_GETPWANAM 1 +_ACEOF fi +done - printf "%s\n" "#define PAM_SUN_CODEBASE 1" >>confdefs.h + $as_echo "#define PAM_SUN_CODEBASE 1" >>confdefs.h conf_utmp_location=/etc/utmp conf_wtmp_location=/var/adm/wtmp conf_lastlog_location=/var/adm/lastlog - printf "%s\n" "#define USE_PIPES 1" >>confdefs.h - - -printf "%s\n" "#define DISABLE_UTMPX 1" >>confdefs.h + $as_echo "#define USE_PIPES 1" >>confdefs.h + ssh_disable_utmpx=yes ;; *-ncr-sysv*) LIBS="$LIBS -lc89" - printf "%s\n" "#define USE_PIPES 1" >>confdefs.h + $as_echo "#define USE_PIPES 1" >>confdefs.h - printf "%s\n" "#define SSHD_ACQUIRES_CTTY 1" >>confdefs.h + $as_echo "#define SSHD_ACQUIRES_CTTY 1" >>confdefs.h - printf "%s\n" "#define SETEUID_BREAKS_SETUID 1" >>confdefs.h + $as_echo "#define SETEUID_BREAKS_SETUID 1" >>confdefs.h - printf "%s\n" "#define BROKEN_SETREUID 1" >>confdefs.h + $as_echo "#define BROKEN_SETREUID 1" >>confdefs.h - printf "%s\n" "#define BROKEN_SETREGID 1" >>confdefs.h + $as_echo "#define BROKEN_SETREGID 1" >>confdefs.h ;; *-sni-sysv*) # /usr/ucblib MUST NOT be searched on ReliantUNIX - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for dlsym in -ldl" >&5 -printf %s "checking for dlsym in -ldl... " >&6; } -if test ${ac_cv_lib_dl_dlsym+y} -then : - printf %s "(cached) " >&6 -else $as_nop + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlsym in -ldl" >&5 +$as_echo_n "checking for dlsym in -ldl... " >&6; } +if ${ac_cv_lib_dl_dlsym+:} false; then : + $as_echo_n "(cached) " >&6 +else ac_check_lib_save_LIBS=$LIBS LIBS="-ldl $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -10043,42 +8946,44 @@ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif char dlsym (); int -main (void) +main () { return dlsym (); ; return 0; } _ACEOF -if ac_fn_c_try_link "$LINENO" -then : +if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dl_dlsym=yes -else $as_nop +else ac_cv_lib_dl_dlsym=no fi -rm -f core conftest.err conftest.$ac_objext conftest.beam \ +rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlsym" >&5 -printf "%s\n" "$ac_cv_lib_dl_dlsym" >&6; } -if test "x$ac_cv_lib_dl_dlsym" = xyes -then : - printf "%s\n" "#define HAVE_LIBDL 1" >>confdefs.h +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlsym" >&5 +$as_echo "$ac_cv_lib_dl_dlsym" >&6; } +if test "x$ac_cv_lib_dl_dlsym" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBDL 1 +_ACEOF LIBS="-ldl $LIBS" fi # -lresolv needs to be at the end of LIBS or DNS lookups break - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for res_query in -lresolv" >&5 -printf %s "checking for res_query in -lresolv... " >&6; } -if test ${ac_cv_lib_resolv_res_query+y} -then : - printf %s "(cached) " >&6 -else $as_nop + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for res_query in -lresolv" >&5 +$as_echo_n "checking for res_query in -lresolv... " >&6; } +if ${ac_cv_lib_resolv_res_query+:} false; then : + $as_echo_n "(cached) " >&6 +else ac_check_lib_save_LIBS=$LIBS LIBS="-lresolv $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -10087,44 +8992,45 @@ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif char res_query (); int -main (void) +main () { return res_query (); ; return 0; } _ACEOF -if ac_fn_c_try_link "$LINENO" -then : +if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_resolv_res_query=yes -else $as_nop +else ac_cv_lib_resolv_res_query=no fi -rm -f core conftest.err conftest.$ac_objext conftest.beam \ +rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_resolv_res_query" >&5 -printf "%s\n" "$ac_cv_lib_resolv_res_query" >&6; } -if test "x$ac_cv_lib_resolv_res_query" = xyes -then : +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_resolv_res_query" >&5 +$as_echo "$ac_cv_lib_resolv_res_query" >&6; } +if test "x$ac_cv_lib_resolv_res_query" = xyes; then : LIBS="$LIBS -lresolv" fi IPADDR_IN_DISPLAY=yes - printf "%s\n" "#define USE_PIPES 1" >>confdefs.h + $as_echo "#define USE_PIPES 1" >>confdefs.h - printf "%s\n" "#define IP_TOS_IS_BROKEN 1" >>confdefs.h + $as_echo "#define IP_TOS_IS_BROKEN 1" >>confdefs.h - printf "%s\n" "#define SETEUID_BREAKS_SETUID 1" >>confdefs.h + $as_echo "#define SETEUID_BREAKS_SETUID 1" >>confdefs.h - printf "%s\n" "#define BROKEN_SETREUID 1" >>confdefs.h + $as_echo "#define BROKEN_SETREUID 1" >>confdefs.h - printf "%s\n" "#define BROKEN_SETREGID 1" >>confdefs.h + $as_echo "#define BROKEN_SETREGID 1" >>confdefs.h - printf "%s\n" "#define SSHD_ACQUIRES_CTTY 1" >>confdefs.h + $as_echo "#define SSHD_ACQUIRES_CTTY 1" >>confdefs.h external_path_file=/etc/default/login # /usr/ucblib/libucb.a no longer needed on ReliantUNIX @@ -10133,53 +9039,50 @@ ;; # UnixWare 1.x, UnixWare 2.x, and others based on code from Univel. *-*-sysv4.2*) - printf "%s\n" "#define USE_PIPES 1" >>confdefs.h + $as_echo "#define USE_PIPES 1" >>confdefs.h - printf "%s\n" "#define SETEUID_BREAKS_SETUID 1" >>confdefs.h + $as_echo "#define SETEUID_BREAKS_SETUID 1" >>confdefs.h - printf "%s\n" "#define BROKEN_SETREUID 1" >>confdefs.h + $as_echo "#define BROKEN_SETREUID 1" >>confdefs.h - printf "%s\n" "#define BROKEN_SETREGID 1" >>confdefs.h + $as_echo "#define BROKEN_SETREGID 1" >>confdefs.h -printf "%s\n" "#define PASSWD_NEEDS_USERNAME 1" >>confdefs.h +$as_echo "#define PASSWD_NEEDS_USERNAME 1" >>confdefs.h - printf "%s\n" "#define LOCKED_PASSWD_STRING \"*LK*\"" >>confdefs.h + $as_echo "#define LOCKED_PASSWD_STRING \"*LK*\"" >>confdefs.h - TEST_SHELL=$SHELL # let configure find us a capable shell ;; # UnixWare 7.x, OpenUNIX 8 *-*-sysv5*) CPPFLAGS="$CPPFLAGS -Dvsnprintf=_xvsnprintf -Dsnprintf=_xsnprintf" -printf "%s\n" "#define UNIXWARE_LONG_PASSWORDS 1" >>confdefs.h +$as_echo "#define UNIXWARE_LONG_PASSWORDS 1" >>confdefs.h - printf "%s\n" "#define USE_PIPES 1" >>confdefs.h + $as_echo "#define USE_PIPES 1" >>confdefs.h - printf "%s\n" "#define SETEUID_BREAKS_SETUID 1" >>confdefs.h + $as_echo "#define SETEUID_BREAKS_SETUID 1" >>confdefs.h - printf "%s\n" "#define BROKEN_GETADDRINFO 1" >>confdefs.h + $as_echo "#define BROKEN_GETADDRINFO 1" >>confdefs.h - printf "%s\n" "#define BROKEN_SETREUID 1" >>confdefs.h + $as_echo "#define BROKEN_SETREUID 1" >>confdefs.h - printf "%s\n" "#define BROKEN_SETREGID 1" >>confdefs.h + $as_echo "#define BROKEN_SETREGID 1" >>confdefs.h - printf "%s\n" "#define PASSWD_NEEDS_USERNAME 1" >>confdefs.h + $as_echo "#define PASSWD_NEEDS_USERNAME 1" >>confdefs.h - printf "%s\n" "#define BROKEN_TCGETATTR_ICANON 1" >>confdefs.h + $as_echo "#define BROKEN_TCGETATTR_ICANON 1" >>confdefs.h - TEST_SHELL=$SHELL # let configure find us a capable shell case "$host" in *-*-sysv5SCO_SV*) # SCO OpenServer 6.x maildir=/var/spool/mail - printf "%s\n" "#define BROKEN_UPDWTMPX 1" >>confdefs.h + $as_echo "#define BROKEN_UPDWTMPX 1" >>confdefs.h - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for getluid in -lprot" >&5 -printf %s "checking for getluid in -lprot... " >&6; } -if test ${ac_cv_lib_prot_getluid+y} -then : - printf %s "(cached) " >&6 -else $as_nop + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for getluid in -lprot" >&5 +$as_echo_n "checking for getluid in -lprot... " >&6; } +if ${ac_cv_lib_prot_getluid+:} false; then : + $as_echo_n "(cached) " >&6 +else ac_check_lib_save_LIBS=$LIBS LIBS="-lprot $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -10188,48 +9091,48 @@ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif char getluid (); int -main (void) +main () { return getluid (); ; return 0; } _ACEOF -if ac_fn_c_try_link "$LINENO" -then : +if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_prot_getluid=yes -else $as_nop +else ac_cv_lib_prot_getluid=no fi -rm -f core conftest.err conftest.$ac_objext conftest.beam \ +rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_prot_getluid" >&5 -printf "%s\n" "$ac_cv_lib_prot_getluid" >&6; } -if test "x$ac_cv_lib_prot_getluid" = xyes -then : +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_prot_getluid" >&5 +$as_echo "$ac_cv_lib_prot_getluid" >&6; } +if test "x$ac_cv_lib_prot_getluid" = xyes; then : LIBS="$LIBS -lprot" - ac_fn_c_check_func "$LINENO" "getluid" "ac_cv_func_getluid" -if test "x$ac_cv_func_getluid" = xyes -then : - printf "%s\n" "#define HAVE_GETLUID 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "setluid" "ac_cv_func_setluid" -if test "x$ac_cv_func_setluid" = xyes -then : - printf "%s\n" "#define HAVE_SETLUID 1" >>confdefs.h + for ac_func in getluid setluid +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF fi +done fi ;; - *) printf "%s\n" "#define LOCKED_PASSWD_STRING \"*LK*\"" >>confdefs.h + *) $as_echo "#define LOCKED_PASSWD_STRING \"*LK*\"" >>confdefs.h ;; esac @@ -10242,62 +9145,59 @@ ;; # SCO OpenServer 5.x *-*-sco3.2v5*) + ac_cv_file__dev_ptmx=ignore if test -z "$GCC"; then CFLAGS="$CFLAGS -belf" fi LIBS="$LIBS -lprot -lx -ltinfo -lm" - no_dev_ptmx=1 - printf "%s\n" "#define USE_PIPES 1" >>confdefs.h - - printf "%s\n" "#define HAVE_SECUREWARE 1" >>confdefs.h + $as_echo "#define USE_PIPES 1" >>confdefs.h - printf "%s\n" "#define DISABLE_SHADOW 1" >>confdefs.h + $as_echo "#define HAVE_SECUREWARE 1" >>confdefs.h - printf "%s\n" "#define DISABLE_FD_PASSING 1" >>confdefs.h + $as_echo "#define DISABLE_SHADOW 1" >>confdefs.h - printf "%s\n" "#define SETEUID_BREAKS_SETUID 1" >>confdefs.h + $as_echo "#define DISABLE_FD_PASSING 1" >>confdefs.h - printf "%s\n" "#define BROKEN_GETADDRINFO 1" >>confdefs.h + $as_echo "#define SETEUID_BREAKS_SETUID 1" >>confdefs.h - printf "%s\n" "#define BROKEN_SETREUID 1" >>confdefs.h + $as_echo "#define BROKEN_GETADDRINFO 1" >>confdefs.h - printf "%s\n" "#define BROKEN_SETREGID 1" >>confdefs.h + $as_echo "#define BROKEN_SETREUID 1" >>confdefs.h - printf "%s\n" "#define WITH_ABBREV_NO_TTY 1" >>confdefs.h + $as_echo "#define BROKEN_SETREGID 1" >>confdefs.h - printf "%s\n" "#define BROKEN_UPDWTMPX 1" >>confdefs.h + $as_echo "#define WITH_ABBREV_NO_TTY 1" >>confdefs.h - printf "%s\n" "#define PASSWD_NEEDS_USERNAME 1" >>confdefs.h + $as_echo "#define BROKEN_UPDWTMPX 1" >>confdefs.h - ac_fn_c_check_func "$LINENO" "getluid" "ac_cv_func_getluid" -if test "x$ac_cv_func_getluid" = xyes -then : - printf "%s\n" "#define HAVE_GETLUID 1" >>confdefs.h + $as_echo "#define PASSWD_NEEDS_USERNAME 1" >>confdefs.h -fi -ac_fn_c_check_func "$LINENO" "setluid" "ac_cv_func_setluid" -if test "x$ac_cv_func_setluid" = xyes -then : - printf "%s\n" "#define HAVE_SETLUID 1" >>confdefs.h + for ac_func in getluid setluid +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF fi +done MANTYPE=man - TEST_SHELL=$SHELL # let configure find us a capable shell SKIP_DISABLE_LASTLOG_DEFINE=yes ;; *-dec-osf*) - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for Digital Unix SIA" >&5 -printf %s "checking for Digital Unix SIA... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Digital Unix SIA" >&5 +$as_echo_n "checking for Digital Unix SIA... " >&6; } no_osfsia="" # Check whether --with-osfsia was given. -if test ${with_osfsia+y} -then : +if test "${with_osfsia+set}" = set; then : withval=$with_osfsia; if test "x$withval" = "xno" ; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: disabled" >&5 -printf "%s\n" "disabled" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: disabled" >&5 +$as_echo "disabled" >&6; } no_osfsia=1 fi @@ -10305,55 +9205,55 @@ if test -z "$no_osfsia" ; then if test -f /etc/sia/matrix.conf; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } -printf "%s\n" "#define HAVE_OSF_SIA 1" >>confdefs.h +$as_echo "#define HAVE_OSF_SIA 1" >>confdefs.h -printf "%s\n" "#define DISABLE_LOGIN 1" >>confdefs.h +$as_echo "#define DISABLE_LOGIN 1" >>confdefs.h - printf "%s\n" "#define DISABLE_FD_PASSING 1" >>confdefs.h + $as_echo "#define DISABLE_FD_PASSING 1" >>confdefs.h LIBS="$LIBS -lsecurity -ldb -lm -laud" SIA_MSG="yes" else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } -printf "%s\n" "#define LOCKED_PASSWD_SUBSTR \"Nologin\"" >>confdefs.h +$as_echo "#define LOCKED_PASSWD_SUBSTR \"Nologin\"" >>confdefs.h fi fi - printf "%s\n" "#define BROKEN_GETADDRINFO 1" >>confdefs.h + $as_echo "#define BROKEN_GETADDRINFO 1" >>confdefs.h - printf "%s\n" "#define SETEUID_BREAKS_SETUID 1" >>confdefs.h + $as_echo "#define SETEUID_BREAKS_SETUID 1" >>confdefs.h - printf "%s\n" "#define BROKEN_SETREUID 1" >>confdefs.h + $as_echo "#define BROKEN_SETREUID 1" >>confdefs.h - printf "%s\n" "#define BROKEN_SETREGID 1" >>confdefs.h + $as_echo "#define BROKEN_SETREGID 1" >>confdefs.h -printf "%s\n" "#define BROKEN_READV_COMPARISON 1" >>confdefs.h +$as_echo "#define BROKEN_READV_COMPARISON 1" >>confdefs.h ;; *-*-nto-qnx*) - printf "%s\n" "#define USE_PIPES 1" >>confdefs.h + $as_echo "#define USE_PIPES 1" >>confdefs.h - printf "%s\n" "#define NO_X11_UNIX_SOCKETS 1" >>confdefs.h + $as_echo "#define NO_X11_UNIX_SOCKETS 1" >>confdefs.h - printf "%s\n" "#define DISABLE_LASTLOG 1" >>confdefs.h + $as_echo "#define DISABLE_LASTLOG 1" >>confdefs.h - printf "%s\n" "#define SSHD_ACQUIRES_CTTY 1" >>confdefs.h + $as_echo "#define SSHD_ACQUIRES_CTTY 1" >>confdefs.h -printf "%s\n" "#define BROKEN_SHADOW_EXPIRE 1" >>confdefs.h +$as_echo "#define BROKEN_SHADOW_EXPIRE 1" >>confdefs.h enable_etc_default_login=no # has incompatible /etc/default/login case "$host" in *-*-nto-qnx6*) - printf "%s\n" "#define DISABLE_FD_PASSING 1" >>confdefs.h + $as_echo "#define DISABLE_FD_PASSING 1" >>confdefs.h ;; esac @@ -10361,26 +9261,20 @@ *-*-ultrix*) -printf "%s\n" "#define BROKEN_GETGROUPS 1" >>confdefs.h - - -printf "%s\n" "#define NEED_SETPGRP 1" >>confdefs.h +$as_echo "#define BROKEN_GETGROUPS 1" >>confdefs.h + $as_echo "#define NEED_SETPGRP 1" >>confdefs.h -printf "%s\n" "#define HAVE_SYS_SYSLOG_H 1" >>confdefs.h +$as_echo "#define HAVE_SYS_SYSLOG_H 1" >>confdefs.h -printf "%s\n" "#define DISABLE_UTMPX 1" >>confdefs.h - - # DISABLE_FD_PASSING so that we call setpgrp as root, otherwise we - # don't get a controlling tty. - -printf "%s\n" "#define DISABLE_FD_PASSING 1" >>confdefs.h + ssh_disable_utmpx=yes + $as_echo "#define DISABLE_FD_PASSING 1" >>confdefs.h # On Ultrix some headers are not protected against multiple includes, # so we create wrappers and put it where the compiler will find it. - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: creating compat wrappers for headers" >&5 -printf "%s\n" "$as_me: WARNING: creating compat wrappers for headers" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: creating compat wrappers for headers" >&5 +$as_echo "$as_me: WARNING: creating compat wrappers for headers" >&2;} mkdir -p netinet for header in netinet/ip.h netdb.h resolv.h; do name=`echo $header | tr 'a-z/.' 'A-Z__'` @@ -10396,38 +9290,41 @@ *-*-lynxos) CFLAGS="$CFLAGS -D__NO_INCLUDE_WARN__" -printf "%s\n" "#define BROKEN_SETVBUF 1" >>confdefs.h +$as_echo "#define BROKEN_SETVBUF 1" >>confdefs.h ;; esac -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking compiler and flags for sanity" >&5 -printf %s "checking compiler and flags for sanity... " >&6; } -if test "$cross_compiling" = yes -then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: not checking compiler sanity" >&5 -printf "%s\n" "$as_me: WARNING: cross compiling: not checking compiler sanity" >&2;} +# let configure find us a capable shell +TEST_SHELL=$SHELL + -else $as_nop + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking compiler and flags for sanity" >&5 +$as_echo_n "checking compiler and flags for sanity... " >&6; } +if test "$cross_compiling" = yes; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: not checking compiler sanity" >&5 +$as_echo "$as_me: WARNING: cross compiling: not checking compiler sanity" >&2;} + +else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ - #include + int -main (void) +main () { - exit(0); + ; return 0; } _ACEOF -if ac_fn_c_try_run "$LINENO" -then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } -else $as_nop +if ac_fn_c_try_run "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } as_fn_error $? "*** compiler cannot create working executables, check config.log ***" "$LINENO" 5 fi @@ -10438,16 +9335,14 @@ # Checks for libraries. ac_fn_c_check_func "$LINENO" "setsockopt" "ac_cv_func_setsockopt" -if test "x$ac_cv_func_setsockopt" = xyes -then : +if test "x$ac_cv_func_setsockopt" = xyes; then : -else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for setsockopt in -lsocket" >&5 -printf %s "checking for setsockopt in -lsocket... " >&6; } -if test ${ac_cv_lib_socket_setsockopt+y} -then : - printf %s "(cached) " >&6 -else $as_nop +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for setsockopt in -lsocket" >&5 +$as_echo_n "checking for setsockopt in -lsocket... " >&6; } +if ${ac_cv_lib_socket_setsockopt+:} false; then : + $as_echo_n "(cached) " >&6 +else ac_check_lib_save_LIBS=$LIBS LIBS="-lsocket $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -10456,30 +9351,33 @@ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif char setsockopt (); int -main (void) +main () { return setsockopt (); ; return 0; } _ACEOF -if ac_fn_c_try_link "$LINENO" -then : +if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_socket_setsockopt=yes -else $as_nop +else ac_cv_lib_socket_setsockopt=no fi -rm -f core conftest.err conftest.$ac_objext conftest.beam \ +rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_socket_setsockopt" >&5 -printf "%s\n" "$ac_cv_lib_socket_setsockopt" >&6; } -if test "x$ac_cv_lib_socket_setsockopt" = xyes -then : - printf "%s\n" "#define HAVE_LIBSOCKET 1" >>confdefs.h +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_socket_setsockopt" >&5 +$as_echo "$ac_cv_lib_socket_setsockopt" >&6; } +if test "x$ac_cv_lib_socket_setsockopt" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBSOCKET 1 +_ACEOF LIBS="-lsocket $LIBS" @@ -10488,28 +9386,32 @@ fi - - for ac_func in dirname +for ac_func in dirname do : ac_fn_c_check_func "$LINENO" "dirname" "ac_cv_func_dirname" -if test "x$ac_cv_func_dirname" = xyes -then : - printf "%s\n" "#define HAVE_DIRNAME 1" >>confdefs.h - ac_fn_c_check_header_compile "$LINENO" "libgen.h" "ac_cv_header_libgen_h" "$ac_includes_default" -if test "x$ac_cv_header_libgen_h" = xyes -then : - printf "%s\n" "#define HAVE_LIBGEN_H 1" >>confdefs.h +if test "x$ac_cv_func_dirname" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_DIRNAME 1 +_ACEOF + for ac_header in libgen.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "libgen.h" "ac_cv_header_libgen_h" "$ac_includes_default" +if test "x$ac_cv_header_libgen_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBGEN_H 1 +_ACEOF fi -else $as_nop - - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for dirname in -lgen" >&5 -printf %s "checking for dirname in -lgen... " >&6; } -if test ${ac_cv_lib_gen_dirname+y} -then : - printf %s "(cached) " >&6 -else $as_nop +done + +else + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dirname in -lgen" >&5 +$as_echo_n "checking for dirname in -lgen... " >&6; } +if ${ac_cv_lib_gen_dirname+:} false; then : + $as_echo_n "(cached) " >&6 +else ac_check_lib_save_LIBS=$LIBS LIBS="-lgen $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -10518,67 +9420,66 @@ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif char dirname (); int -main (void) +main () { return dirname (); ; return 0; } _ACEOF -if ac_fn_c_try_link "$LINENO" -then : +if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_gen_dirname=yes -else $as_nop +else ac_cv_lib_gen_dirname=no fi -rm -f core conftest.err conftest.$ac_objext conftest.beam \ +rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_gen_dirname" >&5 -printf "%s\n" "$ac_cv_lib_gen_dirname" >&6; } -if test "x$ac_cv_lib_gen_dirname" = xyes -then : - - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for broken dirname" >&5 -printf %s "checking for broken dirname... " >&6; } -if test ${ac_cv_have_broken_dirname+y} -then : - printf %s "(cached) " >&6 -else $as_nop +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_gen_dirname" >&5 +$as_echo "$ac_cv_lib_gen_dirname" >&6; } +if test "x$ac_cv_lib_gen_dirname" = xyes; then : + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for broken dirname" >&5 +$as_echo_n "checking for broken dirname... " >&6; } +if ${ac_cv_have_broken_dirname+:} false; then : + $as_echo_n "(cached) " >&6 +else save_LIBS="$LIBS" LIBS="$LIBS -lgen" - if test "$cross_compiling" = yes -then : + if test "$cross_compiling" = yes; then : ac_cv_have_broken_dirname="no" -else $as_nop +else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include -#include -int main(int argc, char **argv) { +int +main () +{ + char *s, buf[32]; strncpy(buf,"/etc", 32); s = dirname(buf); - if (!s || strncmp(s, "/", 32) != 0) { - exit(1); - } else { - exit(0); - } -} + if (s == NULL || strncmp(s, "/", 32) != 0) + return 1; + ; + return 0; +} _ACEOF -if ac_fn_c_try_run "$LINENO" -then : +if ac_fn_c_try_run "$LINENO"; then : ac_cv_have_broken_dirname="no" -else $as_nop +else ac_cv_have_broken_dirname="yes" fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ @@ -10588,39 +9489,42 @@ LIBS="$save_LIBS" fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_broken_dirname" >&5 -printf "%s\n" "$ac_cv_have_broken_dirname" >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_broken_dirname" >&5 +$as_echo "$ac_cv_have_broken_dirname" >&6; } if test "x$ac_cv_have_broken_dirname" = "xno" ; then LIBS="$LIBS -lgen" - printf "%s\n" "#define HAVE_DIRNAME 1" >>confdefs.h + $as_echo "#define HAVE_DIRNAME 1" >>confdefs.h - ac_fn_c_check_header_compile "$LINENO" "libgen.h" "ac_cv_header_libgen_h" "$ac_includes_default" -if test "x$ac_cv_header_libgen_h" = xyes -then : - printf "%s\n" "#define HAVE_LIBGEN_H 1" >>confdefs.h + for ac_header in libgen.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "libgen.h" "ac_cv_header_libgen_h" "$ac_includes_default" +if test "x$ac_cv_header_libgen_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBGEN_H 1 +_ACEOF fi +done + fi fi fi - done + ac_fn_c_check_func "$LINENO" "getspnam" "ac_cv_func_getspnam" -if test "x$ac_cv_func_getspnam" = xyes -then : +if test "x$ac_cv_func_getspnam" = xyes; then : -else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for getspnam in -lgen" >&5 -printf %s "checking for getspnam in -lgen... " >&6; } -if test ${ac_cv_lib_gen_getspnam+y} -then : - printf %s "(cached) " >&6 -else $as_nop +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for getspnam in -lgen" >&5 +$as_echo_n "checking for getspnam in -lgen... " >&6; } +if ${ac_cv_lib_gen_getspnam+:} false; then : + $as_echo_n "(cached) " >&6 +else ac_check_lib_save_LIBS=$LIBS LIBS="-lgen $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -10629,40 +9533,40 @@ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif char getspnam (); int -main (void) +main () { return getspnam (); ; return 0; } _ACEOF -if ac_fn_c_try_link "$LINENO" -then : +if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_gen_getspnam=yes -else $as_nop +else ac_cv_lib_gen_getspnam=no fi -rm -f core conftest.err conftest.$ac_objext conftest.beam \ +rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_gen_getspnam" >&5 -printf "%s\n" "$ac_cv_lib_gen_getspnam" >&6; } -if test "x$ac_cv_lib_gen_getspnam" = xyes -then : +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_gen_getspnam" >&5 +$as_echo "$ac_cv_lib_gen_getspnam" >&6; } +if test "x$ac_cv_lib_gen_getspnam" = xyes; then : LIBS="$LIBS -lgen" fi fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for library containing basename" >&5 -printf %s "checking for library containing basename... " >&6; } -if test ${ac_cv_search_basename+y} -then : - printf %s "(cached) " >&6 -else $as_nop +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing basename" >&5 +$as_echo_n "checking for library containing basename... " >&6; } +if ${ac_cv_search_basename+:} false; then : + $as_echo_n "(cached) " >&6 +else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -10670,62 +9574,59 @@ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif char basename (); int -main (void) +main () { return basename (); ; return 0; } _ACEOF -for ac_lib in '' gen -do +for ac_lib in '' gen; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi - if ac_fn_c_try_link "$LINENO" -then : + if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_basename=$ac_res fi -rm -f core conftest.err conftest.$ac_objext conftest.beam \ +rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext - if test ${ac_cv_search_basename+y} -then : + if ${ac_cv_search_basename+:} false; then : break fi done -if test ${ac_cv_search_basename+y} -then : +if ${ac_cv_search_basename+:} false; then : -else $as_nop +else ac_cv_search_basename=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_basename" >&5 -printf "%s\n" "$ac_cv_search_basename" >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_basename" >&5 +$as_echo "$ac_cv_search_basename" >&6; } ac_res=$ac_cv_search_basename -if test "$ac_res" != no -then : +if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" -printf "%s\n" "#define HAVE_BASENAME 1" >>confdefs.h +$as_echo "#define HAVE_BASENAME 1" >>confdefs.h fi -zlib=yes +ZLIB_MSG=yes # Check whether --with-zlib was given. -if test ${with_zlib+y} -then : +if test "${with_zlib+set}" = set; then : withval=$with_zlib; if test "x$withval" = "xno" ; then - zlib=no + ZLIB_MSG=no elif test "x$withval" != "xyes"; then if test -d "$withval/lib"; then if test -n "${rpath_opt}"; then @@ -10750,35 +9651,30 @@ fi -# These libraries are needed for anything that links in the channel code. -CHANNELLIBS="" -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for zlib" >&5 -printf %s "checking for zlib... " >&6; } -if test "x${zlib}" = "xno"; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } -else - saved_LIBS="$LIBS" - CHANNELLIBS="$CHANNELLIBS -lz" - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } - -printf "%s\n" "#define WITH_ZLIB 1" >>confdefs.h - - ac_fn_c_check_header_compile "$LINENO" "zlib.h" "ac_cv_header_zlib_h" "$ac_includes_default" -if test "x$ac_cv_header_zlib_h" = xyes -then : +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for zlib" >&5 +$as_echo_n "checking for zlib... " >&6; } +if test "x$ZLIB_MSG" = "xno"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +$as_echo "#define WITH_ZLIB 1" >>confdefs.h -else $as_nop + ac_fn_c_check_header_mongrel "$LINENO" "zlib.h" "ac_cv_header_zlib_h" "$ac_includes_default" +if test "x$ac_cv_header_zlib_h" = xyes; then : + +else as_fn_error $? "*** zlib.h missing - please install first or check config.log ***" "$LINENO" 5 fi - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for deflate in -lz" >&5 -printf %s "checking for deflate in -lz... " >&6; } -if test ${ac_cv_lib_z_deflate+y} -then : - printf %s "(cached) " >&6 -else $as_nop + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for deflate in -lz" >&5 +$as_echo_n "checking for deflate in -lz... " >&6; } +if ${ac_cv_lib_z_deflate+:} false; then : + $as_echo_n "(cached) " >&6 +else ac_check_lib_save_LIBS=$LIBS LIBS="-lz $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -10787,69 +9683,76 @@ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif char deflate (); int -main (void) +main () { return deflate (); ; return 0; } _ACEOF -if ac_fn_c_try_link "$LINENO" -then : +if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_z_deflate=yes -else $as_nop +else ac_cv_lib_z_deflate=no fi -rm -f core conftest.err conftest.$ac_objext conftest.beam \ +rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_z_deflate" >&5 -printf "%s\n" "$ac_cv_lib_z_deflate" >&6; } -if test "x$ac_cv_lib_z_deflate" = xyes -then : - printf "%s\n" "#define HAVE_LIBZ 1" >>confdefs.h +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_z_deflate" >&5 +$as_echo "$ac_cv_lib_z_deflate" >&6; } +if test "x$ac_cv_lib_z_deflate" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBZ 1 +_ACEOF LIBS="-lz $LIBS" -else $as_nop +else saved_CPPFLAGS="$CPPFLAGS" saved_LDFLAGS="$LDFLAGS" + save_LIBS="$LIBS" if test -n "${rpath_opt}"; then LDFLAGS="-L/usr/local/lib ${rpath_opt}/usr/local/lib ${saved_LDFLAGS}" else LDFLAGS="-L/usr/local/lib ${saved_LDFLAGS}" fi CPPFLAGS="-I/usr/local/include ${saved_CPPFLAGS}" + LIBS="$LIBS -lz" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif char deflate (); int -main (void) +main () { return deflate (); ; return 0; } _ACEOF -if ac_fn_c_try_link "$LINENO" -then : - printf "%s\n" "#define HAVE_LIBZ 1" >>confdefs.h +if ac_fn_c_try_link "$LINENO"; then : + $as_echo "#define HAVE_LIBZ 1" >>confdefs.h -else $as_nop +else as_fn_error $? "*** zlib missing - please install first or check config.log ***" "$LINENO" 5 fi -rm -f core conftest.err conftest.$ac_objext conftest.beam \ +rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext @@ -10858,8 +9761,7 @@ # Check whether --with-zlib-version-check was given. -if test ${with_zlib_version_check+y} -then : +if test "${with_zlib_version_check+set}" = set; then : withval=$with_zlib_version_check; if test "x$withval" = "xno" ; then zlib_check_nonfatal=1 fi @@ -10868,53 +9770,48 @@ fi - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for possibly buggy zlib" >&5 -printf %s "checking for possibly buggy zlib... " >&6; } - if test "$cross_compiling" = yes -then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: not checking zlib version" >&5 -printf "%s\n" "$as_me: WARNING: cross compiling: not checking zlib version" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for possibly buggy zlib" >&5 +$as_echo_n "checking for possibly buggy zlib... " >&6; } + if test "$cross_compiling" = yes; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: not checking zlib version" >&5 +$as_echo "$as_me: WARNING: cross compiling: not checking zlib version" >&2;} -else $as_nop +else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include -#include #include int -main (void) +main () { int a=0, b=0, c=0, d=0, n, v; n = sscanf(ZLIB_VERSION, "%d.%d.%d.%d", &a, &b, &c, &d); - if (n != 3 && n != 4) - exit(1); + if (n < 1) + return 1; v = a*1000000 + b*10000 + c*100 + d; fprintf(stderr, "found zlib version %s (%d)\n", ZLIB_VERSION, v); /* 1.1.4 is OK */ if (a == 1 && b == 1 && c >= 4) - exit(0); + return 0; /* 1.2.3 and up are OK */ - if (v >= 1020300) - exit(0); - - exit(2); + if (v < 1020300) + return 2; ; return 0; } _ACEOF -if ac_fn_c_try_run "$LINENO" -then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } -else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } +if ac_fn_c_try_run "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } if test -z "$zlib_check_nonfatal" ; then as_fn_error $? "*** zlib too old - check config.log *** Your reported zlib version has known security problems. It's possible your @@ -10922,10 +9819,10 @@ are sure this is the case, you can disable the check by running \"./configure --without-zlib-version-check\". If you are in doubt, upgrade zlib to version 1.2.3 or greater. -See http://www.gzip.org/zlib/ for details." "$LINENO" 5 +See https://zlib.net/ for details." "$LINENO" 5 else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: zlib version may have security problems" >&5 -printf "%s\n" "$as_me: WARNING: zlib version may have security problems" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: zlib version may have security problems" >&5 +$as_echo "$as_me: WARNING: zlib version may have security problems" >&2;} fi fi @@ -10933,20 +9830,17 @@ conftest.$ac_objext conftest.beam conftest.$ac_ext fi - LIBS="$saved_LIBS" fi ac_fn_c_check_func "$LINENO" "strcasecmp" "ac_cv_func_strcasecmp" -if test "x$ac_cv_func_strcasecmp" = xyes -then : +if test "x$ac_cv_func_strcasecmp" = xyes; then : -else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for strcasecmp in -lresolv" >&5 -printf %s "checking for strcasecmp in -lresolv... " >&6; } -if test ${ac_cv_lib_resolv_strcasecmp+y} -then : - printf %s "(cached) " >&6 -else $as_nop +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for strcasecmp in -lresolv" >&5 +$as_echo_n "checking for strcasecmp in -lresolv... " >&6; } +if ${ac_cv_lib_resolv_strcasecmp+:} false; then : + $as_echo_n "(cached) " >&6 +else ac_check_lib_save_LIBS=$LIBS LIBS="-lresolv $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -10955,50 +9849,50 @@ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif char strcasecmp (); int -main (void) +main () { return strcasecmp (); ; return 0; } _ACEOF -if ac_fn_c_try_link "$LINENO" -then : +if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_resolv_strcasecmp=yes -else $as_nop +else ac_cv_lib_resolv_strcasecmp=no fi -rm -f core conftest.err conftest.$ac_objext conftest.beam \ +rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_resolv_strcasecmp" >&5 -printf "%s\n" "$ac_cv_lib_resolv_strcasecmp" >&6; } -if test "x$ac_cv_lib_resolv_strcasecmp" = xyes -then : +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_resolv_strcasecmp" >&5 +$as_echo "$ac_cv_lib_resolv_strcasecmp" >&6; } +if test "x$ac_cv_lib_resolv_strcasecmp" = xyes; then : LIBS="$LIBS -lresolv" fi fi - - for ac_func in utimes +for ac_func in utimes do : ac_fn_c_check_func "$LINENO" "utimes" "ac_cv_func_utimes" -if test "x$ac_cv_func_utimes" = xyes -then : - printf "%s\n" "#define HAVE_UTIMES 1" >>confdefs.h - -else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for utimes in -lc89" >&5 -printf %s "checking for utimes in -lc89... " >&6; } -if test ${ac_cv_lib_c89_utimes+y} -then : - printf %s "(cached) " >&6 -else $as_nop +if test "x$ac_cv_func_utimes" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_UTIMES 1 +_ACEOF + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for utimes in -lc89" >&5 +$as_echo_n "checking for utimes in -lc89... " >&6; } +if ${ac_cv_lib_c89_utimes+:} false; then : + $as_echo_n "(cached) " >&6 +else ac_check_lib_save_LIBS=$LIBS LIBS="-lc89 $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -11007,58 +9901,58 @@ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif char utimes (); int -main (void) +main () { return utimes (); ; return 0; } _ACEOF -if ac_fn_c_try_link "$LINENO" -then : +if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_c89_utimes=yes -else $as_nop +else ac_cv_lib_c89_utimes=no fi -rm -f core conftest.err conftest.$ac_objext conftest.beam \ +rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_c89_utimes" >&5 -printf "%s\n" "$ac_cv_lib_c89_utimes" >&6; } -if test "x$ac_cv_lib_c89_utimes" = xyes -then : - printf "%s\n" "#define HAVE_UTIMES 1" >>confdefs.h +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_c89_utimes" >&5 +$as_echo "$ac_cv_lib_c89_utimes" >&6; } +if test "x$ac_cv_lib_c89_utimes" = xyes; then : + $as_echo "#define HAVE_UTIMES 1" >>confdefs.h LIBS="$LIBS -lc89" fi fi - done -ac_fn_c_check_header_compile "$LINENO" "bsd/libutil.h" "ac_cv_header_bsd_libutil_h" "$ac_includes_default" -if test "x$ac_cv_header_bsd_libutil_h" = xyes -then : - printf "%s\n" "#define HAVE_BSD_LIBUTIL_H 1" >>confdefs.h -fi -ac_fn_c_check_header_compile "$LINENO" "libutil.h" "ac_cv_header_libutil_h" "$ac_includes_default" -if test "x$ac_cv_header_libutil_h" = xyes -then : - printf "%s\n" "#define HAVE_LIBUTIL_H 1" >>confdefs.h +for ac_header in bsd/libutil.h libutil.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for library containing fmt_scaled" >&5 -printf %s "checking for library containing fmt_scaled... " >&6; } -if test ${ac_cv_search_fmt_scaled+y} -then : - printf %s "(cached) " >&6 -else $as_nop +done + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing fmt_scaled" >&5 +$as_echo_n "checking for library containing fmt_scaled... " >&6; } +if ${ac_cv_search_fmt_scaled+:} false; then : + $as_echo_n "(cached) " >&6 +else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -11066,58 +9960,55 @@ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif char fmt_scaled (); int -main (void) +main () { return fmt_scaled (); ; return 0; } _ACEOF -for ac_lib in '' util bsd -do +for ac_lib in '' util bsd; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi - if ac_fn_c_try_link "$LINENO" -then : + if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_fmt_scaled=$ac_res fi -rm -f core conftest.err conftest.$ac_objext conftest.beam \ +rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext - if test ${ac_cv_search_fmt_scaled+y} -then : + if ${ac_cv_search_fmt_scaled+:} false; then : break fi done -if test ${ac_cv_search_fmt_scaled+y} -then : +if ${ac_cv_search_fmt_scaled+:} false; then : -else $as_nop +else ac_cv_search_fmt_scaled=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_fmt_scaled" >&5 -printf "%s\n" "$ac_cv_search_fmt_scaled" >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_fmt_scaled" >&5 +$as_echo "$ac_cv_search_fmt_scaled" >&6; } ac_res=$ac_cv_search_fmt_scaled -if test "$ac_res" != no -then : +if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for library containing scan_scaled" >&5 -printf %s "checking for library containing scan_scaled... " >&6; } -if test ${ac_cv_search_scan_scaled+y} -then : - printf %s "(cached) " >&6 -else $as_nop +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing scan_scaled" >&5 +$as_echo_n "checking for library containing scan_scaled... " >&6; } +if ${ac_cv_search_scan_scaled+:} false; then : + $as_echo_n "(cached) " >&6 +else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -11125,58 +10016,55 @@ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif char scan_scaled (); int -main (void) +main () { return scan_scaled (); ; return 0; } _ACEOF -for ac_lib in '' util bsd -do +for ac_lib in '' util bsd; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi - if ac_fn_c_try_link "$LINENO" -then : + if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_scan_scaled=$ac_res fi -rm -f core conftest.err conftest.$ac_objext conftest.beam \ +rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext - if test ${ac_cv_search_scan_scaled+y} -then : + if ${ac_cv_search_scan_scaled+:} false; then : break fi done -if test ${ac_cv_search_scan_scaled+y} -then : +if ${ac_cv_search_scan_scaled+:} false; then : -else $as_nop +else ac_cv_search_scan_scaled=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_scan_scaled" >&5 -printf "%s\n" "$ac_cv_search_scan_scaled" >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_scan_scaled" >&5 +$as_echo "$ac_cv_search_scan_scaled" >&6; } ac_res=$ac_cv_search_scan_scaled -if test "$ac_res" != no -then : +if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for library containing login" >&5 -printf %s "checking for library containing login... " >&6; } -if test ${ac_cv_search_login+y} -then : - printf %s "(cached) " >&6 -else $as_nop +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing login" >&5 +$as_echo_n "checking for library containing login... " >&6; } +if ${ac_cv_search_login+:} false; then : + $as_echo_n "(cached) " >&6 +else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -11184,58 +10072,55 @@ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif char login (); int -main (void) +main () { return login (); ; return 0; } _ACEOF -for ac_lib in '' util bsd -do +for ac_lib in '' util bsd; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi - if ac_fn_c_try_link "$LINENO" -then : + if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_login=$ac_res fi -rm -f core conftest.err conftest.$ac_objext conftest.beam \ +rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext - if test ${ac_cv_search_login+y} -then : + if ${ac_cv_search_login+:} false; then : break fi done -if test ${ac_cv_search_login+y} -then : +if ${ac_cv_search_login+:} false; then : -else $as_nop +else ac_cv_search_login=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_login" >&5 -printf "%s\n" "$ac_cv_search_login" >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_login" >&5 +$as_echo "$ac_cv_search_login" >&6; } ac_res=$ac_cv_search_login -if test "$ac_res" != no -then : +if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for library containing logout" >&5 -printf %s "checking for library containing logout... " >&6; } -if test ${ac_cv_search_logout+y} -then : - printf %s "(cached) " >&6 -else $as_nop +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing logout" >&5 +$as_echo_n "checking for library containing logout... " >&6; } +if ${ac_cv_search_logout+:} false; then : + $as_echo_n "(cached) " >&6 +else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -11243,58 +10128,55 @@ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif char logout (); int -main (void) +main () { return logout (); ; return 0; } _ACEOF -for ac_lib in '' util bsd -do +for ac_lib in '' util bsd; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi - if ac_fn_c_try_link "$LINENO" -then : + if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_logout=$ac_res fi -rm -f core conftest.err conftest.$ac_objext conftest.beam \ +rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext - if test ${ac_cv_search_logout+y} -then : + if ${ac_cv_search_logout+:} false; then : break fi done -if test ${ac_cv_search_logout+y} -then : +if ${ac_cv_search_logout+:} false; then : -else $as_nop +else ac_cv_search_logout=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_logout" >&5 -printf "%s\n" "$ac_cv_search_logout" >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_logout" >&5 +$as_echo "$ac_cv_search_logout" >&6; } ac_res=$ac_cv_search_logout -if test "$ac_res" != no -then : +if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for library containing logwtmp" >&5 -printf %s "checking for library containing logwtmp... " >&6; } -if test ${ac_cv_search_logwtmp+y} -then : - printf %s "(cached) " >&6 -else $as_nop +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing logwtmp" >&5 +$as_echo_n "checking for library containing logwtmp... " >&6; } +if ${ac_cv_search_logwtmp+:} false; then : + $as_echo_n "(cached) " >&6 +else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -11302,58 +10184,55 @@ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif char logwtmp (); int -main (void) +main () { return logwtmp (); ; return 0; } _ACEOF -for ac_lib in '' util bsd -do +for ac_lib in '' util bsd; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi - if ac_fn_c_try_link "$LINENO" -then : + if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_logwtmp=$ac_res fi -rm -f core conftest.err conftest.$ac_objext conftest.beam \ +rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext - if test ${ac_cv_search_logwtmp+y} -then : + if ${ac_cv_search_logwtmp+:} false; then : break fi done -if test ${ac_cv_search_logwtmp+y} -then : +if ${ac_cv_search_logwtmp+:} false; then : -else $as_nop +else ac_cv_search_logwtmp=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_logwtmp" >&5 -printf "%s\n" "$ac_cv_search_logwtmp" >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_logwtmp" >&5 +$as_echo "$ac_cv_search_logwtmp" >&6; } ac_res=$ac_cv_search_logwtmp -if test "$ac_res" != no -then : +if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for library containing openpty" >&5 -printf %s "checking for library containing openpty... " >&6; } -if test ${ac_cv_search_openpty+y} -then : - printf %s "(cached) " >&6 -else $as_nop +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing openpty" >&5 +$as_echo_n "checking for library containing openpty... " >&6; } +if ${ac_cv_search_openpty+:} false; then : + $as_echo_n "(cached) " >&6 +else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -11361,58 +10240,55 @@ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif char openpty (); int -main (void) +main () { return openpty (); ; return 0; } _ACEOF -for ac_lib in '' util bsd -do +for ac_lib in '' util bsd; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi - if ac_fn_c_try_link "$LINENO" -then : + if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_openpty=$ac_res fi -rm -f core conftest.err conftest.$ac_objext conftest.beam \ +rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext - if test ${ac_cv_search_openpty+y} -then : + if ${ac_cv_search_openpty+:} false; then : break fi done -if test ${ac_cv_search_openpty+y} -then : +if ${ac_cv_search_openpty+:} false; then : -else $as_nop +else ac_cv_search_openpty=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_openpty" >&5 -printf "%s\n" "$ac_cv_search_openpty" >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_openpty" >&5 +$as_echo "$ac_cv_search_openpty" >&6; } ac_res=$ac_cv_search_openpty -if test "$ac_res" != no -then : +if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for library containing updwtmp" >&5 -printf %s "checking for library containing updwtmp... " >&6; } -if test ${ac_cv_search_updwtmp+y} -then : - printf %s "(cached) " >&6 -else $as_nop +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing updwtmp" >&5 +$as_echo_n "checking for library containing updwtmp... " >&6; } +if ${ac_cv_search_updwtmp+:} false; then : + $as_echo_n "(cached) " >&6 +else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -11420,104 +10296,123 @@ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif char updwtmp (); int -main (void) +main () { return updwtmp (); ; return 0; } _ACEOF -for ac_lib in '' util bsd -do +for ac_lib in '' util bsd; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi - if ac_fn_c_try_link "$LINENO" -then : + if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_updwtmp=$ac_res fi -rm -f core conftest.err conftest.$ac_objext conftest.beam \ +rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext - if test ${ac_cv_search_updwtmp+y} -then : + if ${ac_cv_search_updwtmp+:} false; then : break fi done -if test ${ac_cv_search_updwtmp+y} -then : +if ${ac_cv_search_updwtmp+:} false; then : -else $as_nop +else ac_cv_search_updwtmp=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_updwtmp" >&5 -printf "%s\n" "$ac_cv_search_updwtmp" >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_updwtmp" >&5 +$as_echo "$ac_cv_search_updwtmp" >&6; } ac_res=$ac_cv_search_updwtmp -if test "$ac_res" != no -then : +if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" fi -ac_fn_c_check_func "$LINENO" "fmt_scaled" "ac_cv_func_fmt_scaled" -if test "x$ac_cv_func_fmt_scaled" = xyes -then : - printf "%s\n" "#define HAVE_FMT_SCALED 1" >>confdefs.h +for ac_func in fmt_scaled scan_scaled login logout openpty updwtmp logwtmp +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF fi -ac_fn_c_check_func "$LINENO" "scan_scaled" "ac_cv_func_scan_scaled" -if test "x$ac_cv_func_scan_scaled" = xyes -then : - printf "%s\n" "#define HAVE_SCAN_SCALED 1" >>confdefs.h +done -fi -ac_fn_c_check_func "$LINENO" "login" "ac_cv_func_login" -if test "x$ac_cv_func_login" = xyes -then : - printf "%s\n" "#define HAVE_LOGIN 1" >>confdefs.h -fi -ac_fn_c_check_func "$LINENO" "logout" "ac_cv_func_logout" -if test "x$ac_cv_func_logout" = xyes -then : - printf "%s\n" "#define HAVE_LOGOUT 1" >>confdefs.h +ssh_openpty_args=const +if test $ac_cv_func_openpty != no; then : -fi -ac_fn_c_check_func "$LINENO" "openpty" "ac_cv_func_openpty" -if test "x$ac_cv_func_openpty" = xyes -then : - printf "%s\n" "#define HAVE_OPENPTY 1" >>confdefs.h + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether openpty declare const arguments" >&5 +$as_echo_n "checking whether openpty declare const arguments... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ -fi -ac_fn_c_check_func "$LINENO" "updwtmp" "ac_cv_func_updwtmp" -if test "x$ac_cv_func_updwtmp" = xyes -then : - printf "%s\n" "#define HAVE_UPDWTMP 1" >>confdefs.h +#include +#include +#ifdef HAVE_PTY_H +# include +#endif +#ifdef HAVE_STDDEF_H +# include +#endif +int openpty( + int *amaster, int *aslave, char *name, + const struct termios *termp, const struct winsize *winp +) { +(void)amaster; (void)aslave; (void)name; +(void)termp; (void)winp; +return 0; } + +int +main () +{ + +int ptyfd = 1, ttyfd = 2; +(void)openpty(&ptyfd, &ttyfd, NULL, NULL, NULL); + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + ssh_openpty_args= fi -ac_fn_c_check_func "$LINENO" "logwtmp" "ac_cv_func_logwtmp" -if test "x$ac_cv_func_logwtmp" = xyes -then : - printf "%s\n" "#define HAVE_LOGWTMP 1" >>confdefs.h +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi +cat >>confdefs.h <<_ACEOF +#define OPENPTY_CONST_ARG $ssh_openpty_args +_ACEOF + # On some platforms, inet_ntop and gethostbyname may be found in libresolv # or libnsl. -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for library containing inet_ntop" >&5 -printf %s "checking for library containing inet_ntop... " >&6; } -if test ${ac_cv_search_inet_ntop+y} -then : - printf %s "(cached) " >&6 -else $as_nop +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing inet_ntop" >&5 +$as_echo_n "checking for library containing inet_ntop... " >&6; } +if ${ac_cv_search_inet_ntop+:} false; then : + $as_echo_n "(cached) " >&6 +else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -11525,58 +10420,55 @@ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif char inet_ntop (); int -main (void) +main () { return inet_ntop (); ; return 0; } _ACEOF -for ac_lib in '' resolv nsl -do +for ac_lib in '' resolv nsl; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi - if ac_fn_c_try_link "$LINENO" -then : + if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_inet_ntop=$ac_res fi -rm -f core conftest.err conftest.$ac_objext conftest.beam \ +rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext - if test ${ac_cv_search_inet_ntop+y} -then : + if ${ac_cv_search_inet_ntop+:} false; then : break fi done -if test ${ac_cv_search_inet_ntop+y} -then : +if ${ac_cv_search_inet_ntop+:} false; then : -else $as_nop +else ac_cv_search_inet_ntop=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_inet_ntop" >&5 -printf "%s\n" "$ac_cv_search_inet_ntop" >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_inet_ntop" >&5 +$as_echo "$ac_cv_search_inet_ntop" >&6; } ac_res=$ac_cv_search_inet_ntop -if test "$ac_res" != no -then : +if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for library containing gethostbyname" >&5 -printf %s "checking for library containing gethostbyname... " >&6; } -if test ${ac_cv_search_gethostbyname+y} -then : - printf %s "(cached) " >&6 -else $as_nop +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing gethostbyname" >&5 +$as_echo_n "checking for library containing gethostbyname... " >&6; } +if ${ac_cv_search_gethostbyname+:} false; then : + $as_echo_n "(cached) " >&6 +else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -11584,110 +10476,46 @@ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif char gethostbyname (); int -main (void) +main () { return gethostbyname (); ; return 0; } _ACEOF -for ac_lib in '' resolv nsl -do +for ac_lib in '' resolv nsl; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi - if ac_fn_c_try_link "$LINENO" -then : + if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_gethostbyname=$ac_res fi -rm -f core conftest.err conftest.$ac_objext conftest.beam \ +rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext - if test ${ac_cv_search_gethostbyname+y} -then : + if ${ac_cv_search_gethostbyname+:} false; then : break fi done -if test ${ac_cv_search_gethostbyname+y} -then : +if ${ac_cv_search_gethostbyname+:} false; then : -else $as_nop +else ac_cv_search_gethostbyname=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_gethostbyname" >&5 -printf "%s\n" "$ac_cv_search_gethostbyname" >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_gethostbyname" >&5 +$as_echo "$ac_cv_search_gethostbyname" >&6; } ac_res=$ac_cv_search_gethostbyname -if test "$ac_res" != no -then : - test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" - -fi - - -# Some Linux distribtions ship the BSD libc hashing functions in -# separate libraries. -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for library containing SHA256Update" >&5 -printf %s "checking for library containing SHA256Update... " >&6; } -if test ${ac_cv_search_SHA256Update+y} -then : - printf %s "(cached) " >&6 -else $as_nop - ac_func_search_save_LIBS=$LIBS -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -char SHA256Update (); -int -main (void) -{ -return SHA256Update (); - ; - return 0; -} -_ACEOF -for ac_lib in '' md bsd -do - if test -z "$ac_lib"; then - ac_res="none required" - else - ac_res=-l$ac_lib - LIBS="-l$ac_lib $ac_func_search_save_LIBS" - fi - if ac_fn_c_try_link "$LINENO" -then : - ac_cv_search_SHA256Update=$ac_res -fi -rm -f core conftest.err conftest.$ac_objext conftest.beam \ - conftest$ac_exeext - if test ${ac_cv_search_SHA256Update+y} -then : - break -fi -done -if test ${ac_cv_search_SHA256Update+y} -then : - -else $as_nop - ac_cv_search_SHA256Update=no -fi -rm conftest.$ac_ext -LIBS=$ac_func_search_save_LIBS -fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_SHA256Update" >&5 -printf "%s\n" "$ac_cv_search_SHA256Update" >&6; } -ac_res=$ac_cv_search_SHA256Update -if test "$ac_res" != no -then : +if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" fi @@ -11695,22 +10523,21 @@ # "Particular Function Checks" # see https://www.gnu.org/software/autoconf/manual/autoconf-2.69/html_node/Particular-Functions.html - - for ac_func in strftime +for ac_func in strftime do : ac_fn_c_check_func "$LINENO" "strftime" "ac_cv_func_strftime" -if test "x$ac_cv_func_strftime" = xyes -then : - printf "%s\n" "#define HAVE_STRFTIME 1" >>confdefs.h +if test "x$ac_cv_func_strftime" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_STRFTIME 1 +_ACEOF -else $as_nop +else # strftime is in -lintl on SCO UNIX. -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for strftime in -lintl" >&5 -printf %s "checking for strftime in -lintl... " >&6; } -if test ${ac_cv_lib_intl_strftime+y} -then : - printf %s "(cached) " >&6 -else $as_nop +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for strftime in -lintl" >&5 +$as_echo_n "checking for strftime in -lintl... " >&6; } +if ${ac_cv_lib_intl_strftime+:} false; then : + $as_echo_n "(cached) " >&6 +else ac_check_lib_save_LIBS=$LIBS LIBS="-lintl $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -11719,73 +10546,77 @@ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif char strftime (); int -main (void) +main () { return strftime (); ; return 0; } _ACEOF -if ac_fn_c_try_link "$LINENO" -then : +if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_intl_strftime=yes -else $as_nop +else ac_cv_lib_intl_strftime=no fi -rm -f core conftest.err conftest.$ac_objext conftest.beam \ +rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_intl_strftime" >&5 -printf "%s\n" "$ac_cv_lib_intl_strftime" >&6; } -if test "x$ac_cv_lib_intl_strftime" = xyes -then : - printf "%s\n" "#define HAVE_STRFTIME 1" >>confdefs.h +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_intl_strftime" >&5 +$as_echo "$ac_cv_lib_intl_strftime" >&6; } +if test "x$ac_cv_lib_intl_strftime" = xyes; then : + $as_echo "#define HAVE_STRFTIME 1" >>confdefs.h LIBS="-lintl $LIBS" fi fi +done + +for ac_header in stdlib.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "stdlib.h" "ac_cv_header_stdlib_h" "$ac_includes_default" +if test "x$ac_cv_header_stdlib_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_STDLIB_H 1 +_ACEOF + +fi done -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for GNU libc compatible malloc" >&5 -printf %s "checking for GNU libc compatible malloc... " >&6; } -if test ${ac_cv_func_malloc_0_nonnull+y} -then : - printf %s "(cached) " >&6 -else $as_nop - if test "$cross_compiling" = yes -then : - case "$host_os" in # (( - # Guess yes on platforms where we know the result. - *-gnu* | freebsd* | netbsd* | openbsd* | bitrig* \ - | hpux* | solaris* | cygwin* | mingw* | msys* ) - ac_cv_func_malloc_0_nonnull=yes ;; - # If we don't know, assume the worst. - *) ac_cv_func_malloc_0_nonnull=no ;; - esac -else $as_nop + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU libc compatible malloc" >&5 +$as_echo_n "checking for GNU libc compatible malloc... " >&6; } +if ${ac_cv_func_malloc_0_nonnull+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "$cross_compiling" = yes; then : + ac_cv_func_malloc_0_nonnull=no +else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -#include +#if defined STDC_HEADERS || defined HAVE_STDLIB_H +# include +#else +char *malloc (); +#endif int -main (void) +main () { -void *p = malloc (0); - int result = !p; - free (p); - return result; +return ! malloc (0); ; return 0; } _ACEOF -if ac_fn_c_try_run "$LINENO" -then : +if ac_fn_c_try_run "$LINENO"; then : ac_cv_func_malloc_0_nonnull=yes -else $as_nop +else ac_cv_func_malloc_0_nonnull=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ @@ -11793,15 +10624,14 @@ fi fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_malloc_0_nonnull" >&5 -printf "%s\n" "$ac_cv_func_malloc_0_nonnull" >&6; } -if test $ac_cv_func_malloc_0_nonnull = yes -then : +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_malloc_0_nonnull" >&5 +$as_echo "$ac_cv_func_malloc_0_nonnull" >&6; } +if test $ac_cv_func_malloc_0_nonnull = yes; then : -printf "%s\n" "#define HAVE_MALLOC 1" >>confdefs.h +$as_echo "#define HAVE_MALLOC 1" >>confdefs.h -else $as_nop - printf "%s\n" "#define HAVE_MALLOC 0" >>confdefs.h +else + $as_echo "#define HAVE_MALLOC 0" >>confdefs.h case " $LIBOBJS " in *" malloc.$ac_objext "* ) ;; @@ -11810,47 +10640,50 @@ esac -printf "%s\n" "#define malloc rpl_malloc" >>confdefs.h +$as_echo "#define malloc rpl_malloc" >>confdefs.h fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for GNU libc compatible realloc" >&5 -printf %s "checking for GNU libc compatible realloc... " >&6; } -if test ${ac_cv_func_realloc_0_nonnull+y} -then : - printf %s "(cached) " >&6 -else $as_nop - if test "$cross_compiling" = yes -then : - case "$host_os" in # (( - # Guess yes on platforms where we know the result. - *-gnu* | freebsd* | netbsd* | openbsd* | bitrig* \ - | hpux* | solaris* | cygwin* | mingw* | msys* ) - ac_cv_func_realloc_0_nonnull=yes ;; - # If we don't know, assume the worst. - *) ac_cv_func_realloc_0_nonnull=no ;; - esac -else $as_nop +for ac_header in stdlib.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "stdlib.h" "ac_cv_header_stdlib_h" "$ac_includes_default" +if test "x$ac_cv_header_stdlib_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_STDLIB_H 1 +_ACEOF + +fi + +done + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU libc compatible realloc" >&5 +$as_echo_n "checking for GNU libc compatible realloc... " >&6; } +if ${ac_cv_func_realloc_0_nonnull+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "$cross_compiling" = yes; then : + ac_cv_func_realloc_0_nonnull=no +else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -#include +#if defined STDC_HEADERS || defined HAVE_STDLIB_H +# include +#else +char *realloc (); +#endif int -main (void) +main () { -void *p = realloc (0, 0); - int result = !p; - free (p); - return result; +return ! realloc (0, 0); ; return 0; } _ACEOF -if ac_fn_c_try_run "$LINENO" -then : +if ac_fn_c_try_run "$LINENO"; then : ac_cv_func_realloc_0_nonnull=yes -else $as_nop +else ac_cv_func_realloc_0_nonnull=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ @@ -11858,15 +10691,14 @@ fi fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_realloc_0_nonnull" >&5 -printf "%s\n" "$ac_cv_func_realloc_0_nonnull" >&6; } -if test $ac_cv_func_realloc_0_nonnull = yes -then : +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_realloc_0_nonnull" >&5 +$as_echo "$ac_cv_func_realloc_0_nonnull" >&6; } +if test $ac_cv_func_realloc_0_nonnull = yes; then : -printf "%s\n" "#define HAVE_REALLOC 1" >>confdefs.h +$as_echo "#define HAVE_REALLOC 1" >>confdefs.h -else $as_nop - printf "%s\n" "#define HAVE_REALLOC 0" >>confdefs.h +else + $as_echo "#define HAVE_REALLOC 0" >>confdefs.h case " $LIBOBJS " in *" realloc.$ac_objext "* ) ;; @@ -11875,63 +10707,74 @@ esac -printf "%s\n" "#define realloc rpl_realloc" >>confdefs.h +$as_echo "#define realloc rpl_realloc" >>confdefs.h fi # autoconf doesn't have AC_FUNC_CALLOC so fake it if malloc returns NULL; -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if calloc(0, N) returns non-null" >&5 -printf %s "checking if calloc(0, N) returns non-null... " >&6; } -if test "$cross_compiling" = yes -then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: assuming same as malloc" >&5 -printf "%s\n" "$as_me: WARNING: cross compiling: assuming same as malloc" >&2;} - func_calloc_0_nonnull="$ac_cv_func_malloc_0_nonnull" +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if calloc(0, N) returns non-null" >&5 +$as_echo_n "checking if calloc(0, N) returns non-null... " >&6; } +if ${ssh_cv_func_calloc_0_nonnull+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "$cross_compiling" = yes; then : + ssh_cv_func_calloc_0_nonnull=cross -else $as_nop +else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ - #include + +#include + int -main (void) +main () { - void *p = calloc(0, 1); exit(p == NULL); + + void *p = calloc(0, 1); + if (p == NULL) return 1; ; return 0; } _ACEOF -if ac_fn_c_try_run "$LINENO" -then : - func_calloc_0_nonnull=yes -else $as_nop - func_calloc_0_nonnull=no +if ac_fn_c_try_run "$LINENO"; then : + ssh_cv_func_calloc_0_nonnull=yes +else + ssh_cv_func_calloc_0_nonnull=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $func_calloc_0_nonnull" >&5 -printf "%s\n" "$func_calloc_0_nonnull" >&6; } -if test "x$func_calloc_0_nonnull" = "xyes"; then +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ssh_cv_func_calloc_0_nonnull" >&5 +$as_echo "$ssh_cv_func_calloc_0_nonnull" >&6; } +if test $ssh_cv_func_calloc_0_nonnull = cross ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: assuming calloc(0, N) returns non-null same as malloc" >&5 +$as_echo "$as_me: WARNING: cross compiling: assuming calloc(0, N) returns non-null same as malloc" >&2;} + ssh_cv_func_calloc_0_nonnull=$ac_cv_func_malloc_0_nonnull +fi +if test $ssh_cv_func_calloc_0_nonnull = yes; then : + + +$as_echo "#define HAVE_CALLOC 1" >>confdefs.h -printf "%s\n" "#define HAVE_CALLOC 1" >>confdefs.h else -printf "%s\n" "#define HAVE_CALLOC 0" >>confdefs.h + $as_echo "#define HAVE_CALLOC 0" >>confdefs.h -printf "%s\n" "#define calloc rpl_calloc" >>confdefs.h +$as_echo "#define calloc rpl_calloc" >>confdefs.h + fi # Check for ALTDIRFUNC glob() extension -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for GLOB_ALTDIRFUNC support" >&5 -printf %s "checking for GLOB_ALTDIRFUNC support... " >&6; } - +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for GLOB_ALTDIRFUNC support" >&5 +$as_echo_n "checking for GLOB_ALTDIRFUNC support... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -11942,64 +10785,65 @@ _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - $EGREP "FOUNDIT" >/dev/null 2>&1 -then : + $EGREP "FOUNDIT" >/dev/null 2>&1; then : -printf "%s\n" "#define GLOB_HAS_ALTDIRFUNC 1" >>confdefs.h +$as_echo "#define GLOB_HAS_ALTDIRFUNC 1" >>confdefs.h - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } -else $as_nop +else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } fi -rm -rf conftest* +rm -f conftest* # Check for g.gl_matchc glob() extension -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for gl_matchc field in glob_t" >&5 -printf %s "checking for gl_matchc field in glob_t... " >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for gl_matchc field in glob_t" >&5 +$as_echo_n "checking for gl_matchc field in glob_t... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int -main (void) +main () { glob_t g; g.gl_matchc = 1; ; return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO" -then : +if ac_fn_c_try_compile "$LINENO"; then : -printf "%s\n" "#define GLOB_HAS_GL_MATCHC 1" >>confdefs.h +$as_echo "#define GLOB_HAS_GL_MATCHC 1" >>confdefs.h - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } -else $as_nop +else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext # Check for g.gl_statv glob() extension -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for gl_statv and GLOB_KEEPSTAT extensions for glob" >&5 -printf %s "checking for gl_statv and GLOB_KEEPSTAT extensions for glob... " >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for gl_statv and GLOB_KEEPSTAT extensions for glob" >&5 +$as_echo_n "checking for gl_statv and GLOB_KEEPSTAT extensions for glob... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ - #include + +#include +#include + int -main (void) +main () { #ifndef GLOB_KEEPSTAT @@ -12012,296 +10856,278 @@ return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO" -then : +if ac_fn_c_try_compile "$LINENO"; then : -printf "%s\n" "#define GLOB_HAS_GL_STATV 1" >>confdefs.h +$as_echo "#define GLOB_HAS_GL_STATV 1" >>confdefs.h - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } -else $as_nop +else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -ac_fn_check_decl "$LINENO" "GLOB_NOMATCH" "ac_cv_have_decl_GLOB_NOMATCH" "#include -" "$ac_c_undeclared_builtin_options" "CFLAGS" -if test "x$ac_cv_have_decl_GLOB_NOMATCH" = xyes -then : +ac_fn_c_check_decl "$LINENO" "GLOB_NOMATCH" "ac_cv_have_decl_GLOB_NOMATCH" "#include +" +if test "x$ac_cv_have_decl_GLOB_NOMATCH" = xyes; then : ac_have_decl=1 -else $as_nop +else ac_have_decl=0 fi -printf "%s\n" "#define HAVE_DECL_GLOB_NOMATCH $ac_have_decl" >>confdefs.h + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_GLOB_NOMATCH $ac_have_decl +_ACEOF -ac_fn_check_decl "$LINENO" "VIS_ALL" "ac_cv_have_decl_VIS_ALL" "#include -" "$ac_c_undeclared_builtin_options" "CFLAGS" -if test "x$ac_cv_have_decl_VIS_ALL" = xyes -then : +ac_fn_c_check_decl "$LINENO" "VIS_ALL" "ac_cv_have_decl_VIS_ALL" "#include +" +if test "x$ac_cv_have_decl_VIS_ALL" = xyes; then : -else $as_nop +else -printf "%s\n" "#define BROKEN_STRNVIS 1" >>confdefs.h +$as_echo "#define BROKEN_STRNVIS 1" >>confdefs.h fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether struct dirent allocates space for d_name" >&5 -printf %s "checking whether struct dirent allocates space for d_name... " >&6; } -if test "$cross_compiling" = yes -then : - - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: assuming BROKEN_ONE_BYTE_DIRENT_D_NAME" >&5 -printf "%s\n" "$as_me: WARNING: cross compiling: assuming BROKEN_ONE_BYTE_DIRENT_D_NAME" >&2;} - printf "%s\n" "#define BROKEN_ONE_BYTE_DIRENT_D_NAME 1" >>confdefs.h +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether struct dirent allocates space for d_name" >&5 +$as_echo_n "checking whether struct dirent allocates space for d_name... " >&6; } +if ${ssh_cv_dirent_allocates_space_for_d_name+:} false; then : + $as_echo_n "(cached) " >&6 +else +if test "$cross_compiling" = yes; then : + ssh_cv_dirent_allocates_space_for_d_name=cross -else $as_nop +else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include -#include - int -main (void) +main () { struct dirent d; - exit(sizeof(d.d_name)<=sizeof(char)); + if (sizeof(d.d_name) <= sizeof(char)) + return 1; ; return 0; } _ACEOF -if ac_fn_c_try_run "$LINENO" -then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } -else $as_nop - - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } - -printf "%s\n" "#define BROKEN_ONE_BYTE_DIRENT_D_NAME 1" >>confdefs.h - - +if ac_fn_c_try_run "$LINENO"; then : + ssh_cv_dirent_allocates_space_for_d_name=yes +else + ssh_cv_dirent_allocates_space_for_d_name=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for /proc/pid/fd directory" >&5 -printf %s "checking for /proc/pid/fd directory... " >&6; } +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ssh_cv_dirent_allocates_space_for_d_name" >&5 +$as_echo "$ssh_cv_dirent_allocates_space_for_d_name" >&6; } +case $ssh_cv_dirent_allocates_space_for_d_name in + no) + $as_echo "#define BROKEN_ONE_BYTE_DIRENT_D_NAME 1" >>confdefs.h + + ;; + cross) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: assuming BROKEN_ONE_BYTE_DIRENT_D_NAME" >&5 +$as_echo "$as_me: WARNING: cross compiling: assuming BROKEN_ONE_BYTE_DIRENT_D_NAME" >&2;} + $as_echo "#define BROKEN_ONE_BYTE_DIRENT_D_NAME 1" >>confdefs.h + + ;; +esac + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for /proc/pid/fd directory" >&5 +$as_echo_n "checking for /proc/pid/fd directory... " >&6; } if test -d "/proc/$$/fd" ; then -printf "%s\n" "#define HAVE_PROC_PID 1" >>confdefs.h +$as_echo "#define HAVE_PROC_PID 1" >>confdefs.h - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } fi -# Check whether user wants to use ldns -LDNS_MSG="no" +# Check whether user wants TCP wrappers support +TCPW_MSG="no" -# Check whether --with-ldns was given. -if test ${with_ldns+y} -then : - withval=$with_ldns; - ldns="" - if test "x$withval" = "xyes" ; then - if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}ldns-config", so it can be a program name with args. -set dummy ${ac_tool_prefix}ldns-config; ac_word=$2 -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -printf %s "checking for $ac_word... " >&6; } -if test ${ac_cv_path_LDNSCONFIG+y} -then : - printf %s "(cached) " >&6 -else $as_nop - case $LDNSCONFIG in - [\\/]* | ?:[\\/]*) - ac_cv_path_LDNSCONFIG="$LDNSCONFIG" # Let the user override the test with a path. - ;; - *) - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - case $as_dir in #((( - '') as_dir=./ ;; - */) ;; - *) as_dir=$as_dir/ ;; - esac - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then - ac_cv_path_LDNSCONFIG="$as_dir$ac_word$ac_exec_ext" - printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS +# Check whether --with-tcp-wrappers was given. +if test "${with_tcp_wrappers+set}" = set; then : + withval=$with_tcp_wrappers; if test "x$withval" != "xno"; then : - ;; -esac -fi -LDNSCONFIG=$ac_cv_path_LDNSCONFIG -if test -n "$LDNSCONFIG"; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $LDNSCONFIG" >&5 -printf "%s\n" "$LDNSCONFIG" >&6; } -else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } -fi + saved_LIBS="$LIBS" + saved_LDFLAGS="$LDFLAGS" + saved_CPPFLAGS="$CPPFLAGS" + if test -n "${withval}" && \ + test "x${withval}" != "xyes"; then : -fi -if test -z "$ac_cv_path_LDNSCONFIG"; then - ac_pt_LDNSCONFIG=$LDNSCONFIG - # Extract the first word of "ldns-config", so it can be a program name with args. -set dummy ldns-config; ac_word=$2 -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -printf %s "checking for $ac_word... " >&6; } -if test ${ac_cv_path_ac_pt_LDNSCONFIG+y} -then : - printf %s "(cached) " >&6 -else $as_nop - case $ac_pt_LDNSCONFIG in - [\\/]* | ?:[\\/]*) - ac_cv_path_ac_pt_LDNSCONFIG="$ac_pt_LDNSCONFIG" # Let the user override the test with a path. - ;; - *) - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - case $as_dir in #((( - '') as_dir=./ ;; - */) ;; - *) as_dir=$as_dir/ ;; - esac - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then - ac_cv_path_ac_pt_LDNSCONFIG="$as_dir$ac_word$ac_exec_ext" - printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS + if test -d "${withval}/lib"; then : + + if test -n "${need_dash_r}"; then + LDFLAGS="-L${withval}/lib -R${withval}/lib ${LDFLAGS}" + else + LDFLAGS="-L${withval}/lib ${LDFLAGS}" + fi - ;; -esac -fi -ac_pt_LDNSCONFIG=$ac_cv_path_ac_pt_LDNSCONFIG -if test -n "$ac_pt_LDNSCONFIG"; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_pt_LDNSCONFIG" >&5 -printf "%s\n" "$ac_pt_LDNSCONFIG" >&6; } else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + + if test -n "${need_dash_r}"; then + LDFLAGS="-L${withval} -R${withval} ${LDFLAGS}" + else + LDFLAGS="-L${withval} ${LDFLAGS}" + fi + fi + if test -d "${withval}/include"; then : + + CPPFLAGS="-I${withval}/include ${CPPFLAGS}" - if test "x$ac_pt_LDNSCONFIG" = x; then - LDNSCONFIG="no" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} -ac_tool_warned=yes ;; -esac - LDNSCONFIG=$ac_pt_LDNSCONFIG - fi else - LDNSCONFIG="$ac_cv_path_LDNSCONFIG" + + CPPFLAGS="-I${withval} ${CPPFLAGS}" + +fi + +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to link with wrap library" >&5 +$as_echo_n "checking how to link with wrap library... " >&6; } + # libwrap may require libnsl + for WRAPLIBS in "-lwrap" "-lwrap -lnsl"; do + LIBS="$WRAPLIBS $saved_LIBS" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include +#include +#include +#include +int deny_severity = 0, allow_severity = 0; +int +main () +{ + + hosts_access(0); + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + + TCPW_MSG=yes + fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + test $TCPW_MSG = yes && break + done + + if test $TCPW_MSG = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $WRAPLIBS" >&5 +$as_echo "$WRAPLIBS" >&6; } - if test "x$LDNSCONFIG" = "xno"; then - LIBS="-lldns $LIBS" - ldns=yes +$as_echo "#define LIBWRAP 1" >>confdefs.h + + SSHDLIBS="$SSHDLIBS $WRAPLIBS" else - LIBS="$LIBS `$LDNSCONFIG --libs`" - CPPFLAGS="$CPPFLAGS `$LDNSCONFIG --cflags`" - ldns=yes + as_fn_error $? "cannot link" "$LINENO" 5 fi - elif test "x$withval" != "xno" ; then - CPPFLAGS="$CPPFLAGS -I${withval}/include" - LDFLAGS="$LDFLAGS -L${withval}/lib" - LIBS="-lldns $LIBS" - ldns=yes - fi - # Verify that it works. - if test "x$ldns" = "xyes" ; then + LIBS="$saved_LIBS" + +fi + +fi -printf "%s\n" "#define HAVE_LDNS 1" >>confdefs.h +# Check whether user wants to use ldns +LDNS_MSG="no" + +# Check whether --with-ldns was given. +if test "${with_ldns+set}" = set; then : + withval=$with_ldns; + if test "x$withval" != "xno" ; then + if test "x$withval" != "xyes" ; then + CPPFLAGS="$CPPFLAGS -I$withval/include" + LDFLAGS="$LDFLAGS -L$withval/lib" + fi + LIBS="-lldns $LIBS" LDNS_MSG="yes" - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ldns support" >&5 -printf %s "checking for ldns support... " >&6; } - cat confdefs.h - <<_ACEOF >conftest.$ac_ext + fi + +fi + +# Verify that ldns works. +if test "x$LDNS_MSG" = "xyes" ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ldns support" >&5 +$as_echo_n "checking for ldns support... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -#include -#include -#ifdef HAVE_STDINT_H -# include -#endif #include -int main(void) { ldns_status status = ldns_verify_trusted(NULL, NULL, NULL, NULL); status=LDNS_STATUS_OK; exit(0); } +int +main () +{ + + ldns_status status = ldns_verify_trusted(NULL, NULL, NULL, NULL); + status = LDNS_STATUS_OK; + ; + return 0; +} _ACEOF -if ac_fn_c_try_link "$LINENO" -then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } -else $as_nop +if ac_fn_c_try_link "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } - as_fn_error $? "** Incomplete or missing ldns libraries." "$LINENO" 5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + as_fn_error $? "** Incomplete or missing ldns libraries." "$LINENO" 5 fi -rm -f core conftest.err conftest.$ac_objext conftest.beam \ +rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext - fi -fi +$as_echo "#define HAVE_LDNS 1" >>confdefs.h +fi # Check whether user wants libedit support LIBEDIT_MSG="no" # Check whether --with-libedit was given. -if test ${with_libedit+y} -then : +if test "${with_libedit+set}" = set; then : withval=$with_libedit; if test "x$withval" != "xno" ; then if test "x$withval" = "xyes" ; then if test "x$PKGCONFIG" != "xno"; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $PKGCONFIG knows about libedit" >&5 -printf %s "checking if $PKGCONFIG knows about libedit... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $PKGCONFIG knows about libedit" >&5 +$as_echo_n "checking if $PKGCONFIG knows about libedit... " >&6; } if "$PKGCONFIG" libedit; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } use_pkgconfig_for_libedit=yes else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } fi fi else @@ -12319,12 +11145,11 @@ LIBEDIT="-ledit -lcurses" fi OTHERLIBS=`echo $LIBEDIT | sed 's/-ledit//'` - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for el_init in -ledit" >&5 -printf %s "checking for el_init in -ledit... " >&6; } -if test ${ac_cv_lib_edit_el_init+y} -then : - printf %s "(cached) " >&6 -else $as_nop + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for el_init in -ledit" >&5 +$as_echo_n "checking for el_init in -ledit... " >&6; } +if ${ac_cv_lib_edit_el_init+:} false; then : + $as_echo_n "(cached) " >&6 +else ac_check_lib_save_LIBS=$LIBS LIBS="-ledit $OTHERLIBS $LIBS" @@ -12334,70 +11159,68 @@ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif char el_init (); int -main (void) +main () { return el_init (); ; return 0; } _ACEOF -if ac_fn_c_try_link "$LINENO" -then : +if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_edit_el_init=yes -else $as_nop +else ac_cv_lib_edit_el_init=no fi -rm -f core conftest.err conftest.$ac_objext conftest.beam \ +rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_edit_el_init" >&5 -printf "%s\n" "$ac_cv_lib_edit_el_init" >&6; } -if test "x$ac_cv_lib_edit_el_init" = xyes -then : +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_edit_el_init" >&5 +$as_echo "$ac_cv_lib_edit_el_init" >&6; } +if test "x$ac_cv_lib_edit_el_init" = xyes; then : -printf "%s\n" "#define USE_LIBEDIT 1" >>confdefs.h +$as_echo "#define USE_LIBEDIT 1" >>confdefs.h LIBEDIT_MSG="yes" -else $as_nop +else as_fn_error $? "libedit not found" "$LINENO" 5 fi - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if libedit version is compatible" >&5 -printf %s "checking if libedit version is compatible... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if libedit version is compatible" >&5 +$as_echo_n "checking if libedit version is compatible... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include -#include int -main (void) +main () { int i = H_SETSIZE; el_init("", NULL, NULL, NULL); - exit(0); ; return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO" -then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } -else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } +if ac_fn_c_try_compile "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } as_fn_error $? "libedit version is not compatible" "$LINENO" 5 fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi fi @@ -12406,17 +11229,16 @@ AUDIT_MODULE=none # Check whether --with-audit was given. -if test ${with_audit+y} -then : +if test "${with_audit+set}" = set; then : withval=$with_audit; - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for supported audit module" >&5 -printf %s "checking for supported audit module... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for supported audit module" >&5 +$as_echo_n "checking for supported audit module... " >&6; } case "$withval" in bsm) - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: bsm" >&5 -printf "%s\n" "bsm" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: bsm" >&5 +$as_echo "bsm" >&6; } AUDIT_MODULE=bsm - for ac_header in bsm/audit.h + for ac_header in bsm/audit.h do : ac_fn_c_check_header_compile "$LINENO" "bsm/audit.h" "ac_cv_header_bsm_audit_h" " #ifdef HAVE_TIME_H @@ -12425,21 +11247,22 @@ " -if test "x$ac_cv_header_bsm_audit_h" = xyes -then : - printf "%s\n" "#define HAVE_BSM_AUDIT_H 1" >>confdefs.h +if test "x$ac_cv_header_bsm_audit_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_BSM_AUDIT_H 1 +_ACEOF -else $as_nop +else as_fn_error $? "BSM enabled and bsm/audit.h not found" "$LINENO" 5 fi done - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for getaudit in -lbsm" >&5 -printf %s "checking for getaudit in -lbsm... " >&6; } -if test ${ac_cv_lib_bsm_getaudit+y} -then : - printf %s "(cached) " >&6 -else $as_nop + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for getaudit in -lbsm" >&5 +$as_echo_n "checking for getaudit in -lbsm... " >&6; } +if ${ac_cv_lib_bsm_getaudit+:} false; then : + $as_echo_n "(cached) " >&6 +else ac_check_lib_save_LIBS=$LIBS LIBS="-lbsm $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -12448,101 +11271,108 @@ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif char getaudit (); int -main (void) +main () { return getaudit (); ; return 0; } _ACEOF -if ac_fn_c_try_link "$LINENO" -then : +if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_bsm_getaudit=yes -else $as_nop +else ac_cv_lib_bsm_getaudit=no fi -rm -f core conftest.err conftest.$ac_objext conftest.beam \ +rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_bsm_getaudit" >&5 -printf "%s\n" "$ac_cv_lib_bsm_getaudit" >&6; } -if test "x$ac_cv_lib_bsm_getaudit" = xyes -then : - printf "%s\n" "#define HAVE_LIBBSM 1" >>confdefs.h +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_bsm_getaudit" >&5 +$as_echo "$ac_cv_lib_bsm_getaudit" >&6; } +if test "x$ac_cv_lib_bsm_getaudit" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBBSM 1 +_ACEOF LIBS="-lbsm $LIBS" -else $as_nop +else as_fn_error $? "BSM enabled and required library not found" "$LINENO" 5 fi - - for ac_func in getaudit + for ac_func in getaudit do : ac_fn_c_check_func "$LINENO" "getaudit" "ac_cv_func_getaudit" -if test "x$ac_cv_func_getaudit" = xyes -then : - printf "%s\n" "#define HAVE_GETAUDIT 1" >>confdefs.h +if test "x$ac_cv_func_getaudit" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_GETAUDIT 1 +_ACEOF -else $as_nop +else as_fn_error $? "BSM enabled and required function not found" "$LINENO" 5 fi - done - # These are optional - ac_fn_c_check_func "$LINENO" "getaudit_addr" "ac_cv_func_getaudit_addr" -if test "x$ac_cv_func_getaudit_addr" = xyes -then : - printf "%s\n" "#define HAVE_GETAUDIT_ADDR 1" >>confdefs.h -fi -ac_fn_c_check_func "$LINENO" "aug_get_machine" "ac_cv_func_aug_get_machine" -if test "x$ac_cv_func_aug_get_machine" = xyes -then : - printf "%s\n" "#define HAVE_AUG_GET_MACHINE 1" >>confdefs.h + # These are optional + for ac_func in getaudit_addr aug_get_machine +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF fi +done -printf "%s\n" "#define USE_BSM_AUDIT 1" >>confdefs.h +$as_echo "#define USE_BSM_AUDIT 1" >>confdefs.h if test "$sol2ver" -ge 11; then SSHDLIBS="$SSHDLIBS -lscf" -printf "%s\n" "#define BROKEN_BSM_API 1" >>confdefs.h +$as_echo "#define BROKEN_BSM_API 1" >>confdefs.h fi ;; linux) - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: linux" >&5 -printf "%s\n" "linux" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: linux" >&5 +$as_echo "linux" >&6; } AUDIT_MODULE=linux - ac_fn_c_check_header_compile "$LINENO" "libaudit.h" "ac_cv_header_libaudit_h" "$ac_includes_default" -if test "x$ac_cv_header_libaudit_h" = xyes -then : - printf "%s\n" "#define HAVE_LIBAUDIT_H 1" >>confdefs.h + for ac_header in libaudit.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "libaudit.h" "ac_cv_header_libaudit_h" "$ac_includes_default" +if test "x$ac_cv_header_libaudit_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBAUDIT_H 1 +_ACEOF fi +done + SSHDLIBS="$SSHDLIBS -laudit" -printf "%s\n" "#define USE_LINUX_AUDIT 1" >>confdefs.h +$as_echo "#define USE_LINUX_AUDIT 1" >>confdefs.h ;; debug) AUDIT_MODULE=debug - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: debug" >&5 -printf "%s\n" "debug" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: debug" >&5 +$as_echo "debug" >&6; } -printf "%s\n" "#define SSH_AUDIT_EVENTS 1" >>confdefs.h +$as_echo "#define SSH_AUDIT_EVENTS 1" >>confdefs.h ;; no) - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } ;; *) as_fn_error $? "Unknown audit module $withval" "$LINENO" 5 @@ -12554,8 +11384,7 @@ # Check whether --with-pie was given. -if test ${with_pie+y} -then : +if test "${with_pie+set}" = set; then : withval=$with_pie; if test "x$withval" = "xno"; then use_pie=no @@ -12570,14 +11399,14 @@ if test "x$use_pie" = "x"; then use_pie=no fi -if test "x$use_toolchain_hardening" != "x1" && test "x$use_pie" = "xauto"; then +if $use_toolchain_hardening && test "x$use_pie" = "xauto"; then # Turn off automatic PIE when toolchain hardening is off. use_pie=no fi if test "x$use_pie" = "xauto"; then # Automatic PIE requires gcc >= 4.x - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for gcc >= 4.x" >&5 -printf %s "checking for gcc >= 4.x... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gcc >= 4.x" >&5 +$as_echo_n "checking for gcc >= 4.x... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -12586,24 +11415,23 @@ #endif _ACEOF -if ac_fn_c_try_compile "$LINENO" -then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } -else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } +if ac_fn_c_try_compile "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } use_pie=no fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi if test "x$use_pie" != "xno"; then SAVED_CFLAGS="$CFLAGS" SAVED_LDFLAGS="$LDFLAGS" { - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -fPIE" >&5 -printf %s "checking if $CC supports compile flag -fPIE... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -fPIE" >&5 +$as_echo_n "checking if $CC supports compile flag -fPIE... " >&6; } saved_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $WERROR -fPIE" _define_flag="" @@ -12611,57 +11439,49 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ + #include #include -/* Trivial function to help test for -fzero-call-used-regs */ -void f(int n) {} -int main(int argc, char **argv) { - (void)argv; +/* Trivial function to help test for flags like -fzero-call-used-regs. +Note compiler does not inform whether this option is supported unless it +runs into the situation where it would need to emit corresponding code.*/ +static int f(int n) {return n;} +int main(int argc, char *argv[]) { /* Some math to catch -ftrapv problems in the toolchain */ int i = 123 * argc, j = 456 + argc, k = 789 - argc; float l = i * 2.1; double m = l / 0.5; long long int n = argc * 12345LL, o = 12345LL * (long long int)argc; - f(0); - printf("%d %d %d %f %f %lld %lld\n", i, j, k, l, m, n, o); - /* - * Test fallthrough behaviour. clang 10's -Wimplicit-fallthrough does - * not understand comments and we don't use the "fallthrough" attribute - * that it's looking for. - */ - switch(i){ - case 0: j += i; - /* FALLTHROUGH */ - default: j += k; - } - exit(0); + long long int p = n * o; + printf("%d %d %d %f %f %lld %lld %lld %d\n", i, j, k, l, m, n, o, p, f(0)); + (void)argv; + return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO" -then : +if ac_fn_c_try_compile "$LINENO"; then : -if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null +if $EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } CFLAGS="$saved_CFLAGS" else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } CFLAGS="$saved_CFLAGS $_define_flag" fi -else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } CFLAGS="$saved_CFLAGS" fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext } { - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $LD supports link flag -pie" >&5 -printf %s "checking if $LD supports link flag -pie... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $LD supports link flag -pie" >&5 +$as_echo_n "checking if $LD supports link flag -pie... " >&6; } saved_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS $WERROR -pie" _define_flag="" @@ -12669,1008 +11489,317 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ + #include #include -int main(int argc, char **argv) { - (void)argv; +/* Trivial function to help test for flags like -fzero-call-used-regs. +Note compiler does not inform whether this option is supported unless it +runs into the situation where it would need to emit corresponding code.*/ +static int f(int n) {return n;} +int main(int argc, char *argv[]) { /* Some math to catch -ftrapv problems in the toolchain */ int i = 123 * argc, j = 456 + argc, k = 789 - argc; float l = i * 2.1; double m = l / 0.5; long long int n = argc * 12345LL, o = 12345LL * (long long int)argc; - long long p = n * o; - printf("%d %d %d %f %f %lld %lld %lld\n", i, j, k, l, m, n, o, p); - exit(0); + long long int p = n * o; + printf("%d %d %d %f %f %lld %lld %lld %d\n", i, j, k, l, m, n, o, p, f(0)); + (void)argv; + return 0; } _ACEOF -if ac_fn_c_try_link "$LINENO" -then : +if ac_fn_c_try_link "$LINENO"; then : -if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null +if $EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } LDFLAGS="$saved_LDFLAGS" else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } LDFLAGS="$saved_LDFLAGS $_define_flag" fi -else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } LDFLAGS="$saved_LDFLAGS" fi -rm -f core conftest.err conftest.$ac_objext conftest.beam \ +rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext } # We use both -fPIE and -pie or neither. - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether both -fPIE and -pie are supported" >&5 -printf %s "checking whether both -fPIE and -pie are supported... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether both -fPIE and -pie are supported" >&5 +$as_echo_n "checking whether both -fPIE and -pie are supported... " >&6; } if echo "x $CFLAGS" | grep ' -fPIE' >/dev/null 2>&1 && \ echo "x $LDFLAGS" | grep ' -pie' >/dev/null 2>&1 ; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } CFLAGS="$SAVED_CFLAGS" LDFLAGS="$SAVED_LDFLAGS" fi fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether -fPIC is accepted" >&5 -printf %s "checking whether -fPIC is accepted... " >&6; } -SAVED_CFLAGS="$CFLAGS" -CFLAGS="$CFLAGS -fPIC" -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - #include -int -main (void) -{ - exit(0); - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO" -then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } - PICFLAG="-fPIC"; -else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } - PICFLAG=""; -fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext -CFLAGS="$SAVED_CFLAGS" - - -ac_fn_c_check_func "$LINENO" "Blowfish_initstate" "ac_cv_func_Blowfish_initstate" -if test "x$ac_cv_func_Blowfish_initstate" = xyes -then : - printf "%s\n" "#define HAVE_BLOWFISH_INITSTATE 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "Blowfish_expandstate" "ac_cv_func_Blowfish_expandstate" -if test "x$ac_cv_func_Blowfish_expandstate" = xyes -then : - printf "%s\n" "#define HAVE_BLOWFISH_EXPANDSTATE 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "Blowfish_expand0state" "ac_cv_func_Blowfish_expand0state" -if test "x$ac_cv_func_Blowfish_expand0state" = xyes -then : - printf "%s\n" "#define HAVE_BLOWFISH_EXPAND0STATE 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "Blowfish_stream2word" "ac_cv_func_Blowfish_stream2word" -if test "x$ac_cv_func_Blowfish_stream2word" = xyes -then : - printf "%s\n" "#define HAVE_BLOWFISH_STREAM2WORD 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "SHA256Update" "ac_cv_func_SHA256Update" -if test "x$ac_cv_func_SHA256Update" = xyes -then : - printf "%s\n" "#define HAVE_SHA256UPDATE 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "SHA384Update" "ac_cv_func_SHA384Update" -if test "x$ac_cv_func_SHA384Update" = xyes -then : - printf "%s\n" "#define HAVE_SHA384UPDATE 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "SHA512Update" "ac_cv_func_SHA512Update" -if test "x$ac_cv_func_SHA512Update" = xyes -then : - printf "%s\n" "#define HAVE_SHA512UPDATE 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "asprintf" "ac_cv_func_asprintf" -if test "x$ac_cv_func_asprintf" = xyes -then : - printf "%s\n" "#define HAVE_ASPRINTF 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "b64_ntop" "ac_cv_func_b64_ntop" -if test "x$ac_cv_func_b64_ntop" = xyes -then : - printf "%s\n" "#define HAVE_B64_NTOP 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "__b64_ntop" "ac_cv_func___b64_ntop" -if test "x$ac_cv_func___b64_ntop" = xyes -then : - printf "%s\n" "#define HAVE___B64_NTOP 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "b64_pton" "ac_cv_func_b64_pton" -if test "x$ac_cv_func_b64_pton" = xyes -then : - printf "%s\n" "#define HAVE_B64_PTON 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "__b64_pton" "ac_cv_func___b64_pton" -if test "x$ac_cv_func___b64_pton" = xyes -then : - printf "%s\n" "#define HAVE___B64_PTON 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "bcopy" "ac_cv_func_bcopy" -if test "x$ac_cv_func_bcopy" = xyes -then : - printf "%s\n" "#define HAVE_BCOPY 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "bcrypt_pbkdf" "ac_cv_func_bcrypt_pbkdf" -if test "x$ac_cv_func_bcrypt_pbkdf" = xyes -then : - printf "%s\n" "#define HAVE_BCRYPT_PBKDF 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "bindresvport_sa" "ac_cv_func_bindresvport_sa" -if test "x$ac_cv_func_bindresvport_sa" = xyes -then : - printf "%s\n" "#define HAVE_BINDRESVPORT_SA 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "blf_enc" "ac_cv_func_blf_enc" -if test "x$ac_cv_func_blf_enc" = xyes -then : - printf "%s\n" "#define HAVE_BLF_ENC 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "bzero" "ac_cv_func_bzero" -if test "x$ac_cv_func_bzero" = xyes -then : - printf "%s\n" "#define HAVE_BZERO 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "cap_rights_limit" "ac_cv_func_cap_rights_limit" -if test "x$ac_cv_func_cap_rights_limit" = xyes -then : - printf "%s\n" "#define HAVE_CAP_RIGHTS_LIMIT 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "clock" "ac_cv_func_clock" -if test "x$ac_cv_func_clock" = xyes -then : - printf "%s\n" "#define HAVE_CLOCK 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "closefrom" "ac_cv_func_closefrom" -if test "x$ac_cv_func_closefrom" = xyes -then : - printf "%s\n" "#define HAVE_CLOSEFROM 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "close_range" "ac_cv_func_close_range" -if test "x$ac_cv_func_close_range" = xyes -then : - printf "%s\n" "#define HAVE_CLOSE_RANGE 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "dirfd" "ac_cv_func_dirfd" -if test "x$ac_cv_func_dirfd" = xyes -then : - printf "%s\n" "#define HAVE_DIRFD 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "endgrent" "ac_cv_func_endgrent" -if test "x$ac_cv_func_endgrent" = xyes -then : - printf "%s\n" "#define HAVE_ENDGRENT 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "err" "ac_cv_func_err" -if test "x$ac_cv_func_err" = xyes -then : - printf "%s\n" "#define HAVE_ERR 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "errx" "ac_cv_func_errx" -if test "x$ac_cv_func_errx" = xyes -then : - printf "%s\n" "#define HAVE_ERRX 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "explicit_bzero" "ac_cv_func_explicit_bzero" -if test "x$ac_cv_func_explicit_bzero" = xyes -then : - printf "%s\n" "#define HAVE_EXPLICIT_BZERO 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "explicit_memset" "ac_cv_func_explicit_memset" -if test "x$ac_cv_func_explicit_memset" = xyes -then : - printf "%s\n" "#define HAVE_EXPLICIT_MEMSET 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "fchmod" "ac_cv_func_fchmod" -if test "x$ac_cv_func_fchmod" = xyes -then : - printf "%s\n" "#define HAVE_FCHMOD 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "fchmodat" "ac_cv_func_fchmodat" -if test "x$ac_cv_func_fchmodat" = xyes -then : - printf "%s\n" "#define HAVE_FCHMODAT 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "fchown" "ac_cv_func_fchown" -if test "x$ac_cv_func_fchown" = xyes -then : - printf "%s\n" "#define HAVE_FCHOWN 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "fchownat" "ac_cv_func_fchownat" -if test "x$ac_cv_func_fchownat" = xyes -then : - printf "%s\n" "#define HAVE_FCHOWNAT 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "flock" "ac_cv_func_flock" -if test "x$ac_cv_func_flock" = xyes -then : - printf "%s\n" "#define HAVE_FLOCK 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "fnmatch" "ac_cv_func_fnmatch" -if test "x$ac_cv_func_fnmatch" = xyes -then : - printf "%s\n" "#define HAVE_FNMATCH 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "freeaddrinfo" "ac_cv_func_freeaddrinfo" -if test "x$ac_cv_func_freeaddrinfo" = xyes -then : - printf "%s\n" "#define HAVE_FREEADDRINFO 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "freezero" "ac_cv_func_freezero" -if test "x$ac_cv_func_freezero" = xyes -then : - printf "%s\n" "#define HAVE_FREEZERO 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "fstatfs" "ac_cv_func_fstatfs" -if test "x$ac_cv_func_fstatfs" = xyes -then : - printf "%s\n" "#define HAVE_FSTATFS 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "fstatvfs" "ac_cv_func_fstatvfs" -if test "x$ac_cv_func_fstatvfs" = xyes -then : - printf "%s\n" "#define HAVE_FSTATVFS 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "futimes" "ac_cv_func_futimes" -if test "x$ac_cv_func_futimes" = xyes -then : - printf "%s\n" "#define HAVE_FUTIMES 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "getaddrinfo" "ac_cv_func_getaddrinfo" -if test "x$ac_cv_func_getaddrinfo" = xyes -then : - printf "%s\n" "#define HAVE_GETADDRINFO 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "getcwd" "ac_cv_func_getcwd" -if test "x$ac_cv_func_getcwd" = xyes -then : - printf "%s\n" "#define HAVE_GETCWD 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "getentropy" "ac_cv_func_getentropy" -if test "x$ac_cv_func_getentropy" = xyes -then : - printf "%s\n" "#define HAVE_GETENTROPY 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "getgrouplist" "ac_cv_func_getgrouplist" -if test "x$ac_cv_func_getgrouplist" = xyes -then : - printf "%s\n" "#define HAVE_GETGROUPLIST 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "getline" "ac_cv_func_getline" -if test "x$ac_cv_func_getline" = xyes -then : - printf "%s\n" "#define HAVE_GETLINE 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "getnameinfo" "ac_cv_func_getnameinfo" -if test "x$ac_cv_func_getnameinfo" = xyes -then : - printf "%s\n" "#define HAVE_GETNAMEINFO 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "getopt" "ac_cv_func_getopt" -if test "x$ac_cv_func_getopt" = xyes -then : - printf "%s\n" "#define HAVE_GETOPT 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "getpagesize" "ac_cv_func_getpagesize" -if test "x$ac_cv_func_getpagesize" = xyes -then : - printf "%s\n" "#define HAVE_GETPAGESIZE 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "getpeereid" "ac_cv_func_getpeereid" -if test "x$ac_cv_func_getpeereid" = xyes -then : - printf "%s\n" "#define HAVE_GETPEEREID 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "getpeerucred" "ac_cv_func_getpeerucred" -if test "x$ac_cv_func_getpeerucred" = xyes -then : - printf "%s\n" "#define HAVE_GETPEERUCRED 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "getpgid" "ac_cv_func_getpgid" -if test "x$ac_cv_func_getpgid" = xyes -then : - printf "%s\n" "#define HAVE_GETPGID 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "_getpty" "ac_cv_func__getpty" -if test "x$ac_cv_func__getpty" = xyes -then : - printf "%s\n" "#define HAVE__GETPTY 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "getrlimit" "ac_cv_func_getrlimit" -if test "x$ac_cv_func_getrlimit" = xyes -then : - printf "%s\n" "#define HAVE_GETRLIMIT 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "getrandom" "ac_cv_func_getrandom" -if test "x$ac_cv_func_getrandom" = xyes -then : - printf "%s\n" "#define HAVE_GETRANDOM 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "getsid" "ac_cv_func_getsid" -if test "x$ac_cv_func_getsid" = xyes -then : - printf "%s\n" "#define HAVE_GETSID 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "getttyent" "ac_cv_func_getttyent" -if test "x$ac_cv_func_getttyent" = xyes -then : - printf "%s\n" "#define HAVE_GETTTYENT 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "glob" "ac_cv_func_glob" -if test "x$ac_cv_func_glob" = xyes -then : - printf "%s\n" "#define HAVE_GLOB 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "group_from_gid" "ac_cv_func_group_from_gid" -if test "x$ac_cv_func_group_from_gid" = xyes -then : - printf "%s\n" "#define HAVE_GROUP_FROM_GID 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "inet_aton" "ac_cv_func_inet_aton" -if test "x$ac_cv_func_inet_aton" = xyes -then : - printf "%s\n" "#define HAVE_INET_ATON 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "inet_ntoa" "ac_cv_func_inet_ntoa" -if test "x$ac_cv_func_inet_ntoa" = xyes -then : - printf "%s\n" "#define HAVE_INET_NTOA 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "inet_ntop" "ac_cv_func_inet_ntop" -if test "x$ac_cv_func_inet_ntop" = xyes -then : - printf "%s\n" "#define HAVE_INET_NTOP 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "innetgr" "ac_cv_func_innetgr" -if test "x$ac_cv_func_innetgr" = xyes -then : - printf "%s\n" "#define HAVE_INNETGR 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "killpg" "ac_cv_func_killpg" -if test "x$ac_cv_func_killpg" = xyes -then : - printf "%s\n" "#define HAVE_KILLPG 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "llabs" "ac_cv_func_llabs" -if test "x$ac_cv_func_llabs" = xyes -then : - printf "%s\n" "#define HAVE_LLABS 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "localtime_r" "ac_cv_func_localtime_r" -if test "x$ac_cv_func_localtime_r" = xyes -then : - printf "%s\n" "#define HAVE_LOCALTIME_R 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "login_getcapbool" "ac_cv_func_login_getcapbool" -if test "x$ac_cv_func_login_getcapbool" = xyes -then : - printf "%s\n" "#define HAVE_LOGIN_GETCAPBOOL 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "login_getpwclass" "ac_cv_func_login_getpwclass" -if test "x$ac_cv_func_login_getpwclass" = xyes -then : - printf "%s\n" "#define HAVE_LOGIN_GETPWCLASS 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "memmem" "ac_cv_func_memmem" -if test "x$ac_cv_func_memmem" = xyes -then : - printf "%s\n" "#define HAVE_MEMMEM 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "memmove" "ac_cv_func_memmove" -if test "x$ac_cv_func_memmove" = xyes -then : - printf "%s\n" "#define HAVE_MEMMOVE 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "memset_s" "ac_cv_func_memset_s" -if test "x$ac_cv_func_memset_s" = xyes -then : - printf "%s\n" "#define HAVE_MEMSET_S 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "mkdtemp" "ac_cv_func_mkdtemp" -if test "x$ac_cv_func_mkdtemp" = xyes -then : - printf "%s\n" "#define HAVE_MKDTEMP 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "ngetaddrinfo" "ac_cv_func_ngetaddrinfo" -if test "x$ac_cv_func_ngetaddrinfo" = xyes -then : - printf "%s\n" "#define HAVE_NGETADDRINFO 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "nsleep" "ac_cv_func_nsleep" -if test "x$ac_cv_func_nsleep" = xyes -then : - printf "%s\n" "#define HAVE_NSLEEP 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "ogetaddrinfo" "ac_cv_func_ogetaddrinfo" -if test "x$ac_cv_func_ogetaddrinfo" = xyes -then : - printf "%s\n" "#define HAVE_OGETADDRINFO 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "openlog_r" "ac_cv_func_openlog_r" -if test "x$ac_cv_func_openlog_r" = xyes -then : - printf "%s\n" "#define HAVE_OPENLOG_R 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "pledge" "ac_cv_func_pledge" -if test "x$ac_cv_func_pledge" = xyes -then : - printf "%s\n" "#define HAVE_PLEDGE 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "poll" "ac_cv_func_poll" -if test "x$ac_cv_func_poll" = xyes -then : - printf "%s\n" "#define HAVE_POLL 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "ppoll" "ac_cv_func_ppoll" -if test "x$ac_cv_func_ppoll" = xyes -then : - printf "%s\n" "#define HAVE_PPOLL 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "prctl" "ac_cv_func_prctl" -if test "x$ac_cv_func_prctl" = xyes -then : - printf "%s\n" "#define HAVE_PRCTL 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "procctl" "ac_cv_func_procctl" -if test "x$ac_cv_func_procctl" = xyes -then : - printf "%s\n" "#define HAVE_PROCCTL 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "pselect" "ac_cv_func_pselect" -if test "x$ac_cv_func_pselect" = xyes -then : - printf "%s\n" "#define HAVE_PSELECT 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "pstat" "ac_cv_func_pstat" -if test "x$ac_cv_func_pstat" = xyes -then : - printf "%s\n" "#define HAVE_PSTAT 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "raise" "ac_cv_func_raise" -if test "x$ac_cv_func_raise" = xyes -then : - printf "%s\n" "#define HAVE_RAISE 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "readpassphrase" "ac_cv_func_readpassphrase" -if test "x$ac_cv_func_readpassphrase" = xyes -then : - printf "%s\n" "#define HAVE_READPASSPHRASE 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "reallocarray" "ac_cv_func_reallocarray" -if test "x$ac_cv_func_reallocarray" = xyes -then : - printf "%s\n" "#define HAVE_REALLOCARRAY 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "realpath" "ac_cv_func_realpath" -if test "x$ac_cv_func_realpath" = xyes -then : - printf "%s\n" "#define HAVE_REALPATH 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "recvmsg" "ac_cv_func_recvmsg" -if test "x$ac_cv_func_recvmsg" = xyes -then : - printf "%s\n" "#define HAVE_RECVMSG 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "recallocarray" "ac_cv_func_recallocarray" -if test "x$ac_cv_func_recallocarray" = xyes -then : - printf "%s\n" "#define HAVE_RECALLOCARRAY 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "rresvport_af" "ac_cv_func_rresvport_af" -if test "x$ac_cv_func_rresvport_af" = xyes -then : - printf "%s\n" "#define HAVE_RRESVPORT_AF 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "sendmsg" "ac_cv_func_sendmsg" -if test "x$ac_cv_func_sendmsg" = xyes -then : - printf "%s\n" "#define HAVE_SENDMSG 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "setdtablesize" "ac_cv_func_setdtablesize" -if test "x$ac_cv_func_setdtablesize" = xyes -then : - printf "%s\n" "#define HAVE_SETDTABLESIZE 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "setegid" "ac_cv_func_setegid" -if test "x$ac_cv_func_setegid" = xyes -then : - printf "%s\n" "#define HAVE_SETEGID 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "setenv" "ac_cv_func_setenv" -if test "x$ac_cv_func_setenv" = xyes -then : - printf "%s\n" "#define HAVE_SETENV 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "seteuid" "ac_cv_func_seteuid" -if test "x$ac_cv_func_seteuid" = xyes -then : - printf "%s\n" "#define HAVE_SETEUID 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "setgroupent" "ac_cv_func_setgroupent" -if test "x$ac_cv_func_setgroupent" = xyes -then : - printf "%s\n" "#define HAVE_SETGROUPENT 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "setgroups" "ac_cv_func_setgroups" -if test "x$ac_cv_func_setgroups" = xyes -then : - printf "%s\n" "#define HAVE_SETGROUPS 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "setlinebuf" "ac_cv_func_setlinebuf" -if test "x$ac_cv_func_setlinebuf" = xyes -then : - printf "%s\n" "#define HAVE_SETLINEBUF 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "setlogin" "ac_cv_func_setlogin" -if test "x$ac_cv_func_setlogin" = xyes -then : - printf "%s\n" "#define HAVE_SETLOGIN 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "setpassent" "ac_cv_func_setpassent" -if test "x$ac_cv_func_setpassent" = xyes -then : - printf "%s\n" "#define HAVE_SETPASSENT 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "setpcred" "ac_cv_func_setpcred" -if test "x$ac_cv_func_setpcred" = xyes -then : - printf "%s\n" "#define HAVE_SETPCRED 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "setproctitle" "ac_cv_func_setproctitle" -if test "x$ac_cv_func_setproctitle" = xyes -then : - printf "%s\n" "#define HAVE_SETPROCTITLE 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "setregid" "ac_cv_func_setregid" -if test "x$ac_cv_func_setregid" = xyes -then : - printf "%s\n" "#define HAVE_SETREGID 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "setreuid" "ac_cv_func_setreuid" -if test "x$ac_cv_func_setreuid" = xyes -then : - printf "%s\n" "#define HAVE_SETREUID 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "setrlimit" "ac_cv_func_setrlimit" -if test "x$ac_cv_func_setrlimit" = xyes -then : - printf "%s\n" "#define HAVE_SETRLIMIT 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "setsid" "ac_cv_func_setsid" -if test "x$ac_cv_func_setsid" = xyes -then : - printf "%s\n" "#define HAVE_SETSID 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "setvbuf" "ac_cv_func_setvbuf" -if test "x$ac_cv_func_setvbuf" = xyes -then : - printf "%s\n" "#define HAVE_SETVBUF 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "sigaction" "ac_cv_func_sigaction" -if test "x$ac_cv_func_sigaction" = xyes -then : - printf "%s\n" "#define HAVE_SIGACTION 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "sigvec" "ac_cv_func_sigvec" -if test "x$ac_cv_func_sigvec" = xyes -then : - printf "%s\n" "#define HAVE_SIGVEC 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "snprintf" "ac_cv_func_snprintf" -if test "x$ac_cv_func_snprintf" = xyes -then : - printf "%s\n" "#define HAVE_SNPRINTF 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "socketpair" "ac_cv_func_socketpair" -if test "x$ac_cv_func_socketpair" = xyes -then : - printf "%s\n" "#define HAVE_SOCKETPAIR 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "statfs" "ac_cv_func_statfs" -if test "x$ac_cv_func_statfs" = xyes -then : - printf "%s\n" "#define HAVE_STATFS 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "statvfs" "ac_cv_func_statvfs" -if test "x$ac_cv_func_statvfs" = xyes -then : - printf "%s\n" "#define HAVE_STATVFS 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "strcasestr" "ac_cv_func_strcasestr" -if test "x$ac_cv_func_strcasestr" = xyes -then : - printf "%s\n" "#define HAVE_STRCASESTR 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "strdup" "ac_cv_func_strdup" -if test "x$ac_cv_func_strdup" = xyes -then : - printf "%s\n" "#define HAVE_STRDUP 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "strerror" "ac_cv_func_strerror" -if test "x$ac_cv_func_strerror" = xyes -then : - printf "%s\n" "#define HAVE_STRERROR 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "strlcat" "ac_cv_func_strlcat" -if test "x$ac_cv_func_strlcat" = xyes -then : - printf "%s\n" "#define HAVE_STRLCAT 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "strlcpy" "ac_cv_func_strlcpy" -if test "x$ac_cv_func_strlcpy" = xyes -then : - printf "%s\n" "#define HAVE_STRLCPY 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "strmode" "ac_cv_func_strmode" -if test "x$ac_cv_func_strmode" = xyes -then : - printf "%s\n" "#define HAVE_STRMODE 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "strndup" "ac_cv_func_strndup" -if test "x$ac_cv_func_strndup" = xyes -then : - printf "%s\n" "#define HAVE_STRNDUP 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "strnlen" "ac_cv_func_strnlen" -if test "x$ac_cv_func_strnlen" = xyes -then : - printf "%s\n" "#define HAVE_STRNLEN 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "strnvis" "ac_cv_func_strnvis" -if test "x$ac_cv_func_strnvis" = xyes -then : - printf "%s\n" "#define HAVE_STRNVIS 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "strptime" "ac_cv_func_strptime" -if test "x$ac_cv_func_strptime" = xyes -then : - printf "%s\n" "#define HAVE_STRPTIME 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "strsignal" "ac_cv_func_strsignal" -if test "x$ac_cv_func_strsignal" = xyes -then : - printf "%s\n" "#define HAVE_STRSIGNAL 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "strtonum" "ac_cv_func_strtonum" -if test "x$ac_cv_func_strtonum" = xyes -then : - printf "%s\n" "#define HAVE_STRTONUM 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "strtoll" "ac_cv_func_strtoll" -if test "x$ac_cv_func_strtoll" = xyes -then : - printf "%s\n" "#define HAVE_STRTOLL 1" >>confdefs.h +for ac_func in \ + Blowfish_initstate \ + Blowfish_expandstate \ + Blowfish_expand0state \ + Blowfish_stream2word \ + SHA256Update \ + SHA384Update \ + SHA512Update \ + asprintf \ + b64_ntop \ + __b64_ntop \ + b64_pton \ + __b64_pton \ + bcrypt_pbkdf \ + bindresvport_sa \ + blf_enc \ + cap_rights_limit \ + clock \ + closefrom \ + close_range \ + dirfd \ + endgrent \ + err \ + errx \ + explicit_bzero \ + explicit_memset \ + fchmod \ + fchmodat \ + fchown \ + fchownat \ + flock \ + fnmatch \ + freeaddrinfo \ + freezero \ + fstatfs \ + fstatvfs \ + futimes \ + getaddrinfo \ + getcwd \ + getentropy \ + getgrouplist \ + getifaddrs \ + getline \ + getnameinfo \ + getopt \ + getpagesize \ + getpeereid \ + getpeerucred \ + getpgid \ + _getpty \ + getrlimit \ + getrandom \ + getsid \ + getttyent \ + glob \ + group_from_gid \ + inet_aton \ + inet_ntoa \ + inet_ntop \ + innetgr \ + killpg \ + localtime_r \ + login_getcapbool \ + login_getpwclass \ + md5_crypt \ + memmem \ + memmove \ + memset_s \ + mkdtemp \ + ngetaddrinfo \ + nsleep \ + ogetaddrinfo \ + openlog_r \ + pledge \ + poll \ + ppoll \ + prctl \ + procctl \ + pselect \ + pstat \ + raise \ + readpassphrase \ + reallocarray \ + recvmsg \ + recallocarray \ + rresvport_af \ + sendmsg \ + setdtablesize \ + setegid \ + setenv \ + seteuid \ + setgroupent \ + setgroups \ + setlinebuf \ + setlogin \ + setpassent\ + setpcred \ + setproctitle \ + setregid \ + setreuid \ + setrlimit \ + setsid \ + setvbuf \ + sigaction \ + sigvec \ + snprintf \ + socketpair \ + statfs \ + statvfs \ + strcasestr \ + strdup \ + strerror \ + strlcat \ + strlcpy \ + strmode \ + strndup \ + strnlen \ + strnvis \ + strptime \ + strsignal \ + strtonum \ + strtoll \ + strtoul \ + strtoull \ + swap32 \ + sysconf \ + tcgetpgrp \ + timegm \ + timingsafe_bcmp \ + truncate \ + unsetenv \ + updwtmpx \ + utimensat \ + user_from_uid \ + usleep \ + vasprintf \ + vsnprintf \ + waitpid \ + warn \ -fi -ac_fn_c_check_func "$LINENO" "strtoul" "ac_cv_func_strtoul" -if test "x$ac_cv_func_strtoul" = xyes -then : - printf "%s\n" "#define HAVE_STRTOUL 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "strtoull" "ac_cv_func_strtoull" -if test "x$ac_cv_func_strtoull" = xyes -then : - printf "%s\n" "#define HAVE_STRTOULL 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "swap32" "ac_cv_func_swap32" -if test "x$ac_cv_func_swap32" = xyes -then : - printf "%s\n" "#define HAVE_SWAP32 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "sysconf" "ac_cv_func_sysconf" -if test "x$ac_cv_func_sysconf" = xyes -then : - printf "%s\n" "#define HAVE_SYSCONF 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "tcgetpgrp" "ac_cv_func_tcgetpgrp" -if test "x$ac_cv_func_tcgetpgrp" = xyes -then : - printf "%s\n" "#define HAVE_TCGETPGRP 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "timegm" "ac_cv_func_timegm" -if test "x$ac_cv_func_timegm" = xyes -then : - printf "%s\n" "#define HAVE_TIMEGM 1" >>confdefs.h +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF fi -ac_fn_c_check_func "$LINENO" "timingsafe_bcmp" "ac_cv_func_timingsafe_bcmp" -if test "x$ac_cv_func_timingsafe_bcmp" = xyes -then : - printf "%s\n" "#define HAVE_TIMINGSAFE_BCMP 1" >>confdefs.h +done -fi -ac_fn_c_check_func "$LINENO" "truncate" "ac_cv_func_truncate" -if test "x$ac_cv_func_truncate" = xyes -then : - printf "%s\n" "#define HAVE_TRUNCATE 1" >>confdefs.h +saved_CPPFLAGS="$CPPFLAGS" +CPPFLAGS="$CPPFLAGS -D_GNU_SOURCE" +ac_fn_c_check_decl "$LINENO" "memmem" "ac_cv_have_decl_memmem" "$ac_includes_default" +if test "x$ac_cv_have_decl_memmem" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 fi -ac_fn_c_check_func "$LINENO" "unsetenv" "ac_cv_func_unsetenv" -if test "x$ac_cv_func_unsetenv" = xyes -then : - printf "%s\n" "#define HAVE_UNSETENV 1" >>confdefs.h -fi -ac_fn_c_check_func "$LINENO" "updwtmpx" "ac_cv_func_updwtmpx" -if test "x$ac_cv_func_updwtmpx" = xyes -then : - printf "%s\n" "#define HAVE_UPDWTMPX 1" >>confdefs.h +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_MEMMEM $ac_have_decl +_ACEOF +ac_fn_c_check_decl "$LINENO" "memset_s" "ac_cv_have_decl_memset_s" "$ac_includes_default" +if test "x$ac_cv_have_decl_memset_s" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 fi -ac_fn_c_check_func "$LINENO" "utimensat" "ac_cv_func_utimensat" -if test "x$ac_cv_func_utimensat" = xyes -then : - printf "%s\n" "#define HAVE_UTIMENSAT 1" >>confdefs.h -fi -ac_fn_c_check_func "$LINENO" "user_from_uid" "ac_cv_func_user_from_uid" -if test "x$ac_cv_func_user_from_uid" = xyes -then : - printf "%s\n" "#define HAVE_USER_FROM_UID 1" >>confdefs.h +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_MEMSET_S $ac_have_decl +_ACEOF -fi -ac_fn_c_check_func "$LINENO" "usleep" "ac_cv_func_usleep" -if test "x$ac_cv_func_usleep" = xyes -then : - printf "%s\n" "#define HAVE_USLEEP 1" >>confdefs.h +if test $ac_cv_func_endgrent != no; then : -fi -ac_fn_c_check_func "$LINENO" "vasprintf" "ac_cv_func_vasprintf" -if test "x$ac_cv_func_vasprintf" = xyes -then : - printf "%s\n" "#define HAVE_VASPRINTF 1" >>confdefs.h + ac_fn_c_check_decl "$LINENO" "endgrent" "ac_cv_have_decl_endgrent" " +#include +#include +" +if test "x$ac_cv_have_decl_endgrent" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 fi -ac_fn_c_check_func "$LINENO" "vsnprintf" "ac_cv_func_vsnprintf" -if test "x$ac_cv_func_vsnprintf" = xyes -then : - printf "%s\n" "#define HAVE_VSNPRINTF 1" >>confdefs.h -fi -ac_fn_c_check_func "$LINENO" "waitpid" "ac_cv_func_waitpid" -if test "x$ac_cv_func_waitpid" = xyes -then : - printf "%s\n" "#define HAVE_WAITPID 1" >>confdefs.h +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_ENDGRENT $ac_have_decl +_ACEOF -fi -ac_fn_c_check_func "$LINENO" "warn" "ac_cv_func_warn" -if test "x$ac_cv_func_warn" = xyes -then : - printf "%s\n" "#define HAVE_WARN 1" >>confdefs.h fi +ac_fn_c_check_decl "$LINENO" "endpwent" "ac_cv_have_decl_endpwent" " +#include +#include - -ac_fn_check_decl "$LINENO" "bzero" "ac_cv_have_decl_bzero" "$ac_includes_default" "$ac_c_undeclared_builtin_options" "CFLAGS" -if test "x$ac_cv_have_decl_bzero" = xyes -then : - ac_have_decl=1 -else $as_nop - ac_have_decl=0 -fi -printf "%s\n" "#define HAVE_DECL_BZERO $ac_have_decl" >>confdefs.h -ac_fn_check_decl "$LINENO" "memmem" "ac_cv_have_decl_memmem" "$ac_includes_default" "$ac_c_undeclared_builtin_options" "CFLAGS" -if test "x$ac_cv_have_decl_memmem" = xyes -then : +" +if test "x$ac_cv_have_decl_endpwent" = xyes; then : ac_have_decl=1 -else $as_nop +else ac_have_decl=0 fi -printf "%s\n" "#define HAVE_DECL_MEMMEM $ac_have_decl" >>confdefs.h - - -ac_fn_c_check_func "$LINENO" "mblen" "ac_cv_func_mblen" -if test "x$ac_cv_func_mblen" = xyes -then : - printf "%s\n" "#define HAVE_MBLEN 1" >>confdefs.h -fi -ac_fn_c_check_func "$LINENO" "mbtowc" "ac_cv_func_mbtowc" -if test "x$ac_cv_func_mbtowc" = xyes -then : - printf "%s\n" "#define HAVE_MBTOWC 1" >>confdefs.h +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_ENDPWENT $ac_have_decl +_ACEOF -fi -ac_fn_c_check_func "$LINENO" "nl_langinfo" "ac_cv_func_nl_langinfo" -if test "x$ac_cv_func_nl_langinfo" = xyes -then : - printf "%s\n" "#define HAVE_NL_LANGINFO 1" >>confdefs.h +CPPFLAGS="$saved_CPPFLAGS" -fi -ac_fn_c_check_func "$LINENO" "wcwidth" "ac_cv_func_wcwidth" -if test "x$ac_cv_func_wcwidth" = xyes -then : - printf "%s\n" "#define HAVE_WCWIDTH 1" >>confdefs.h +for ac_func in mblen mbtowc nl_langinfo wcwidth +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF fi +done TEST_SSH_UTF8=${TEST_SSH_UTF8:=yes} -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for utf8 locale support" >&5 -printf %s "checking for utf8 locale support... " >&6; } -if test "$cross_compiling" = yes -then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: assuming yes" >&5 -printf "%s\n" "$as_me: WARNING: cross compiling: assuming yes" >&2;} +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for utf8 locale support" >&5 +$as_echo_n "checking for utf8 locale support... " >&6; } +if test "$cross_compiling" = yes; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: assuming yes" >&5 +$as_echo "$as_me: WARNING: cross compiling: assuming yes" >&2;} -else $as_nop +else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include -#include int -main (void) +main () { char *loc = setlocale(LC_CTYPE, "en_US.UTF-8"); - if (loc != NULL) - exit(0); - exit(1); + if (loc == NULL) return 1; ; return 0; } _ACEOF -if ac_fn_c_try_run "$LINENO" -then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } -else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } +if ac_fn_c_try_run "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } TEST_SSH_UTF8=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ @@ -13682,141 +11811,44 @@ /* end confdefs.h. */ #include int -main (void) +main () { return (isblank('a')); ; return 0; } _ACEOF -if ac_fn_c_try_link "$LINENO" -then : +if ac_fn_c_try_link "$LINENO"; then : -printf "%s\n" "#define HAVE_ISBLANK 1" >>confdefs.h +$as_echo "#define HAVE_ISBLANK 1" >>confdefs.h fi -rm -f core conftest.err conftest.$ac_objext conftest.beam \ +rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext -disable_pkcs11= +PKCS11_MSG=yes # Check whether --enable-pkcs11 was given. -if test ${enable_pkcs11+y} -then : +if test "${enable_pkcs11+set}" = set; then : enableval=$enable_pkcs11; if test "x$enableval" = "xno" ; then - disable_pkcs11=1 + PKCS11_MSG=no fi fi -disable_sk= -# Check whether --enable-security-key was given. -if test ${enable_security_key+y} -then : - enableval=$enable_security_key; - if test "x$enableval" = "xno" ; then - disable_sk=1 - fi - - -fi - -enable_sk_internal= - -# Check whether --with-security-key-builtin was given. -if test ${with_security_key_builtin+y} -then : - withval=$with_security_key_builtin; enable_sk_internal=$withval - -fi - - -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for library containing dlopen" >&5 -printf %s "checking for library containing dlopen... " >&6; } -if test ${ac_cv_search_dlopen+y} -then : - printf %s "(cached) " >&6 -else $as_nop - ac_func_search_save_LIBS=$LIBS -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -char dlopen (); -int -main (void) -{ -return dlopen (); - ; - return 0; -} -_ACEOF -for ac_lib in '' dl -do - if test -z "$ac_lib"; then - ac_res="none required" - else - ac_res=-l$ac_lib - LIBS="-l$ac_lib $ac_func_search_save_LIBS" - fi - if ac_fn_c_try_link "$LINENO" -then : - ac_cv_search_dlopen=$ac_res -fi -rm -f core conftest.err conftest.$ac_objext conftest.beam \ - conftest$ac_exeext - if test ${ac_cv_search_dlopen+y} -then : - break -fi -done -if test ${ac_cv_search_dlopen+y} -then : - -else $as_nop - ac_cv_search_dlopen=no -fi -rm conftest.$ac_ext -LIBS=$ac_func_search_save_LIBS -fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_dlopen" >&5 -printf "%s\n" "$ac_cv_search_dlopen" >&6; } -ac_res=$ac_cv_search_dlopen -if test "$ac_res" != no -then : - test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" - -fi - -ac_fn_c_check_func "$LINENO" "dlopen" "ac_cv_func_dlopen" -if test "x$ac_cv_func_dlopen" = xyes -then : - printf "%s\n" "#define HAVE_DLOPEN 1" >>confdefs.h - -fi - -ac_fn_check_decl "$LINENO" "RTLD_NOW" "ac_cv_have_decl_RTLD_NOW" "#include -" "$ac_c_undeclared_builtin_options" "CFLAGS" -if test "x$ac_cv_have_decl_RTLD_NOW" = xyes -then : - -fi - # IRIX has a const char return value for gai_strerror() - - for ac_func in gai_strerror +for ac_func in gai_strerror do : ac_fn_c_check_func "$LINENO" "gai_strerror" "ac_cv_func_gai_strerror" -if test "x$ac_cv_func_gai_strerror" = xyes -then : - printf "%s\n" "#define HAVE_GAI_STRERROR 1" >>confdefs.h +if test "x$ac_cv_func_gai_strerror" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_GAI_STRERROR 1 +_ACEOF - printf "%s\n" "#define HAVE_GAI_STRERROR 1" >>confdefs.h + $as_echo "#define HAVE_GAI_STRERROR 1" >>confdefs.h cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -13828,7 +11860,7 @@ const char *gai_strerror(int); int -main (void) +main () { char *str; @@ -13838,24 +11870,22 @@ return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO" -then : +if ac_fn_c_try_compile "$LINENO"; then : -printf "%s\n" "#define HAVE_CONST_GAI_STRERROR_PROTO 1" >>confdefs.h +$as_echo "#define HAVE_CONST_GAI_STRERROR_PROTO 1" >>confdefs.h fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi - done -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for library containing nanosleep" >&5 -printf %s "checking for library containing nanosleep... " >&6; } -if test ${ac_cv_search_nanosleep+y} -then : - printf %s "(cached) " >&6 -else $as_nop + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing nanosleep" >&5 +$as_echo_n "checking for library containing nanosleep... " >&6; } +if ${ac_cv_search_nanosleep+:} false; then : + $as_echo_n "(cached) " >&6 +else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -13863,61 +11893,58 @@ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif char nanosleep (); int -main (void) +main () { return nanosleep (); ; return 0; } _ACEOF -for ac_lib in '' rt posix4 -do +for ac_lib in '' rt posix4; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi - if ac_fn_c_try_link "$LINENO" -then : + if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_nanosleep=$ac_res fi -rm -f core conftest.err conftest.$ac_objext conftest.beam \ +rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext - if test ${ac_cv_search_nanosleep+y} -then : + if ${ac_cv_search_nanosleep+:} false; then : break fi done -if test ${ac_cv_search_nanosleep+y} -then : +if ${ac_cv_search_nanosleep+:} false; then : -else $as_nop +else ac_cv_search_nanosleep=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_nanosleep" >&5 -printf "%s\n" "$ac_cv_search_nanosleep" >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_nanosleep" >&5 +$as_echo "$ac_cv_search_nanosleep" >&6; } ac_res=$ac_cv_search_nanosleep -if test "$ac_res" != no -then : +if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" -printf "%s\n" "#define HAVE_NANOSLEEP 1" >>confdefs.h +$as_echo "#define HAVE_NANOSLEEP 1" >>confdefs.h fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for library containing clock_gettime" >&5 -printf %s "checking for library containing clock_gettime... " >&6; } -if test ${ac_cv_search_clock_gettime+y} -then : - printf %s "(cached) " >&6 -else $as_nop +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing clock_gettime" >&5 +$as_echo_n "checking for library containing clock_gettime... " >&6; } +if ${ac_cv_search_clock_gettime+:} false; then : + $as_echo_n "(cached) " >&6 +else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -13925,151 +11952,163 @@ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif char clock_gettime (); int -main (void) +main () { return clock_gettime (); ; return 0; } _ACEOF -for ac_lib in '' rt -do +for ac_lib in '' rt; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi - if ac_fn_c_try_link "$LINENO" -then : + if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_clock_gettime=$ac_res fi -rm -f core conftest.err conftest.$ac_objext conftest.beam \ +rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext - if test ${ac_cv_search_clock_gettime+y} -then : + if ${ac_cv_search_clock_gettime+:} false; then : break fi done -if test ${ac_cv_search_clock_gettime+y} -then : +if ${ac_cv_search_clock_gettime+:} false; then : -else $as_nop +else ac_cv_search_clock_gettime=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_clock_gettime" >&5 -printf "%s\n" "$ac_cv_search_clock_gettime" >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_clock_gettime" >&5 +$as_echo "$ac_cv_search_clock_gettime" >&6; } ac_res=$ac_cv_search_clock_gettime -if test "$ac_res" != no -then : +if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" -printf "%s\n" "#define HAVE_CLOCK_GETTIME 1" >>confdefs.h +$as_echo "#define HAVE_CLOCK_GETTIME 1" >>confdefs.h fi -ac_fn_check_decl "$LINENO" "localtime_r" "ac_cv_have_decl_localtime_r" " #include +ac_fn_c_check_decl "$LINENO" "localtime_r" "ac_cv_have_decl_localtime_r" " #include -" "$ac_c_undeclared_builtin_options" "CFLAGS" -if test "x$ac_cv_have_decl_localtime_r" = xyes -then : +" +if test "x$ac_cv_have_decl_localtime_r" = xyes; then : -else $as_nop +else saved_CPPFLAGS="$CPPFLAGS" CPPFLAGS="$CPPFLAGS -D_REENTRANT" unset ac_cv_have_decl_localtime_r - ac_fn_check_decl "$LINENO" "localtime_r" "ac_cv_have_decl_localtime_r" " #include + ac_fn_c_check_decl "$LINENO" "localtime_r" "ac_cv_have_decl_localtime_r" " #include -" "$ac_c_undeclared_builtin_options" "CFLAGS" -if test "x$ac_cv_have_decl_localtime_r" = xyes -then : +" +if test "x$ac_cv_have_decl_localtime_r" = xyes; then : -else $as_nop +else CPPFLAGS="$saved_CPPFLAGS" fi + fi -ac_fn_check_decl "$LINENO" "strsep" "ac_cv_have_decl_strsep" " + +ac_fn_c_check_decl "$LINENO" "strsep" "ac_cv_have_decl_strsep" " #ifdef HAVE_STRING_H # include #endif -" "$ac_c_undeclared_builtin_options" "CFLAGS" -if test "x$ac_cv_have_decl_strsep" = xyes -then : +" +if test "x$ac_cv_have_decl_strsep" = xyes; then : + for ac_func in strsep +do : ac_fn_c_check_func "$LINENO" "strsep" "ac_cv_func_strsep" -if test "x$ac_cv_func_strsep" = xyes -then : - printf "%s\n" "#define HAVE_STRSEP 1" >>confdefs.h +if test "x$ac_cv_func_strsep" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_STRSEP 1 +_ACEOF fi +done fi -ac_fn_check_decl "$LINENO" "tcsendbreak" "ac_cv_have_decl_tcsendbreak" "#include -" "$ac_c_undeclared_builtin_options" "CFLAGS" -if test "x$ac_cv_have_decl_tcsendbreak" = xyes -then : - printf "%s\n" "#define HAVE_TCSENDBREAK 1" >>confdefs.h +ac_fn_c_check_decl "$LINENO" "tcsendbreak" "ac_cv_have_decl_tcsendbreak" "#include -else $as_nop +" +if test "x$ac_cv_have_decl_tcsendbreak" = xyes; then : + $as_echo "#define HAVE_TCSENDBREAK 1" >>confdefs.h + +else + for ac_func in tcsendbreak +do : ac_fn_c_check_func "$LINENO" "tcsendbreak" "ac_cv_func_tcsendbreak" -if test "x$ac_cv_func_tcsendbreak" = xyes -then : - printf "%s\n" "#define HAVE_TCSENDBREAK 1" >>confdefs.h +if test "x$ac_cv_func_tcsendbreak" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_TCSENDBREAK 1 +_ACEOF fi +done fi -ac_fn_check_decl "$LINENO" "h_errno" "ac_cv_have_decl_h_errno" "#include -" "$ac_c_undeclared_builtin_options" "CFLAGS" -if test "x$ac_cv_have_decl_h_errno" = xyes -then : + +ac_fn_c_check_decl "$LINENO" "h_errno" "ac_cv_have_decl_h_errno" "#include +" +if test "x$ac_cv_have_decl_h_errno" = xyes; then : ac_have_decl=1 -else $as_nop +else ac_have_decl=0 fi -printf "%s\n" "#define HAVE_DECL_H_ERRNO $ac_have_decl" >>confdefs.h +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_H_ERRNO $ac_have_decl +_ACEOF -ac_fn_check_decl "$LINENO" "SHUT_RD" "ac_cv_have_decl_SHUT_RD" " + +ac_fn_c_check_decl "$LINENO" "SHUT_RD" "ac_cv_have_decl_SHUT_RD" " #include #include #include -" "$ac_c_undeclared_builtin_options" "CFLAGS" -if test "x$ac_cv_have_decl_SHUT_RD" = xyes -then : +" +if test "x$ac_cv_have_decl_SHUT_RD" = xyes; then : ac_have_decl=1 -else $as_nop +else ac_have_decl=0 fi -printf "%s\n" "#define HAVE_DECL_SHUT_RD $ac_have_decl" >>confdefs.h -ac_fn_check_decl "$LINENO" "getpeereid" "ac_cv_have_decl_getpeereid" " + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_SHUT_RD $ac_have_decl +_ACEOF +ac_fn_c_check_decl "$LINENO" "getpeereid" "ac_cv_have_decl_getpeereid" " #include #include #include -" "$ac_c_undeclared_builtin_options" "CFLAGS" -if test "x$ac_cv_have_decl_getpeereid" = xyes -then : +" +if test "x$ac_cv_have_decl_getpeereid" = xyes; then : ac_have_decl=1 -else $as_nop +else ac_have_decl=0 fi -printf "%s\n" "#define HAVE_DECL_GETPEEREID $ac_have_decl" >>confdefs.h + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_GETPEEREID $ac_have_decl +_ACEOF -ac_fn_check_decl "$LINENO" "O_NONBLOCK" "ac_cv_have_decl_O_NONBLOCK" " +ac_fn_c_check_decl "$LINENO" "O_NONBLOCK" "ac_cv_have_decl_O_NONBLOCK" " #include #ifdef HAVE_SYS_STAT_H # include @@ -14078,98 +12117,98 @@ # include #endif -" "$ac_c_undeclared_builtin_options" "CFLAGS" -if test "x$ac_cv_have_decl_O_NONBLOCK" = xyes -then : +" +if test "x$ac_cv_have_decl_O_NONBLOCK" = xyes; then : ac_have_decl=1 -else $as_nop +else ac_have_decl=0 fi -printf "%s\n" "#define HAVE_DECL_O_NONBLOCK $ac_have_decl" >>confdefs.h +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_O_NONBLOCK $ac_have_decl +_ACEOF -ac_fn_check_decl "$LINENO" "ftruncate" "ac_cv_have_decl_ftruncate" " -#include -#include -" "$ac_c_undeclared_builtin_options" "CFLAGS" -if test "x$ac_cv_have_decl_ftruncate" = xyes -then : - ac_have_decl=1 -else $as_nop - ac_have_decl=0 -fi -printf "%s\n" "#define HAVE_DECL_FTRUNCATE $ac_have_decl" >>confdefs.h -ac_fn_check_decl "$LINENO" "getentropy" "ac_cv_have_decl_getentropy" " +ac_fn_c_check_decl "$LINENO" "ftruncate" "ac_cv_have_decl_ftruncate" " #include #include -" "$ac_c_undeclared_builtin_options" "CFLAGS" -if test "x$ac_cv_have_decl_getentropy" = xyes -then : +" +if test "x$ac_cv_have_decl_ftruncate" = xyes; then : ac_have_decl=1 -else $as_nop +else ac_have_decl=0 fi -printf "%s\n" "#define HAVE_DECL_GETENTROPY $ac_have_decl" >>confdefs.h + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_FTRUNCATE $ac_have_decl +_ACEOF -ac_fn_check_decl "$LINENO" "readv" "ac_cv_have_decl_readv" " +ac_fn_c_check_decl "$LINENO" "readv" "ac_cv_have_decl_readv" " #include #include #include -" "$ac_c_undeclared_builtin_options" "CFLAGS" -if test "x$ac_cv_have_decl_readv" = xyes -then : +" +if test "x$ac_cv_have_decl_readv" = xyes; then : ac_have_decl=1 -else $as_nop +else ac_have_decl=0 fi -printf "%s\n" "#define HAVE_DECL_READV $ac_have_decl" >>confdefs.h -ac_fn_check_decl "$LINENO" "writev" "ac_cv_have_decl_writev" " + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_READV $ac_have_decl +_ACEOF +ac_fn_c_check_decl "$LINENO" "writev" "ac_cv_have_decl_writev" " #include #include #include -" "$ac_c_undeclared_builtin_options" "CFLAGS" -if test "x$ac_cv_have_decl_writev" = xyes -then : +" +if test "x$ac_cv_have_decl_writev" = xyes; then : ac_have_decl=1 -else $as_nop +else ac_have_decl=0 fi -printf "%s\n" "#define HAVE_DECL_WRITEV $ac_have_decl" >>confdefs.h + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_WRITEV $ac_have_decl +_ACEOF -ac_fn_check_decl "$LINENO" "MAXSYMLINKS" "ac_cv_have_decl_MAXSYMLINKS" " +ac_fn_c_check_decl "$LINENO" "MAXSYMLINKS" "ac_cv_have_decl_MAXSYMLINKS" " #include -" "$ac_c_undeclared_builtin_options" "CFLAGS" -if test "x$ac_cv_have_decl_MAXSYMLINKS" = xyes -then : +" +if test "x$ac_cv_have_decl_MAXSYMLINKS" = xyes; then : ac_have_decl=1 -else $as_nop +else ac_have_decl=0 fi -printf "%s\n" "#define HAVE_DECL_MAXSYMLINKS $ac_have_decl" >>confdefs.h + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_MAXSYMLINKS $ac_have_decl +_ACEOF -ac_fn_check_decl "$LINENO" "offsetof" "ac_cv_have_decl_offsetof" " +ac_fn_c_check_decl "$LINENO" "offsetof" "ac_cv_have_decl_offsetof" " #include -" "$ac_c_undeclared_builtin_options" "CFLAGS" -if test "x$ac_cv_have_decl_offsetof" = xyes -then : +" +if test "x$ac_cv_have_decl_offsetof" = xyes; then : ac_have_decl=1 -else $as_nop +else ac_have_decl=0 fi -printf "%s\n" "#define HAVE_DECL_OFFSETOF $ac_have_decl" >>confdefs.h + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_OFFSETOF $ac_have_decl +_ACEOF # extra bits for select(2) -ac_fn_check_decl "$LINENO" "howmany" "ac_cv_have_decl_howmany" " +ac_fn_c_check_decl "$LINENO" "howmany" "ac_cv_have_decl_howmany" " #include #include #ifdef HAVE_SYS_SYSMACROS_H @@ -14181,19 +12220,19 @@ #ifdef HAVE_SYS_TIME_H #include #endif -#ifdef HAVE_UNISTD_H #include -#endif -" "$ac_c_undeclared_builtin_options" "CFLAGS" -if test "x$ac_cv_have_decl_howmany" = xyes -then : +" +if test "x$ac_cv_have_decl_howmany" = xyes; then : ac_have_decl=1 -else $as_nop +else ac_have_decl=0 fi -printf "%s\n" "#define HAVE_DECL_HOWMANY $ac_have_decl" >>confdefs.h -ac_fn_check_decl "$LINENO" "NFDBITS" "ac_cv_have_decl_NFDBITS" " + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_HOWMANY $ac_have_decl +_ACEOF +ac_fn_c_check_decl "$LINENO" "NFDBITS" "ac_cv_have_decl_NFDBITS" " #include #include #ifdef HAVE_SYS_SYSMACROS_H @@ -14205,18 +12244,18 @@ #ifdef HAVE_SYS_TIME_H #include #endif -#ifdef HAVE_UNISTD_H #include -#endif -" "$ac_c_undeclared_builtin_options" "CFLAGS" -if test "x$ac_cv_have_decl_NFDBITS" = xyes -then : +" +if test "x$ac_cv_have_decl_NFDBITS" = xyes; then : ac_have_decl=1 -else $as_nop +else ac_have_decl=0 fi -printf "%s\n" "#define HAVE_DECL_NFDBITS $ac_have_decl" >>confdefs.h + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_NFDBITS $ac_have_decl +_ACEOF ac_fn_c_check_type "$LINENO" "fd_mask" "ac_cv_type_fd_mask" " #include @@ -14227,308 +12266,256 @@ #ifdef HAVE_SYS_TIME_H #include #endif -#ifdef HAVE_UNISTD_H #include -#endif " -if test "x$ac_cv_type_fd_mask" = xyes -then : +if test "x$ac_cv_type_fd_mask" = xyes; then : -printf "%s\n" "#define HAVE_FD_MASK 1" >>confdefs.h +cat >>confdefs.h <<_ACEOF +#define HAVE_FD_MASK 1 +_ACEOF fi - - for ac_func in setresuid +for ac_func in setresuid do : ac_fn_c_check_func "$LINENO" "setresuid" "ac_cv_func_setresuid" -if test "x$ac_cv_func_setresuid" = xyes -then : - printf "%s\n" "#define HAVE_SETRESUID 1" >>confdefs.h - - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if setresuid seems to work" >&5 -printf %s "checking if setresuid seems to work... " >&6; } - if test "$cross_compiling" = yes -then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: not checking setresuid" >&5 -printf "%s\n" "$as_me: WARNING: cross compiling: not checking setresuid" >&2;} +if test "x$ac_cv_func_setresuid" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_SETRESUID 1 +_ACEOF -else $as_nop + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if setresuid seems to work" >&5 +$as_echo_n "checking if setresuid seems to work... " >&6; } +if ${ssh_cv_func_setresuid_work+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "$cross_compiling" = yes; then : + ssh_cv_func_setresuid_work=cross + +else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -#include -#include +#define _GNU_SOURCE #include +#include int -main (void) +main () { - errno=0; - setresuid(0,0,0); - if (errno==ENOSYS) - exit(1); - else - exit(0); +errno=0; +setresuid(0,0,0); +if (errno==ENOSYS) return 1; ; return 0; } _ACEOF -if ac_fn_c_try_run "$LINENO" -then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } -else $as_nop - -printf "%s\n" "#define BROKEN_SETRESUID 1" >>confdefs.h - - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: not implemented" >&5 -printf "%s\n" "not implemented" >&6; } +if ac_fn_c_try_run "$LINENO"; then : + ssh_cv_func_setresuid_work=yes +else + ssh_cv_func_setresuid_work=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ssh_cv_func_setresuid_work" >&5 +$as_echo "$ssh_cv_func_setresuid_work" >&6; } +if test $ssh_cv_func_setresuid_work = cross; then : + + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: assuming working setresuid" >&5 +$as_echo "$as_me: WARNING: cross compiling: assuming working setresuid" >&2;} + ssh_cv_func_setresuid_work=yes + +fi +if test $ssh_cv_func_setresuid_work != yes; then : + + +$as_echo "#define BROKEN_SETRESUID 1" >>confdefs.h + fi +fi done - for ac_func in setresgid +for ac_func in setresgid do : ac_fn_c_check_func "$LINENO" "setresgid" "ac_cv_func_setresgid" -if test "x$ac_cv_func_setresgid" = xyes -then : - printf "%s\n" "#define HAVE_SETRESGID 1" >>confdefs.h - - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if setresgid seems to work" >&5 -printf %s "checking if setresgid seems to work... " >&6; } - if test "$cross_compiling" = yes -then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: not checking setresuid" >&5 -printf "%s\n" "$as_me: WARNING: cross compiling: not checking setresuid" >&2;} +if test "x$ac_cv_func_setresgid" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_SETRESGID 1 +_ACEOF -else $as_nop + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if setresgid seems to work" >&5 +$as_echo_n "checking if setresgid seems to work... " >&6; } +if ${ssh_cv_func_setresgid_work+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "$cross_compiling" = yes; then : + ssh_cv_func_setresgid_work=cross + +else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -#include -#include +#define _GNU_SOURCE #include +#include int -main (void) +main () { - errno=0; - setresgid(0,0,0); - if (errno==ENOSYS) - exit(1); - else - exit(0); +errno=0; +setresgid(0,0,0); +if (errno==ENOSYS) return 1; ; return 0; } _ACEOF -if ac_fn_c_try_run "$LINENO" -then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } -else $as_nop - -printf "%s\n" "#define BROKEN_SETRESGID 1" >>confdefs.h - - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: not implemented" >&5 -printf "%s\n" "not implemented" >&6; } +if ac_fn_c_try_run "$LINENO"; then : + ssh_cv_func_setresgid_work=yes +else + ssh_cv_func_setresgid_work=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ssh_cv_func_setresgid_work" >&5 +$as_echo "$ssh_cv_func_setresgid_work" >&6; } +if test $ssh_cv_func_setresgid_work = cross; then : + + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: assuming working setresgid" >&5 +$as_echo "$as_me: WARNING: cross compiling: assuming working setresgid" >&2;} + ssh_cv_func_setresgid_work=yes fi +if test $ssh_cv_func_setresgid_work != yes; then : + + +$as_echo "#define BROKEN_SETRESGID 1" >>confdefs.h + +fi + +fi done -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for working fflush(NULL)" >&5 -printf %s "checking for working fflush(NULL)... " >&6; } -if test "$cross_compiling" = yes -then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: assuming working" >&5 -printf "%s\n" "$as_me: WARNING: cross compiling: assuming working" >&2;} -else $as_nop +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for working fflush(NULL)" >&5 +$as_echo_n "checking for working fflush(NULL)... " >&6; } +if ${ssh_cv_func_fflush_null+:} false; then : + $as_echo_n "(cached) " >&6 +else + +if test "$cross_compiling" = yes; then : + ssh_cv_func_fflush_null=cross + +else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ - #include -#include - int -main (void) +main () { -fflush(NULL); exit(0); +fflush(NULL); ; return 0; } _ACEOF -if ac_fn_c_try_run "$LINENO" -then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } -else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } - -printf "%s\n" "#define FFLUSH_NULL_BUG 1" >>confdefs.h - +if ac_fn_c_try_run "$LINENO"; then : + ssh_cv_func_fflush_null=yes +else + ssh_cv_func_fflush_null=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi - -ac_fn_c_check_func "$LINENO" "gettimeofday" "ac_cv_func_gettimeofday" -if test "x$ac_cv_func_gettimeofday" = xyes -then : - printf "%s\n" "#define HAVE_GETTIMEOFDAY 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "time" "ac_cv_func_time" -if test "x$ac_cv_func_time" = xyes -then : - printf "%s\n" "#define HAVE_TIME 1" >>confdefs.h - -fi - -ac_fn_c_check_func "$LINENO" "endutent" "ac_cv_func_endutent" -if test "x$ac_cv_func_endutent" = xyes -then : - printf "%s\n" "#define HAVE_ENDUTENT 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "getutent" "ac_cv_func_getutent" -if test "x$ac_cv_func_getutent" = xyes -then : - printf "%s\n" "#define HAVE_GETUTENT 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "getutid" "ac_cv_func_getutid" -if test "x$ac_cv_func_getutid" = xyes -then : - printf "%s\n" "#define HAVE_GETUTID 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "getutline" "ac_cv_func_getutline" -if test "x$ac_cv_func_getutline" = xyes -then : - printf "%s\n" "#define HAVE_GETUTLINE 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "pututline" "ac_cv_func_pututline" -if test "x$ac_cv_func_pututline" = xyes -then : - printf "%s\n" "#define HAVE_PUTUTLINE 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "setutent" "ac_cv_func_setutent" -if test "x$ac_cv_func_setutent" = xyes -then : - printf "%s\n" "#define HAVE_SETUTENT 1" >>confdefs.h - fi - -ac_fn_c_check_func "$LINENO" "utmpname" "ac_cv_func_utmpname" -if test "x$ac_cv_func_utmpname" = xyes -then : - printf "%s\n" "#define HAVE_UTMPNAME 1" >>confdefs.h - -fi - -ac_fn_c_check_func "$LINENO" "endutxent" "ac_cv_func_endutxent" -if test "x$ac_cv_func_endutxent" = xyes -then : - printf "%s\n" "#define HAVE_ENDUTXENT 1" >>confdefs.h - +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ssh_cv_func_fflush_null" >&5 +$as_echo "$ssh_cv_func_fflush_null" >&6; } +if test $ssh_cv_func_fflush_null = cross ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: assuming working fflush(NULL)" >&5 +$as_echo "$as_me: WARNING: cross compiling: assuming working fflush(NULL)" >&2;} + ssh_cv_func_fflush_null=yes fi -ac_fn_c_check_func "$LINENO" "getutxent" "ac_cv_func_getutxent" -if test "x$ac_cv_func_getutxent" = xyes -then : - printf "%s\n" "#define HAVE_GETUTXENT 1" >>confdefs.h +if test $ssh_cv_func_fflush_null != yes ; then +$as_echo "#define FFLUSH_NULL_BUG 1" >>confdefs.h +], fi -ac_fn_c_check_func "$LINENO" "getutxid" "ac_cv_func_getutxid" -if test "x$ac_cv_func_getutxid" = xyes -then : - printf "%s\n" "#define HAVE_GETUTXID 1" >>confdefs.h -fi -ac_fn_c_check_func "$LINENO" "getutxline" "ac_cv_func_getutxline" -if test "x$ac_cv_func_getutxline" = xyes -then : - printf "%s\n" "#define HAVE_GETUTXLINE 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "getutxuser" "ac_cv_func_getutxuser" -if test "x$ac_cv_func_getutxuser" = xyes -then : - printf "%s\n" "#define HAVE_GETUTXUSER 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "pututxline" "ac_cv_func_pututxline" -if test "x$ac_cv_func_pututxline" = xyes -then : - printf "%s\n" "#define HAVE_PUTUTXLINE 1" >>confdefs.h +for ac_func in gettimeofday time +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF fi +done -ac_fn_c_check_func "$LINENO" "setutxdb" "ac_cv_func_setutxdb" -if test "x$ac_cv_func_setutxdb" = xyes -then : - printf "%s\n" "#define HAVE_SETUTXDB 1" >>confdefs.h +for ac_func in endutxent getutxent getutxid getutxline getutxuser pututxline +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF fi -ac_fn_c_check_func "$LINENO" "setutxent" "ac_cv_func_setutxent" -if test "x$ac_cv_func_setutxent" = xyes -then : - printf "%s\n" "#define HAVE_SETUTXENT 1" >>confdefs.h +done -fi -ac_fn_c_check_func "$LINENO" "utmpxname" "ac_cv_func_utmpxname" -if test "x$ac_cv_func_utmpxname" = xyes -then : - printf "%s\n" "#define HAVE_UTMPXNAME 1" >>confdefs.h +for ac_func in setutxdb setutxent utmpxname +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF fi +done -ac_fn_c_check_func "$LINENO" "getlastlogxbyname" "ac_cv_func_getlastlogxbyname" -if test "x$ac_cv_func_getlastlogxbyname" = xyes -then : - printf "%s\n" "#define HAVE_GETLASTLOGXBYNAME 1" >>confdefs.h +for ac_func in getlastlogxbyname +do : + ac_fn_c_check_func "$LINENO" "getlastlogxbyname" "ac_cv_func_getlastlogxbyname" +if test "x$ac_cv_func_getlastlogxbyname" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_GETLASTLOGXBYNAME 1 +_ACEOF fi +done ac_fn_c_check_func "$LINENO" "daemon" "ac_cv_func_daemon" -if test "x$ac_cv_func_daemon" = xyes -then : +if test "x$ac_cv_func_daemon" = xyes; then : -printf "%s\n" "#define HAVE_DAEMON 1" >>confdefs.h +$as_echo "#define HAVE_DAEMON 1" >>confdefs.h -else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for daemon in -lbsd" >&5 -printf %s "checking for daemon in -lbsd... " >&6; } -if test ${ac_cv_lib_bsd_daemon+y} -then : - printf %s "(cached) " >&6 -else $as_nop +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for daemon in -lbsd" >&5 +$as_echo_n "checking for daemon in -lbsd... " >&6; } +if ${ac_cv_lib_bsd_daemon+:} false; then : + $as_echo_n "(cached) " >&6 +else ac_check_lib_save_LIBS=$LIBS LIBS="-lbsd $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -14537,30 +12524,31 @@ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif char daemon (); int -main (void) +main () { return daemon (); ; return 0; } _ACEOF -if ac_fn_c_try_link "$LINENO" -then : +if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_bsd_daemon=yes -else $as_nop +else ac_cv_lib_bsd_daemon=no fi -rm -f core conftest.err conftest.$ac_objext conftest.beam \ +rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_bsd_daemon" >&5 -printf "%s\n" "$ac_cv_lib_bsd_daemon" >&6; } -if test "x$ac_cv_lib_bsd_daemon" = xyes -then : - LIBS="$LIBS -lbsd"; printf "%s\n" "#define HAVE_DAEMON 1" >>confdefs.h +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_bsd_daemon" >&5 +$as_echo "$ac_cv_lib_bsd_daemon" >&6; } +if test "x$ac_cv_lib_bsd_daemon" = xyes; then : + LIBS="$LIBS -lbsd"; $as_echo "#define HAVE_DAEMON 1" >>confdefs.h fi @@ -14569,18 +12557,16 @@ ac_fn_c_check_func "$LINENO" "getpagesize" "ac_cv_func_getpagesize" -if test "x$ac_cv_func_getpagesize" = xyes -then : +if test "x$ac_cv_func_getpagesize" = xyes; then : -printf "%s\n" "#define HAVE_GETPAGESIZE 1" >>confdefs.h +$as_echo "#define HAVE_GETPAGESIZE 1" >>confdefs.h -else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for getpagesize in -lucb" >&5 -printf %s "checking for getpagesize in -lucb... " >&6; } -if test ${ac_cv_lib_ucb_getpagesize+y} -then : - printf %s "(cached) " >&6 -else $as_nop +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for getpagesize in -lucb" >&5 +$as_echo_n "checking for getpagesize in -lucb... " >&6; } +if ${ac_cv_lib_ucb_getpagesize+:} false; then : + $as_echo_n "(cached) " >&6 +else ac_check_lib_save_LIBS=$LIBS LIBS="-lucb $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -14589,337 +12575,134 @@ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif char getpagesize (); int -main (void) +main () { return getpagesize (); ; return 0; } _ACEOF -if ac_fn_c_try_link "$LINENO" -then : +if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_ucb_getpagesize=yes -else $as_nop +else ac_cv_lib_ucb_getpagesize=no fi -rm -f core conftest.err conftest.$ac_objext conftest.beam \ +rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ucb_getpagesize" >&5 -printf "%s\n" "$ac_cv_lib_ucb_getpagesize" >&6; } -if test "x$ac_cv_lib_ucb_getpagesize" = xyes -then : - LIBS="$LIBS -lucb"; printf "%s\n" "#define HAVE_GETPAGESIZE 1" >>confdefs.h - -fi - - -fi - - -# Check for broken snprintf -if test "x$ac_cv_func_snprintf" = "xyes" ; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether snprintf correctly terminates long strings" >&5 -printf %s "checking whether snprintf correctly terminates long strings... " >&6; } - if test "$cross_compiling" = yes -then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: Assuming working snprintf()" >&5 -printf "%s\n" "$as_me: WARNING: cross compiling: Assuming working snprintf()" >&2;} - -else $as_nop - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -#include -#include - -int -main (void) -{ - - char b[5]; - snprintf(b,5,"123456789"); - exit(b[4]!='\0'); - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_run "$LINENO" -then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } -else $as_nop - - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } - -printf "%s\n" "#define BROKEN_SNPRINTF 1" >>confdefs.h - - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: ****** Your snprintf() function is broken, complain to your vendor" >&5 -printf "%s\n" "$as_me: WARNING: ****** Your snprintf() function is broken, complain to your vendor" >&2;} - -fi -rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ - conftest.$ac_objext conftest.beam conftest.$ac_ext -fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ucb_getpagesize" >&5 +$as_echo "$ac_cv_lib_ucb_getpagesize" >&6; } +if test "x$ac_cv_lib_ucb_getpagesize" = xyes; then : + LIBS="$LIBS -lucb"; $as_echo "#define HAVE_GETPAGESIZE 1" >>confdefs.h fi -if test "x$ac_cv_func_snprintf" = "xyes" ; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether snprintf understands %zu" >&5 -printf %s "checking whether snprintf understands %zu... " >&6; } - if test "$cross_compiling" = yes -then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: Assuming working snprintf()" >&5 -printf "%s\n" "$as_me: WARNING: cross compiling: Assuming working snprintf()" >&2;} - -else $as_nop - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -#include -#include -#include -#include - -int -main (void) -{ - - size_t a = 1, b = 2; - char z[128]; - snprintf(z, sizeof z, "%zu%zu", a, b); - exit(strcmp(z, "12")); - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_run "$LINENO" -then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } -else $as_nop - - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } - -printf "%s\n" "#define BROKEN_SNPRINTF 1" >>confdefs.h - - -fi -rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ - conftest.$ac_objext conftest.beam conftest.$ac_ext -fi fi -# We depend on vsnprintf returning the right thing on overflow: the -# number of characters it tried to create (as per SUSv3) -if test "x$ac_cv_func_vsnprintf" = "xyes" ; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether vsnprintf returns correct values on overflow" >&5 -printf %s "checking whether vsnprintf returns correct values on overflow... " >&6; } - if test "$cross_compiling" = yes -then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: Assuming working vsnprintf()" >&5 -printf "%s\n" "$as_me: WARNING: cross compiling: Assuming working vsnprintf()" >&2;} - -else $as_nop - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -#include -#include -#include - -int x_snprintf(char *str, size_t count, const char *fmt, ...) -{ - size_t ret; - va_list ap; - - va_start(ap, fmt); - ret = vsnprintf(str, count, fmt, ap); - va_end(ap); - return ret; -} - -int -main (void) -{ - -char x[1]; -if (x_snprintf(x, 1, "%s %d", "hello", 12345) != 11) - return 1; -if (x_snprintf(NULL, 0, "%s %d", "hello", 12345) != 11) - return 1; -return 0; - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_run "$LINENO" -then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } -else $as_nop - - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } - -printf "%s\n" "#define BROKEN_SNPRINTF 1" >>confdefs.h - - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: ****** Your vsnprintf() function is broken, complain to your vendor" >&5 -printf "%s\n" "$as_me: WARNING: ****** Your vsnprintf() function is broken, complain to your vendor" >&2;} - -fi -rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ - conftest.$ac_objext conftest.beam conftest.$ac_ext -fi - -fi - -# On systems where [v]snprintf is broken, but is declared in stdio, -# check that the fmt argument is const char * or just char *. -# This is only useful for when BROKEN_SNPRINTF -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether snprintf can declare const char *fmt" >&5 -printf %s "checking whether snprintf can declare const char *fmt... " >&6; } -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -#include -int snprintf(char *a, size_t b, const char *c, ...) { return 0; } - -int -main (void) -{ - - snprintf(0, 0, 0); - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO" -then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } - -printf "%s\n" "#define SNPRINTF_CONST const" >>confdefs.h - -else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } - printf "%s\n" "#define SNPRINTF_CONST /* not const */" >>confdefs.h - -fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext # Check for missing getpeereid (or equiv) support NO_PEERCHECK="" if test "x$ac_cv_func_getpeereid" != "xyes" -a "x$ac_cv_func_getpeerucred" != "xyes"; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether system supports SO_PEERCRED getsockopt" >&5 -printf %s "checking whether system supports SO_PEERCRED getsockopt... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether system supports SO_PEERCRED getsockopt" >&5 +$as_echo_n "checking whether system supports SO_PEERCRED getsockopt... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int -main (void) +main () { int i = SO_PEERCRED; ; return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO" -then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } +if ac_fn_c_try_compile "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } -printf "%s\n" "#define HAVE_SO_PEERCRED 1" >>confdefs.h +$as_echo "#define HAVE_SO_PEERCRED 1" >>confdefs.h -else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } NO_PEERCHECK=1 fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi if test ! -z "$check_for_openpty_ctty_bug"; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if openpty correctly handles controlling tty" >&5 -printf %s "checking if openpty correctly handles controlling tty... " >&6; } - if test "$cross_compiling" = yes -then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if openpty correctly handles controlling tty" >&5 +$as_echo_n "checking if openpty correctly handles controlling tty... " >&6; } + if test "$cross_compiling" = yes; then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: cross-compiling, assuming yes" >&5 -printf "%s\n" "cross-compiling, assuming yes" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: cross-compiling, assuming yes" >&5 +$as_echo "cross-compiling, assuming yes" >&6; } -else $as_nop +else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include -#include +#include +#include +#include #include #ifdef HAVE_PTY_H # include #endif -#include -#include -#include int -main (void) +main () { pid_t pid; int fd, ptyfd, ttyfd, status; pid = fork(); - if (pid < 0) { /* failed */ - exit(1); + if (pid == -1) { /* failed */ + return 1; } else if (pid > 0) { /* parent */ waitpid(pid, &status, 0); if (WIFEXITED(status)) - exit(WEXITSTATUS(status)); + return WEXITSTATUS(status); else - exit(2); + return 2; } else { /* child */ close(0); close(1); close(2); setsid(); openpty(&ptyfd, &ttyfd, NULL, NULL, NULL); fd = open("/dev/tty", O_RDWR | O_NOCTTY); - if (fd >= 0) - exit(3); /* Acquired ctty: broken */ - else - exit(0); /* Did not acquire ctty: OK */ + if (fd != -1) + return 3; /* Acquired ctty: broken */ + /*else Did not acquire ctty: OK */ } ; return 0; } _ACEOF -if ac_fn_c_try_run "$LINENO" -then : +if ac_fn_c_try_run "$LINENO"; then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } -else $as_nop +else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } - printf "%s\n" "#define SSHD_ACQUIRES_CTTY 1" >>confdefs.h + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + $as_echo "#define SSHD_ACQUIRES_CTTY 1" >>confdefs.h fi @@ -14931,21 +12714,19 @@ if test "x$ac_cv_func_getaddrinfo" = "xyes" && \ test "x$check_for_hpux_broken_getaddrinfo" = "x1"; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if getaddrinfo seems to work" >&5 -printf %s "checking if getaddrinfo seems to work... " >&6; } - if test "$cross_compiling" = yes -then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if getaddrinfo seems to work" >&5 +$as_echo_n "checking if getaddrinfo seems to work... " >&6; } + if test "$cross_compiling" = yes; then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: cross-compiling, assuming yes" >&5 -printf "%s\n" "cross-compiling, assuming yes" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: cross-compiling, assuming yes" >&5 +$as_echo "cross-compiling, assuming yes" >&6; } -else $as_nop +else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include -#include #include #include #include @@ -14954,7 +12735,7 @@ #define TEST_PORT "2222" int -main (void) +main () { int err, sock; @@ -14969,7 +12750,7 @@ err = getaddrinfo(name, TEST_PORT, &hints, &gai_ai); if (err != 0) { fprintf(stderr, "getaddrinfo failed (%s)", gai_strerror(err)); - exit(1); + return 1; } for (ai = gai_ai; ai != NULL; ai = ai->ai_next) { @@ -14986,34 +12767,32 @@ else fprintf(stderr, "getnameinfo failed: %s\n", gai_strerror(err)); - exit(2); + return 2; } sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); - if (sock < 0) + if (sock == -1) perror("socket"); - if (bind(sock, ai->ai_addr, ai->ai_addrlen) < 0) { + if (bind(sock, ai->ai_addr, ai->ai_addrlen) == -1) { if (errno == EBADF) - exit(3); + return 3; } } - exit(0); ; return 0; } _ACEOF -if ac_fn_c_try_run "$LINENO" -then : +if ac_fn_c_try_run "$LINENO"; then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } -else $as_nop +else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } - printf "%s\n" "#define BROKEN_GETADDRINFO 1" >>confdefs.h + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + $as_echo "#define BROKEN_GETADDRINFO 1" >>confdefs.h fi @@ -15025,21 +12804,19 @@ if test "x$ac_cv_func_getaddrinfo" = "xyes" && \ test "x$check_for_aix_broken_getaddrinfo" = "x1"; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if getaddrinfo seems to work" >&5 -printf %s "checking if getaddrinfo seems to work... " >&6; } - if test "$cross_compiling" = yes -then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if getaddrinfo seems to work" >&5 +$as_echo_n "checking if getaddrinfo seems to work... " >&6; } + if test "$cross_compiling" = yes; then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: cross-compiling, assuming no" >&5 -printf "%s\n" "cross-compiling, assuming no" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: cross-compiling, assuming no" >&5 +$as_echo "cross-compiling, assuming no" >&6; } -else $as_nop +else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include -#include #include #include #include @@ -15048,7 +12825,7 @@ #define TEST_PORT "2222" int -main (void) +main () { int err, sock; @@ -15063,7 +12840,7 @@ err = getaddrinfo(name, TEST_PORT, &hints, &gai_ai); if (err != 0) { fprintf(stderr, "getaddrinfo failed (%s)", gai_strerror(err)); - exit(1); + return 1; } for (ai = gai_ai; ai != NULL; ai = ai->ai_next) { @@ -15076,29 +12853,27 @@ if (ai->ai_family == AF_INET && err != 0) { perror("getnameinfo"); - exit(2); + return 2; } } - exit(0); ; return 0; } _ACEOF -if ac_fn_c_try_run "$LINENO" -then : +if ac_fn_c_try_run "$LINENO"; then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } -printf "%s\n" "#define AIX_GETNAMEINFO_HACK 1" >>confdefs.h +$as_echo "#define AIX_GETNAMEINFO_HACK 1" >>confdefs.h -else $as_nop +else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } - printf "%s\n" "#define BROKEN_GETADDRINFO 1" >>confdefs.h + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + $as_echo "#define BROKEN_GETADDRINFO 1" >>confdefs.h fi @@ -15109,102 +12884,99 @@ fi if test "x$ac_cv_func_getaddrinfo" = "xyes"; then - ac_fn_check_decl "$LINENO" "AI_NUMERICSERV" "ac_cv_have_decl_AI_NUMERICSERV" "#include + ac_fn_c_check_decl "$LINENO" "AI_NUMERICSERV" "ac_cv_have_decl_AI_NUMERICSERV" "#include #include #include -" "$ac_c_undeclared_builtin_options" "CFLAGS" -if test "x$ac_cv_have_decl_AI_NUMERICSERV" = xyes -then : +" +if test "x$ac_cv_have_decl_AI_NUMERICSERV" = xyes; then : ac_have_decl=1 -else $as_nop +else ac_have_decl=0 fi -printf "%s\n" "#define HAVE_DECL_AI_NUMERICSERV $ac_have_decl" >>confdefs.h + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_AI_NUMERICSERV $ac_have_decl +_ACEOF fi if test "x$check_for_conflicting_getspnam" = "x1"; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for conflicting getspnam in shadow.h" >&5 -printf %s "checking for conflicting getspnam in shadow.h... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for conflicting getspnam in shadow.h" >&5 +$as_echo_n "checking for conflicting getspnam in shadow.h... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include -#include int -main (void) +main () { - exit(0); + + ; return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO" -then : +if ac_fn_c_try_compile "$LINENO"; then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } -else $as_nop +else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } -printf "%s\n" "#define GETSPNAM_CONFLICTING_DEFS 1" >>confdefs.h +$as_echo "#define GETSPNAM_CONFLICTING_DEFS 1" >>confdefs.h fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi if test "x$ac_cv_func_strnvis" = "xyes"; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for working strnvis" >&5 -printf %s "checking for working strnvis... " >&6; } - if test "$cross_compiling" = yes -then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: assuming broken" >&5 -printf "%s\n" "$as_me: WARNING: cross compiling: assuming broken" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for working strnvis" >&5 +$as_echo_n "checking for working strnvis... " >&6; } + if test "$cross_compiling" = yes; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: assuming broken" >&5 +$as_echo "$as_me: WARNING: cross compiling: assuming broken" >&2;} -printf "%s\n" "#define BROKEN_STRNVIS 1" >>confdefs.h +$as_echo "#define BROKEN_STRNVIS 1" >>confdefs.h -else $as_nop +else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include -#include #include #include #include static void sighandler(int sig) { _exit(1); } int -main (void) +main () { char dst[16]; signal(SIGSEGV, sighandler); - if (strnvis(dst, "src", 4, 0) && strcmp(dst, "src") == 0) - exit(0); - exit(1) + if (strnvis(dst, "src", 4, 0) != 4 || strcmp(dst, "src") != 0) + return 1; ; return 0; } _ACEOF -if ac_fn_c_try_run "$LINENO" -then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } -else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } +if ac_fn_c_try_run "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } -printf "%s\n" "#define BROKEN_STRNVIS 1" >>confdefs.h +$as_echo "#define BROKEN_STRNVIS 1" >>confdefs.h fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ @@ -15213,14 +12985,15 @@ fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if SA_RESTARTed signals interrupt select()" >&5 -printf %s "checking if SA_RESTARTed signals interrupt select()... " >&6; } -if test "$cross_compiling" = yes -then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: assuming yes" >&5 -printf "%s\n" "$as_me: WARNING: cross compiling: assuming yes" >&2;} +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if restarted signals interrupt select()" >&5 +$as_echo_n "checking if restarted signals interrupt select()... " >&6; } +if ${ssh_cv_sa_restart_work+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "$cross_compiling" = yes; then : + ssh_cv_sa_restart_work=cross -else $as_nop +else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -15228,17 +13001,17 @@ # include #endif #include -#include -#include +#ifdef HAVE_SYS_TIME_H +# include +#endif #include #include static void sighandler(int sig) { } int -main (void) +main () { - int r; pid_t pid; struct sigaction sa; @@ -15252,82 +13025,89 @@ sleep(1); if (getppid() == pid) /* if parent did not exit, shoot it */ kill(pid, SIGKILL); - exit(0); } else { /* parent */ - r = select(0, NULL, NULL, NULL, NULL); + int r = select(0, NULL, NULL, NULL, NULL); + if (r != -1) return 1; } - exit(r == -1 ? 0 : 1); ; return 0; } _ACEOF -if ac_fn_c_try_run "$LINENO" -then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } -else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } - -printf "%s\n" "#define NO_SA_RESTART 1" >>confdefs.h - +if ac_fn_c_try_run "$LINENO"; then : + ssh_cv_sa_restart_work=yes +else + ssh_cv_sa_restart_work=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ssh_cv_sa_restart_work" >&5 +$as_echo "$ssh_cv_sa_restart_work" >&6; } +if test $ssh_cv_sa_restart_work = cross; then : + + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: assuming working restarted signals" >&5 +$as_echo "$as_me: WARNING: cross compiling: assuming working restarted signals" >&2;} + ssh_cv_sa_restart_work=yes + +fi +if test $ssh_cv_sa_restart_work != yes; then : + + +$as_echo "#define BROKEN_SA_RESTART 1" >>confdefs.h - for ac_func in getpgrp +fi + +for ac_func in getpgrp do : ac_fn_c_check_func "$LINENO" "getpgrp" "ac_cv_func_getpgrp" -if test "x$ac_cv_func_getpgrp" = xyes -then : - printf "%s\n" "#define HAVE_GETPGRP 1" >>confdefs.h +if test "x$ac_cv_func_getpgrp" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_GETPGRP 1 +_ACEOF - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if getpgrp accepts zero args" >&5 -printf %s "checking if getpgrp accepts zero args... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if getpgrp accepts zero args" >&5 +$as_echo_n "checking if getpgrp accepts zero args... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_includes_default int -main (void) +main () { getpgrp(); ; return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO" -then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } +if ac_fn_c_try_compile "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } -printf "%s\n" "#define GETPGRP_VOID 1" >>confdefs.h +$as_echo "#define GETPGRP_VOID 1" >>confdefs.h -else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } -printf "%s\n" "#define GETPGRP_VOID 0" >>confdefs.h +$as_echo "#define GETPGRP_VOID 0" >>confdefs.h fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi - done + # Search for OpenSSL saved_CPPFLAGS="$CPPFLAGS" saved_LDFLAGS="$LDFLAGS" -openssl_bin_PATH="$PATH" # Check whether --with-ssl-dir was given. -if test ${with_ssl_dir+y} -then : +if test "${with_ssl_dir+set}" = set; then : withval=$with_ssl_dir; if test "x$openssl" = "xno" ; then as_fn_error $? "cannot use --with-ssl-dir when OpenSSL disabled" "$LINENO" 5 @@ -15337,87 +13117,45 @@ # Relative paths ./*|../*) withval="`pwd`/$withval" esac - if test -d "$withval/lib"; then - libcrypto_path="${withval}/lib" - elif test -d "$withval/lib64"; then + if test -d "$withval/lib64"; then libcrypto_path="$withval/lib64" + elif test -d "$withval/lib"; then + libcrypto_path="$withval/lib" else - # Built but not installed - libcrypto_path="${withval}" + libcrypto_path="$withval" fi - if test -n "${rpath_opt}"; then - LDFLAGS="-L${libcrypto_path} ${rpath_opt}${libcrypto_path} ${LDFLAGS}" + if test -n "$rpath_opt"; then + LDFLAGS="-L$libcrypto_path $rpath_opt$libcrypto_path $LDFLAGS" else - LDFLAGS="-L${libcrypto_path} ${LDFLAGS}" + LDFLAGS="-L$libcrypto_path $LDFLAGS" fi if test -d "$withval/include"; then CPPFLAGS="-I${withval}/include ${CPPFLAGS}" else CPPFLAGS="-I${withval} ${CPPFLAGS}" fi - openssl_bin_PATH="${PATH}${PATH_SEPARATOR}${withval}/bin${PATH_SEPARATOR}${withval}/apps" fi - -fi - -for ac_prog in openssl -do - # Extract the first word of "$ac_prog", so it can be a program name with args. -set dummy $ac_prog; ac_word=$2 -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -printf %s "checking for $ac_word... " >&6; } -if test ${ac_cv_path_openssl_bin+y} -then : - printf %s "(cached) " >&6 -else $as_nop - case $openssl_bin in - [\\/]* | ?:[\\/]*) - ac_cv_path_openssl_bin="$openssl_bin" # Let the user override the test with a path. - ;; - *) - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $openssl_bin_PATH -do - IFS=$as_save_IFS - case $as_dir in #((( - '') as_dir=./ ;; - */) ;; - *) as_dir=$as_dir/ ;; - esac - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then - ac_cv_path_openssl_bin="$as_dir$ac_word$ac_exec_ext" - printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - - ;; -esac -fi -openssl_bin=$ac_cv_path_openssl_bin -if test -n "$openssl_bin"; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $openssl_bin" >&5 -printf "%s\n" "$openssl_bin" >&6; } else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } -fi + if test -d /usr/local/ssl/lib ; then + if test -n "${need_dash_r}"; then + LDFLAGS="-L/usr/local/ssl/lib -R/usr/local/ssl/lib $LDFLAGS" + else + LDFLAGS="-L/usr/local/ssl/lib $LDFLAGS" + fi + fi + if test -d /usr/local/ssl/include ; then + CPPFLAGS="-I/usr/local/ssl/include $CPPFLAGS" + fi - test -n "$openssl_bin" && break -done -OPENSSL_BIN=${openssl_bin} +fi # Check whether --with-openssl-header-check was given. -if test ${with_openssl_header_check+y} -then : +if test "${with_openssl_header_check+set}" = set; then : withval=$with_openssl_header_check; if test "x$withval" = "xno" ; then openssl_check_nonfatal=1 @@ -15427,112 +13165,267 @@ fi -openssl_engine=no # Check whether --with-ssl-engine was given. -if test ${with_ssl_engine+y} -then : +if test "${with_ssl_engine+set}" = set; then : withval=$with_ssl_engine; - if test "x$withval" != "xno" ; then - if test "x$openssl" = "xno" ; then - as_fn_error $? "cannot use --with-ssl-engine when OpenSSL disabled" "$LINENO" 5 - fi - openssl_engine=yes - fi +else + with_ssl_engine=check + +fi +# enable/disable OCSP requests +ssh_ocsp=: +# Check whether --enable-ocsp was given. +if test "${enable_ocsp+set}" = set; then : + enableval=$enable_ocsp; if test "x$enableval" = "xno"; then : + ssh_ocsp=false fi +fi + + +# Where to place ssh CA root +sshcadir='${sysconfdir}/ca' +sshcadir=`eval echo ${sshcadir}` +sshcadir=`eval echo ${sshcadir}` +case $sshcadir in + NONE/*) sshcadir=`echo $sshcadir | sed "s~NONE~$ac_default_prefix~"` ;; +esac + + +# Check whether --with-sshca-dir was given. +if test "${with_sshca_dir+set}" = set; then : + withval=$with_sshca_dir; + if test "x$withval" != "xno"; then : + + sshcadir=$withval + +fi + + +fi + + + +cat >>confdefs.h <<_ACEOF +#define SSHCADIR "$sshcadir" +_ACEOF + + + +# reserved for future removal +COMMENT_OUT_DSA= + + +COMMENT_OUT_ECC="#no ecc#" +COMMENT_OUT_ECC256="#no ecc256#" +COMMENT_OUT_ECC384="#no ecc384#" +COMMENT_OUT_ECC521="#no ecc521#" + + + + + +# OpenSSL >= 1.1.1 +COMMENT_OUT_ED25519="#no ed25519#" -nocrypto_saved_LIBS="$LIBS" if test "x$openssl" = "xyes" ; then - LIBS="-lcrypto $LIBS" - CHANNELLIBS="-lcrypto $CHANNELLIBS" + + save_LIBS="$LIBS" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to link programs using OpenSSL functions" >&5 +$as_echo_n "checking how to link programs using OpenSSL functions... " >&6; } + ac_CRYPTO_LINK=false + for L in "" "-ldl" "-lpthread" "-lpthread -ldl" ; do + LIBS="-lcrypto $L $save_LIBS" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include + +int +main () +{ + +/* "OpenSSL_add_all_algorithms" is macro existing in 1.1.0 + * only for backward compatibility, i.e. some builds could + * deprecate it. + OpenSSL_add_all_algorithms(); */ + EVP_add_cipher(NULL); + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_CRYPTO_LINK=: +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + $ac_CRYPTO_LINK && break + done + if $ac_CRYPTO_LINK ; then + CRYPTO_LIBS="-lcrypto $L" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CRYPTO_LIBS" >&5 +$as_echo "$CRYPTO_LIBS" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: fail" >&5 +$as_echo "fail" >&6; } + as_fn_error $? "cannot link with OpenSSL crypto library" "$LINENO" 5 + fi + LIBS="$CRYPTO_LIBS $save_LIBS" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif char RAND_add (); int -main (void) +main () { return RAND_add (); ; return 0; } _ACEOF -if ac_fn_c_try_link "$LINENO" -then : +if ac_fn_c_try_link "$LINENO"; then : + +$as_echo "#define HAVE_OPENSSL 1" >>confdefs.h + +else + + ac_fn_c_check_header_mongrel "$LINENO" "openssl/opensslv.h" "ac_cv_header_openssl_opensslv_h" "$ac_includes_default" +if test "x$ac_cv_header_openssl_opensslv_h" = xyes; then : + +else + as_fn_error $? "*** OpenSSL headers missing - please install first or check config.log ***" "$LINENO" 5 +fi + + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char RAND_add (); +int +main () +{ +return RAND_add (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + $as_echo "#define HAVE_OPENSSL 1" >>confdefs.h + +else + + as_fn_error $? "*** Can't find recent OpenSSL libcrypto (see config.log for details) ***" "$LINENO" 5 + -else $as_nop - as_fn_error $? "*** working libcrypto not found, check config.log" "$LINENO" 5 fi -rm -f core conftest.err conftest.$ac_objext conftest.beam \ +rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext - ac_fn_c_check_header_compile "$LINENO" "openssl/opensslv.h" "ac_cv_header_openssl_opensslv_h" "$ac_includes_default" -if test "x$ac_cv_header_openssl_opensslv_h" = xyes -then : -else $as_nop - as_fn_error $? "*** OpenSSL headers missing - please install first or check config.log ***" "$LINENO" 5 + fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + + # check for OpenSSL 1.1 API + for ac_func in OPENSSL_init_crypto +do : + ac_fn_c_check_func "$LINENO" "OPENSSL_init_crypto" "ac_cv_func_OPENSSL_init_crypto" +if test "x$ac_cv_func_OPENSSL_init_crypto" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_OPENSSL_INIT_CRYPTO 1 +_ACEOF + +fi +done + + + # check for new OpenSSL version scheme (3.0 API) + for ac_func in OPENSSL_version_major +do : + ac_fn_c_check_func "$LINENO" "OPENSSL_version_major" "ac_cv_func_OPENSSL_version_major" +if test "x$ac_cv_func_OPENSSL_version_major" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_OPENSSL_VERSION_MAJOR 1 +_ACEOF + +fi +done # Determine OpenSSL header version - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking OpenSSL header version" >&5 -printf %s "checking OpenSSL header version... " >&6; } - if test "$cross_compiling" = yes -then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking OpenSSL header version" >&5 +$as_echo_n "checking OpenSSL header version... " >&6; } + if test "$cross_compiling" = yes; then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: not checking" >&5 -printf "%s\n" "$as_me: WARNING: cross compiling: not checking" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: not checking" >&5 +$as_echo "$as_me: WARNING: cross compiling: not checking" >&2;} -else $as_nop +else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ - #include #include #include - #include + #include #define DATA "conftest.sslincver" int -main (void) +main () { FILE *fd; int rc; + const char *ver_s = OPENSSL_VERSION_TEXT; fd = fopen(DATA,"w"); - if(fd == NULL) - exit(1); - - if ((rc = fprintf(fd, "%08lx (%s)\n", - (unsigned long)OPENSSL_VERSION_NUMBER, - OPENSSL_VERSION_TEXT)) < 0) - exit(1); - - exit(0); + if (fd == NULL) return 1; + #ifdef HAVE_OPENSSL_VERSION_MAJOR + rc = fprintf(fd, "%u.%u.%u (%s)\n", + (unsigned)OPENSSL_VERSION_MAJOR, + (unsigned)OPENSSL_VERSION_MINOR, + (unsigned)OPENSSL_VERSION_PATCH, + ver_s); + #else + { + unsigned long ver_num = OPENSSL_VERSION_NUMBER; + rc = fprintf(fd, "%08lx (%s)\n", ver_num, ver_s); + } + #endif + fclose(fd); + if (rc < 0) return 1; ; return 0; } _ACEOF -if ac_fn_c_try_run "$LINENO" -then : +if ac_fn_c_try_run "$LINENO"; then : ssl_header_ver=`cat conftest.sslincver` - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ssl_header_ver" >&5 -printf "%s\n" "$ssl_header_ver" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ssl_header_ver" >&5 +$as_echo "$ssl_header_ver" >&6; } -else $as_nop +else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: not found" >&5 -printf "%s\n" "not found" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5 +$as_echo "not found" >&6; } as_fn_error $? "OpenSSL version header not found." "$LINENO" 5 fi @@ -15541,114 +13434,72 @@ fi - # Determining OpenSSL library version is version dependent. - ac_fn_c_check_func "$LINENO" "OpenSSL_version" "ac_cv_func_OpenSSL_version" -if test "x$ac_cv_func_OpenSSL_version" = xyes -then : - printf "%s\n" "#define HAVE_OPENSSL_VERSION 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "OpenSSL_version_num" "ac_cv_func_OpenSSL_version_num" -if test "x$ac_cv_func_OpenSSL_version_num" = xyes -then : - printf "%s\n" "#define HAVE_OPENSSL_VERSION_NUM 1" >>confdefs.h - -fi - - # Determine OpenSSL library version - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking OpenSSL library version" >&5 -printf %s "checking OpenSSL library version... " >&6; } - if test "$cross_compiling" = yes -then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking OpenSSL library version" >&5 +$as_echo_n "checking OpenSSL library version... " >&6; } + if test "$cross_compiling" = yes; then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: not checking" >&5 -printf "%s\n" "$as_me: WARNING: cross compiling: not checking" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: not checking" >&5 +$as_echo "$as_me: WARNING: cross compiling: not checking" >&2;} -else $as_nop +else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include - #include - #include - #include #include #define DATA "conftest.ssllibver" int -main (void) +main () { - FILE *f; - /* We need these legacy bits to warn for old libcrypto */ - #ifndef OPENSSL_VERSION - # define OPENSSL_VERSION SSLEAY_VERSION - #endif - #ifndef HAVE_OPENSSL_VERSION - # define OpenSSL_version SSLeay_version - #endif - #ifndef HAVE_OPENSSL_VERSION_NUM - # define OpenSSL_version_num SSLeay - #endif - if ((f = fopen(DATA, "w")) == NULL) - exit(1); - if (fprintf(f, "%08lx (%s)", - (unsigned long)OpenSSL_version_num(), - OpenSSL_version(OPENSSL_VERSION)) < 0) - exit(1); -#ifdef LIBRESSL_VERSION_NUMBER - if (fprintf(f, " libressl-%08lx", LIBRESSL_VERSION_NUMBER) < 0) - exit(1); -#endif - if (fputc('\n', f) == EOF || fclose(f) == EOF) - exit(1); - exit(0); + FILE *fd; + int rc; + const char *ver_s; + #ifdef HAVE_OPENSSL_INIT_CRYPTO + ver_s = OpenSSL_version(OPENSSL_VERSION); + #else + ver_s = SSLeay_version(SSLEAY_VERSION); + #endif + + fd = fopen(DATA,"w"); + if (fd == NULL) return 1; + #ifdef HAVE_OPENSSL_VERSION_MAJOR + rc = fprintf(fd, "%u.%u.%u (%s)\n", + OPENSSL_version_major(), + OPENSSL_version_minor(), + OPENSSL_version_patch(), + ver_s); + #else + { + unsigned long ver_num; + #ifdef HAVE_OPENSSL_INIT_CRYPTO + ver_num = OpenSSL_version_num(); + #else + ver_num = SSLeay(); + #endif + rc = fprintf(fd, "%08lx (%s)\n", ver_num, ver_s); + } + #endif + fclose(fd); + if (rc < 0) return 1; ; return 0; } _ACEOF -if ac_fn_c_try_run "$LINENO" -then : - - sslver=`cat conftest.ssllibver` - ssl_showver=`echo "$sslver" | sed 's/ libressl-.*//'` - # Check version is supported. - case "$sslver" in - 100*|10100*) # 1.0.x, 1.1.0x - as_fn_error $? "OpenSSL >= 1.1.1 required (have \"$ssl_showver\")" "$LINENO" 5 - ;; - 101*) ;; # 1.1.x - 200*) # LibreSSL - lver=`echo "$sslver" | sed 's/.*libressl-//'` - case "$lver" in - 2*|300*) # 2.x, 3.0.0 - as_fn_error $? "LibreSSL >= 3.1.0 required (have \"$ssl_showver\")" "$LINENO" 5 - ;; - *) ;; # Assume all other versions are good. - esac - ;; - 300*) - # OpenSSL 3; we use the 1.1x API - CPPFLAGS="$CPPFLAGS -DOPENSSL_API_COMPAT=0x10100000L" - ;; - 301*|302*) - # OpenSSL development branch; request 1.1x API - CPPFLAGS="$CPPFLAGS -DOPENSSL_API_COMPAT=0x10100000L" - ;; - *) - as_fn_error $? "Unknown/unsupported OpenSSL version (\"$ssl_showver\")" "$LINENO" 5 - ;; - esac - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ssl_showver" >&5 -printf "%s\n" "$ssl_showver" >&6; } +if ac_fn_c_try_run "$LINENO"; then : -else $as_nop + ssl_library_ver=`cat conftest.ssllibver` + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ssl_library_ver" >&5 +$as_echo "$ssl_library_ver" >&6; } - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: not found" >&5 -printf "%s\n" "not found" >&6; } +else + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5 +$as_echo "not found" >&6; } as_fn_error $? "OpenSSL library not found." "$LINENO" 5 fi @@ -15657,68 +13508,65 @@ fi - case "$host" in - x86_64-*) - case "$sslver" in - 3000004*) - as_fn_error $? "OpenSSL 3.0.4 has a potential RCE in its RSA implementation (CVE-2022-2274)" "$LINENO" 5 - ;; - esac - esac - # Sanity check OpenSSL headers - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether OpenSSL's headers match the library" >&5 -printf %s "checking whether OpenSSL's headers match the library... " >&6; } - if test "$cross_compiling" = yes -then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether OpenSSL's headers match the library" >&5 +$as_echo_n "checking whether OpenSSL's headers match the library... " >&6; } + if test "$cross_compiling" = yes; then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: not checking" >&5 -printf "%s\n" "$as_me: WARNING: cross compiling: not checking" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: not checking" >&5 +$as_echo "$as_me: WARNING: cross compiling: not checking" >&2;} -else $as_nop +else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ - #include - #include - #include #include int -main (void) +main () { - exit(OpenSSL_version_num() == OPENSSL_VERSION_NUMBER ? 0 : 1); + #ifdef HAVE_OPENSSL_VERSION_MAJOR + if (OPENSSL_version_major() != OPENSSL_VERSION_MAJOR) return 1; + if (OPENSSL_version_minor() != OPENSSL_VERSION_MINOR) return 1; + if (OPENSSL_version_patch() != OPENSSL_VERSION_PATCH) return 1; + #else + { + unsigned long ver_num; + #ifdef HAVE_OPENSSL_INIT_CRYPTO + ver_num = OpenSSL_version_num(); + #else + ver_num = SSLeay(); + #endif + if (ver_num != OPENSSL_VERSION_NUMBER) return 1; + } + #endif ; return 0; } _ACEOF -if ac_fn_c_try_run "$LINENO" -then : +if ac_fn_c_try_run "$LINENO"; then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } -else $as_nop +else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } if test "x$openssl_check_nonfatal" = "x"; then as_fn_error $? "Your OpenSSL headers do not match your library. Check config.log for details. If you are sure your installation is consistent, you can disable the check by running \"./configure --without-openssl-header-check\". - Also see contrib/findssl.sh for help identifying header/library mismatches. " "$LINENO" 5 else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: Your OpenSSL headers do not match your - library. Check config.log for details. - Also see contrib/findssl.sh for help identifying header/library mismatches." >&5 -printf "%s\n" "$as_me: WARNING: Your OpenSSL headers do not match your - library. Check config.log for details. - Also see contrib/findssl.sh for help identifying header/library mismatches." >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Your OpenSSL headers do not match your + library. Check config.log for details." >&5 +$as_echo "$as_me: WARNING: Your OpenSSL headers do not match your + library. Check config.log for details." >&2;} fi fi @@ -15727,329 +13575,203 @@ fi - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if programs using OpenSSL functions will link" >&5 -printf %s "checking if programs using OpenSSL functions will link... " >&6; } - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - #include -int -main (void) -{ - ERR_load_crypto_strings(); - ; - return 0; -} + if test "x$with_ssl_engine" != "xno" ; then + for ac_header in openssl/engine.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "openssl/engine.h" "ac_cv_header_openssl_engine_h" "$ac_includes_default" +if test "x$ac_cv_header_openssl_engine_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_OPENSSL_ENGINE_H 1 _ACEOF -if ac_fn_c_try_link "$LINENO" -then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } +fi -else $as_nop +done - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } - LIBS="$LIBS -ldl" - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if programs using OpenSSL need -ldl" >&5 -printf %s "checking if programs using OpenSSL need -ldl... " >&6; } - cat confdefs.h - <<_ACEOF >conftest.$ac_ext + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for OpenSSL ENGINE support" >&5 +$as_echo_n "checking for OpenSSL ENGINE support... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ - #include + + #include + int -main (void) +main () { - ERR_load_crypto_strings(); + + ENGINE_load_builtin_engines(); + ENGINE_register_all_complete(); + ; return 0; } _ACEOF -if ac_fn_c_try_link "$LINENO" -then : - - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } - CHANNELLIBS="$CHANNELLIBS -ldl" - -else $as_nop - - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } - - -fi -rm -f core conftest.err conftest.$ac_objext conftest.beam \ - conftest$ac_exeext conftest.$ac_ext - - -fi -rm -f core conftest.err conftest.$ac_objext conftest.beam \ - conftest$ac_exeext conftest.$ac_ext - - ac_fn_c_check_func "$LINENO" "BN_is_prime_ex" "ac_cv_func_BN_is_prime_ex" -if test "x$ac_cv_func_BN_is_prime_ex" = xyes -then : - printf "%s\n" "#define HAVE_BN_IS_PRIME_EX 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "DES_crypt" "ac_cv_func_DES_crypt" -if test "x$ac_cv_func_DES_crypt" = xyes -then : - printf "%s\n" "#define HAVE_DES_CRYPT 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "DSA_generate_parameters_ex" "ac_cv_func_DSA_generate_parameters_ex" -if test "x$ac_cv_func_DSA_generate_parameters_ex" = xyes -then : - printf "%s\n" "#define HAVE_DSA_GENERATE_PARAMETERS_EX 1" >>confdefs.h +if ac_fn_c_try_compile "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } -fi -ac_fn_c_check_func "$LINENO" "EVP_DigestFinal_ex" "ac_cv_func_EVP_DigestFinal_ex" -if test "x$ac_cv_func_EVP_DigestFinal_ex" = xyes -then : - printf "%s\n" "#define HAVE_EVP_DIGESTFINAL_EX 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "EVP_DigestInit_ex" "ac_cv_func_EVP_DigestInit_ex" -if test "x$ac_cv_func_EVP_DigestInit_ex" = xyes -then : - printf "%s\n" "#define HAVE_EVP_DIGESTINIT_EX 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "EVP_MD_CTX_cleanup" "ac_cv_func_EVP_MD_CTX_cleanup" -if test "x$ac_cv_func_EVP_MD_CTX_cleanup" = xyes -then : - printf "%s\n" "#define HAVE_EVP_MD_CTX_CLEANUP 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "EVP_MD_CTX_copy_ex" "ac_cv_func_EVP_MD_CTX_copy_ex" -if test "x$ac_cv_func_EVP_MD_CTX_copy_ex" = xyes -then : - printf "%s\n" "#define HAVE_EVP_MD_CTX_COPY_EX 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "EVP_MD_CTX_init" "ac_cv_func_EVP_MD_CTX_init" -if test "x$ac_cv_func_EVP_MD_CTX_init" = xyes -then : - printf "%s\n" "#define HAVE_EVP_MD_CTX_INIT 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "HMAC_CTX_init" "ac_cv_func_HMAC_CTX_init" -if test "x$ac_cv_func_HMAC_CTX_init" = xyes -then : - printf "%s\n" "#define HAVE_HMAC_CTX_INIT 1" >>confdefs.h +$as_echo "#define USE_OPENSSL_ENGINE 1" >>confdefs.h -fi -ac_fn_c_check_func "$LINENO" "RSA_generate_key_ex" "ac_cv_func_RSA_generate_key_ex" -if test "x$ac_cv_func_RSA_generate_key_ex" = xyes -then : - printf "%s\n" "#define HAVE_RSA_GENERATE_KEY_EX 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "RSA_get_default_method" "ac_cv_func_RSA_get_default_method" -if test "x$ac_cv_func_RSA_get_default_method" = xyes -then : - printf "%s\n" "#define HAVE_RSA_GET_DEFAULT_METHOD 1" >>confdefs.h - -fi - - - # OpenSSL_add_all_algorithms may be a macro. - ac_fn_c_check_func "$LINENO" "OpenSSL_add_all_algorithms" "ac_cv_func_OpenSSL_add_all_algorithms" -if test "x$ac_cv_func_OpenSSL_add_all_algorithms" = xyes -then : - -printf "%s\n" "#define HAVE_OPENSSL_ADD_ALL_ALGORITHMS 1" >>confdefs.h - -else $as_nop - ac_fn_check_decl "$LINENO" "OpenSSL_add_all_algorithms" "ac_cv_have_decl_OpenSSL_add_all_algorithms" "#include - -" "$ac_c_undeclared_builtin_options" "CFLAGS" -if test "x$ac_cv_have_decl_OpenSSL_add_all_algorithms" = xyes -then : - -printf "%s\n" "#define HAVE_OPENSSL_ADD_ALL_ALGORITHMS 1" >>confdefs.h - -fi - -fi - - - # LibreSSL/OpenSSL API differences - ac_fn_c_check_func "$LINENO" "EVP_CIPHER_CTX_iv" "ac_cv_func_EVP_CIPHER_CTX_iv" -if test "x$ac_cv_func_EVP_CIPHER_CTX_iv" = xyes -then : - printf "%s\n" "#define HAVE_EVP_CIPHER_CTX_IV 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "EVP_CIPHER_CTX_iv_noconst" "ac_cv_func_EVP_CIPHER_CTX_iv_noconst" -if test "x$ac_cv_func_EVP_CIPHER_CTX_iv_noconst" = xyes -then : - printf "%s\n" "#define HAVE_EVP_CIPHER_CTX_IV_NOCONST 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "EVP_CIPHER_CTX_get_iv" "ac_cv_func_EVP_CIPHER_CTX_get_iv" -if test "x$ac_cv_func_EVP_CIPHER_CTX_get_iv" = xyes -then : - printf "%s\n" "#define HAVE_EVP_CIPHER_CTX_GET_IV 1" >>confdefs.h -fi -ac_fn_c_check_func "$LINENO" "EVP_CIPHER_CTX_get_updated_iv" "ac_cv_func_EVP_CIPHER_CTX_get_updated_iv" -if test "x$ac_cv_func_EVP_CIPHER_CTX_get_updated_iv" = xyes -then : - printf "%s\n" "#define HAVE_EVP_CIPHER_CTX_GET_UPDATED_IV 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "EVP_CIPHER_CTX_set_iv" "ac_cv_func_EVP_CIPHER_CTX_set_iv" -if test "x$ac_cv_func_EVP_CIPHER_CTX_set_iv" = xyes -then : - printf "%s\n" "#define HAVE_EVP_CIPHER_CTX_SET_IV 1" >>confdefs.h +else + as_fn_error $? "OpenSSL ENGINE support not found" "$LINENO" 5 fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + fi - - if test "x$openssl_engine" = "xyes" ; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for OpenSSL ENGINE support" >&5 -printf %s "checking for OpenSSL ENGINE support... " >&6; } - cat confdefs.h - <<_ACEOF >conftest.$ac_ext + # Check for OpenSSL without EVP_aes_{192,256}_cbc + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether OpenSSL has crippled AES support" >&5 +$as_echo_n "checking whether OpenSSL has crippled AES support... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ - #include + #include int -main (void) +main () { - ENGINE_load_builtin_engines(); - ENGINE_register_all_complete(); + if (EVP_aes_192_cbc() == NULL || + EVP_aes_256_cbc() == NULL) + return 1; ; return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO" -then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } +if ac_fn_c_try_link "$LINENO"; then : -printf "%s\n" "#define USE_OPENSSL_ENGINE 1" >>confdefs.h + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +else + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +$as_echo "#define OPENSSL_LOBOTOMISED_AES 1" >>confdefs.h -else $as_nop - as_fn_error $? "OpenSSL ENGINE support not found" "$LINENO" 5 fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext - fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext - # Check for OpenSSL without EVP_aes_{192,256}_cbc - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether OpenSSL has crippled AES support" >&5 -printf %s "checking whether OpenSSL has crippled AES support... " >&6; } + # Check for OpenSSL with EVP_aes_*ctr + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether OpenSSL has AES CTR via EVP" >&5 +$as_echo_n "checking whether OpenSSL has AES CTR via EVP... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ - #include - #include #include int -main (void) +main () { - exit(EVP_aes_192_cbc() == NULL || EVP_aes_256_cbc() == NULL); + if (EVP_aes_128_ctr() == NULL || + EVP_aes_192_ctr() == NULL || + EVP_aes_256_ctr() == NULL) + return 1; ; return 0; } _ACEOF -if ac_fn_c_try_link "$LINENO" -then : +if ac_fn_c_try_link "$LINENO"; then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } -else $as_nop +$as_echo "#define OPENSSL_HAVE_EVPCTR 1" >>confdefs.h - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } -printf "%s\n" "#define OPENSSL_LOBOTOMISED_AES 1" >>confdefs.h +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } fi -rm -f core conftest.err conftest.$ac_objext conftest.beam \ +rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if EVP_DigestUpdate returns an int" >&5 -printf %s "checking if EVP_DigestUpdate returns an int... " >&6; } + # Check for OpenSSL with EVP_aes_*gcm + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether OpenSSL has AES GCM via EVP" >&5 +$as_echo_n "checking whether OpenSSL has AES GCM via EVP... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ - #include - #include #include int -main (void) +main () { - if(EVP_DigestUpdate(NULL, NULL,0)) - exit(0); + if (EVP_aes_128_gcm() == NULL || + EVP_aes_256_gcm() == NULL || + EVP_CTRL_GCM_SET_IV_FIXED == 0 || + EVP_CTRL_GCM_IV_GEN == 0 || + EVP_CTRL_GCM_SET_TAG == 0 || + EVP_CTRL_GCM_GET_TAG == 0 || + EVP_CIPHER_CTX_ctrl(NULL, 0, 0, NULL) == 0) + return 1; ; return 0; } _ACEOF -if ac_fn_c_try_link "$LINENO" -then : +if ac_fn_c_try_link "$LINENO"; then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } -else $as_nop +$as_echo "#define OPENSSL_HAVE_EVPGCM 1" >>confdefs.h - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } -printf "%s\n" "#define OPENSSL_EVP_DIGESTUPDATE_VOID 1" >>confdefs.h +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + unsupported_algorithms="$unsupported_cipers \ + aes128-gcm@openssh.com \ + aes256-gcm@openssh.com" fi -rm -f core conftest.err conftest.$ac_objext conftest.beam \ +rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext - # Check for various EVP support in OpenSSL - ac_fn_c_check_func "$LINENO" "EVP_sha256" "ac_cv_func_EVP_sha256" -if test "x$ac_cv_func_EVP_sha256" = xyes -then : - printf "%s\n" "#define HAVE_EVP_SHA256 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "EVP_sha384" "ac_cv_func_EVP_sha384" -if test "x$ac_cv_func_EVP_sha384" = xyes -then : - printf "%s\n" "#define HAVE_EVP_SHA384 1" >>confdefs.h + # Check for SHA256, SHA384 and SHA512 support in OpenSSL + for ac_func in EVP_sha256 EVP_sha384 EVP_sha512 +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF -fi -ac_fn_c_check_func "$LINENO" "EVP_sha512" "ac_cv_func_EVP_sha512" -if test "x$ac_cv_func_EVP_sha512" = xyes -then : - printf "%s\n" "#define HAVE_EVP_SHA512 1" >>confdefs.h +else + unsupported_algorithms="$unsupported_algorithms \ + hmac-sha2-256 \ + hmac-sha2-512 \ + diffie-hellman-group14-sha256 \ + diffie-hellman-group16-sha512 \ + diffie-hellman-group18-sha512 \ + diffie-hellman-group-exchange-sha256 \ + hmac-sha2-256-etm@openssh.com \ + hmac-sha2-512-etm@openssh.com" -fi -ac_fn_c_check_func "$LINENO" "EVP_chacha20" "ac_cv_func_EVP_chacha20" -if test "x$ac_cv_func_EVP_chacha20" = xyes -then : - printf "%s\n" "#define HAVE_EVP_CHACHA20 1" >>confdefs.h fi +done # Check complete ECC support in OpenSSL - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether OpenSSL has NID_X9_62_prime256v1" >&5 -printf %s "checking whether OpenSSL has NID_X9_62_prime256v1... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether OpenSSL has NID_X9_62_prime256v1" >&5 +$as_echo_n "checking whether OpenSSL has NID_X9_62_prime256v1... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -16059,9 +13781,19 @@ #include #include #include + #ifndef HAVE_OPENSSL_INIT_CRYPTO /* < 1.1.0 */ + #if OPENSSL_VERSION_NUMBER < 0x0090807f /* 0.9.8g */ + # error "OpenSSL < 0.9.8g has unreliable ECC code" + #endif + #ifdef OPENSSL_FIPS + # if OPENSSL_VERSION_NUMBER < 0x00908fff /* 0.9.8* */ + # error "OpenSSL <= 0.9.8* has unreliable ECC code in FIPS build" + # endif + #endif + #endif int -main (void) +main () { EC_KEY *e = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); @@ -16071,21 +13803,20 @@ return 0; } _ACEOF -if ac_fn_c_try_link "$LINENO" -then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } +if ac_fn_c_try_link "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } enable_nistp256=1 -else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } fi -rm -f core conftest.err conftest.$ac_objext conftest.beam \ +rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether OpenSSL has NID_secp384r1" >&5 -printf %s "checking whether OpenSSL has NID_secp384r1... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether OpenSSL has NID_secp384r1" >&5 +$as_echo_n "checking whether OpenSSL has NID_secp384r1... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -16095,9 +13826,19 @@ #include #include #include + #ifndef HAVE_OPENSSL_INIT_CRYPTO /* < 1.1.0 */ + #if OPENSSL_VERSION_NUMBER < 0x0090807f /* 0.9.8g */ + # error "OpenSSL < 0.9.8g has unreliable ECC code" + #endif + #ifdef OPENSSL_FIPS + # if OPENSSL_VERSION_NUMBER < 0x00908fff /* 0.9.8* */ + # error "OpenSSL <= 0.9.8* has unreliable ECC code in FIPS build" + # endif + #endif + #endif int -main (void) +main () { EC_KEY *e = EC_KEY_new_by_curve_name(NID_secp384r1); @@ -16107,21 +13848,20 @@ return 0; } _ACEOF -if ac_fn_c_try_link "$LINENO" -then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } +if ac_fn_c_try_link "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } enable_nistp384=1 -else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } fi -rm -f core conftest.err conftest.$ac_objext conftest.beam \ +rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether OpenSSL has NID_secp521r1" >&5 -printf %s "checking whether OpenSSL has NID_secp521r1... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether OpenSSL has NID_secp521r1" >&5 +$as_echo_n "checking whether OpenSSL has NID_secp521r1... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -16131,9 +13871,19 @@ #include #include #include + #ifndef HAVE_OPENSSL_INIT_CRYPTO /* < 1.1.0 */ + #if OPENSSL_VERSION_NUMBER < 0x0090807f /* 0.9.8g */ + # error "OpenSSL < 0.9.8g has unreliable ECC code" + #endif + #ifdef OPENSSL_FIPS + # if OPENSSL_VERSION_NUMBER < 0x00908fff /* 0.9.8* */ + # error "OpenSSL <= 0.9.8* has unreliable ECC code in FIPS build" + # endif + #endif + #endif int -main (void) +main () { EC_KEY *e = EC_KEY_new_by_curve_name(NID_secp521r1); @@ -16143,23 +13893,22 @@ return 0; } _ACEOF -if ac_fn_c_try_link "$LINENO" -then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if OpenSSL's NID_secp521r1 is functional" >&5 -printf %s "checking if OpenSSL's NID_secp521r1 is functional... " >&6; } - if test "$cross_compiling" = yes -then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cross-compiling: assuming yes" >&5 -printf "%s\n" "$as_me: WARNING: cross-compiling: assuming yes" >&2;} - enable_nistp521=1 +if ac_fn_c_try_link "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if OpenSSL's curve secp521r1 is functional" >&5 +$as_echo_n "checking if OpenSSL's curve secp521r1 is functional... " >&6; } +if ${ssh_cv_working_secp521r1+:} false; then : + $as_echo_n "(cached) " >&6 +else + + if test "$cross_compiling" = yes; then : + ssh_cv_working_secp521r1=cross -else $as_nop +else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ - #include #include #include #include @@ -16168,58 +13917,62 @@ #include int -main (void) +main () { + int ret = 0; EC_KEY *e = EC_KEY_new_by_curve_name(NID_secp521r1); const EVP_MD *m = EVP_sha512(); /* We need this too */ - exit(e == NULL || m == NULL); + if (e == NULL || m == NULL) + ret = 1; + EC_KEY_free(e); + return ret; ; return 0; } _ACEOF -if ac_fn_c_try_run "$LINENO" -then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } - enable_nistp521=1 -else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } +if ac_fn_c_try_run "$LINENO"; then : + ssh_cv_working_secp521r1=yes +else + ssh_cv_working_secp521r1=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi -else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ssh_cv_working_secp521r1" >&5 +$as_echo "$ssh_cv_working_secp521r1" >&6; } + if test "x$ssh_cv_working_secp521r1" = xcross ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: assuming functional secp521r1 curve" >&5 +$as_echo "$as_me: WARNING: cross compiling: assuming functional secp521r1 curve" >&2;} + ssh_cv_working_secp521r1=yes + fi + if test "x$ssh_cv_working_secp521r1" = xyes ; then + enable_nistp521=1 + fi + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } fi -rm -f core conftest.err conftest.$ac_objext conftest.beam \ +rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test x$enable_nistp256 = x1 || test x$enable_nistp384 = x1 || \ test x$enable_nistp521 = x1; then -printf "%s\n" "#define OPENSSL_HAS_ECC 1" >>confdefs.h +$as_echo "#define OPENSSL_HAS_ECC 1" >>confdefs.h - ac_fn_c_check_func "$LINENO" "EC_KEY_METHOD_new" "ac_cv_func_EC_KEY_METHOD_new" -if test "x$ac_cv_func_EC_KEY_METHOD_new" = xyes -then : - printf "%s\n" "#define HAVE_EC_KEY_METHOD_NEW 1" >>confdefs.h - -fi - - openssl_ecc=yes - else - openssl_ecc=no fi if test x$enable_nistp256 = x1; then -printf "%s\n" "#define OPENSSL_HAS_NISTP256 1" >>confdefs.h +$as_echo "#define OPENSSL_HAS_NISTP256 1" >>confdefs.h + COMMENT_OUT_ECC= + COMMENT_OUT_ECC256= else unsupported_algorithms="$unsupported_algorithms \ ecdsa-sha2-nistp256 \ @@ -16228,8 +13981,10 @@ fi if test x$enable_nistp384 = x1; then -printf "%s\n" "#define OPENSSL_HAS_NISTP384 1" >>confdefs.h +$as_echo "#define OPENSSL_HAS_NISTP384 1" >>confdefs.h + COMMENT_OUT_ECC= + COMMENT_OUT_ECC384= else unsupported_algorithms="$unsupported_algorithms \ ecdsa-sha2-nistp384 \ @@ -16238,302 +13993,908 @@ fi if test x$enable_nistp521 = x1; then -printf "%s\n" "#define OPENSSL_HAS_NISTP521 1" >>confdefs.h +$as_echo "#define OPENSSL_HAS_NISTP521 1" >>confdefs.h + COMMENT_OUT_ECC= + COMMENT_OUT_ECC521= else unsupported_algorithms="$unsupported_algorithms \ ecdh-sha2-nistp521 \ ecdsa-sha2-nistp521 \ ecdsa-sha2-nistp521-cert-v01@openssh.com" fi + + # Check for OpenSSL with ED25519 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether OpenSSL has ED25519 support" >&5 +$as_echo_n "checking whether OpenSSL has ED25519 support... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + #include + +int +main () +{ + + unsigned char buf[64]; + if (EVP_PKEY_new_raw_private_key( + EVP_PKEY_ED25519, NULL, + buf, sizeof(buf)) == NULL) + return 1; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +$as_echo "#define OPENSSL_HAS_ED25519 1" >>confdefs.h + + COMMENT_OUT_ED25519= + +else + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + + fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi + + +# check for openssl 0.9.7+ functions ... +for ac_func in \ + DES_crypt \ + EVP_MD_CTX_init \ + +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF -# PKCS11/U2F depend on OpenSSL and dlopen(). -enable_pkcs11=yes -enable_sk=yes -if test "x$openssl" != "xyes" ; then - enable_pkcs11="disabled; missing libcrypto" fi -if test "x$ac_cv_func_dlopen" != "xyes" ; then - enable_pkcs11="disabled; missing dlopen(3)" - enable_sk="disabled; missing dlopen(3)" +done + + +# check for openssl 0.9.8+ headers ... +for ac_header in \ + openssl/ec.h \ + +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + fi -if test "x$ac_cv_have_decl_RTLD_NOW" != "xyes" ; then - enable_pkcs11="disabled; missing RTLD_NOW" - enable_sk="disabled; missing RTLD_NOW" + +done + + +# check for openssl 0.9.8+ functions ... +for ac_func in \ + BN_is_prime_ex \ + DSA_generate_parameters_ex \ + EVP_CIPHER_CTX_new \ + EVP_PKEY_cmp \ + RSA_generate_key_ex \ + +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + fi -if test ! -z "$disable_pkcs11" ; then - enable_pkcs11="disabled by user" +done + + +# Check for the existence of "X509_VERIFY_PARAM *param" (OpenSSL 0.9.8+) +# Instead check for X509_STORE_CTX.param we check for get functions +for ac_func in X509_STORE_CTX_get0_param +do : + ac_fn_c_check_func "$LINENO" "X509_STORE_CTX_get0_param" "ac_cv_func_X509_STORE_CTX_get0_param" +if test "x$ac_cv_func_X509_STORE_CTX_get0_param" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_X509_STORE_CTX_GET0_PARAM 1 +_ACEOF + fi -if test ! -z "$disable_sk" ; then - enable_sk="disabled by user" +done + + +# check for openssl 1.0.0+ functions ... +for ac_func in \ + ERR_remove_thread_state \ + EVP_DigestSignInit \ + EVP_MD_flags \ + EVP_PKEY_base_id \ + EVP_PKEY_print_params \ + X509_STORE_set_verify_cb \ + +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + fi +done -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether to enable PKCS11" >&5 -printf %s "checking whether to enable PKCS11... " >&6; } -if test "x$enable_pkcs11" = "xyes" ; then -printf "%s\n" "#define ENABLE_PKCS11 /**/" >>confdefs.h +# check for some structures +ac_fn_c_check_member "$LINENO" "ECDSA_METHOD" "name" "ac_cv_member_ECDSA_METHOD_name" "#include + +" +if test "x$ac_cv_member_ECDSA_METHOD_name" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_ECDSA_METHOD_NAME 1 +_ACEOF + fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $enable_pkcs11" >&5 -printf "%s\n" "$enable_pkcs11" >&6; } -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether to enable U2F" >&5 -printf %s "checking whether to enable U2F... " >&6; } -if test "x$enable_sk" = "xyes" ; then -printf "%s\n" "#define ENABLE_SK /**/" >>confdefs.h +# check for openssl 1.0.2+ functions ... +for ac_func in \ + ECDSA_METHOD_new \ - SK_DUMMY_LIBRARY=regress/misc/sk-dummy/sk-dummy.so +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF +fi +done + + +# check for openssl 1.1+ functions ... +for ac_func in \ + ASN1_STRING_get0_data \ + BN_is_negative \ + DH_get0_key \ + DSA_SIG_get0 \ + DSA_SIG_set0 \ + EC_KEY_METHOD_new \ + ECDSA_SIG_get0 \ + ECDSA_SIG_set0 \ + EVP_chacha20 \ + EVP_CIPHER_CTX_iv \ + EVP_MD_CTX_new \ + RSA_meth_new \ + RSA_PKCS1_OpenSSL \ + X509_CRL_get0_lastUpdate \ + X509_get0_tbs_sigalg \ + X509_get_extension_flags \ + X509_get_key_usage \ + X509_OBJECT_new \ + X509_STORE_CTX_get_by_subject \ + X509_STORE_get0_objects \ + X509_STORE_lock \ + +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + +for ac_func in X509_VERIFY_PARAM_get_time +do : + ac_fn_c_check_func "$LINENO" "X509_VERIFY_PARAM_get_time" "ac_cv_func_X509_VERIFY_PARAM_get_time" +if test "x$ac_cv_func_X509_VERIFY_PARAM_get_time" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_X509_VERIFY_PARAM_GET_TIME 1 +_ACEOF + +fi +done + + +# check for functions randomly implemented for compatibility with openssl 1.1+ +for ac_func in \ + DSA_get0_key \ + OPENSSL_cleanup \ + RSA_meth_get_pub_enc \ + RSA_meth_set1_name \ + RSA_meth_set_priv_enc \ + RSA_get0_key \ + X509_OBJECT_get0_X509 \ + +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + +# check for removed in openssl 1.1+ functions ... +for ac_func in \ + EVP_dss1 \ + +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + +# check for openssl 1.1.+ declarations ... +ac_fn_c_check_decl "$LINENO" "DEFINE_STACK_OF" "ac_cv_have_decl_DEFINE_STACK_OF" " +#include +#include + +" +if test "x$ac_cv_have_decl_DEFINE_STACK_OF" = xyes; then : + ac_have_decl=1 else - # Do not try to build sk-dummy library. - SK_DUMMY_LIBRARY="" + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_DEFINE_STACK_OF $ac_have_decl +_ACEOF + +# check for openssl 1.1+ opaque structures ... +ac_fn_c_check_type "$LINENO" "struct x509_lookup_method_st" "ac_cv_type_struct_x509_lookup_method_st" " +#include + +" +if test "x$ac_cv_type_struct_x509_lookup_method_st" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_X509_LOOKUP_METHOD_ST 1 +_ACEOF + fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $enable_sk" >&5 -printf "%s\n" "$enable_sk" >&6; } -# Now check for built-in security key support. -if test "x$enable_sk" = "xyes" -a "x$enable_sk_internal" != "xno" ; then - use_pkgconfig_for_libfido2= - if test "x$PKGCONFIG" != "xno"; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $PKGCONFIG knows about libfido2" >&5 -printf %s "checking if $PKGCONFIG knows about libfido2... " >&6; } - if "$PKGCONFIG" libfido2; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } - use_pkgconfig_for_libfido2=yes - else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } - fi - fi - if test "x$use_pkgconfig_for_libfido2" = "xyes"; then - LIBFIDO2=`$PKGCONFIG --libs libfido2` - CPPFLAGS="$CPPFLAGS `$PKGCONFIG --cflags libfido2`" - else - LIBFIDO2="-lfido2 -lcbor" - fi - OTHERLIBS=`echo $LIBFIDO2 | sed 's/-lfido2//'` - fido2_error= - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for fido_init in -lfido2" >&5 -printf %s "checking for fido_init in -lfido2... " >&6; } -if test ${ac_cv_lib_fido2_fido_init+y} -then : - printf %s "(cached) " >&6 -else $as_nop + +# check for openssl 1.1.1+ functions ... +for ac_func in \ + EC_POINT_get_affine_coordinates \ + EVP_DigestSign \ + RAND_keep_random_devices_open \ + +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + +# activate openssl(1.1.1+) store functionality +USE_OPENSSL_STORE2=false +ac_fn_c_check_func "$LINENO" "OSSL_STORE_open" "ac_cv_func_OSSL_STORE_open" +if test "x$ac_cv_func_OSSL_STORE_open" = xyes; then : + +fi + +if test "x$ac_cv_func_OSSL_STORE_open" = xyes ; then + +$as_echo "#define USE_OPENSSL_STORE2 1" >>confdefs.h + + USE_OPENSSL_STORE2=: +fi + + +# check for openssl 3.0+ functions ... +for ac_func in \ + BN_check_prime \ + EC_GROUP_get_field_type \ + ERR_get_error_all \ + EVP_KEYMGMT_get0_provider \ + EVP_MD_get_flags \ + EVP_PKEY_eq \ + EVP_PKEY_get_base_id \ + X509_LOOKUP_store \ + +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + +# check for deprecated 3.0+ functions ... +for ac_func in \ + AES_encrypt \ + +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + +# functions in openssl compatible libraries +ac_fn_c_check_decl "$LINENO" "UTF8_getc" "ac_cv_have_decl_UTF8_getc" " +#include + +" +if test "x$ac_cv_have_decl_UTF8_getc" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_UTF8_GETC $ac_have_decl +_ACEOF + +for ac_func in \ + EVP_CIPHER_CTX_get_iv \ + UTF8_getc \ + +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + +# ASN1_STRING_length const argument >= 1.0 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ASN1_STRING_length declare const argument" >&5 +$as_echo_n "checking whether ASN1_STRING_length declare const argument... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include +int ASN1_STRING_length(const ASN1_STRING *x) { + (void) x; return 0; +} + +int +main () +{ + + ASN1_STRING_length(NULL); + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + asn1_string_length_const="const" + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + asn1_string_length_const="/* not const */" + + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +cat >>confdefs.h <<_ACEOF +#define ASN1_STRING_LENGTH_CONST $asn1_string_length_const +_ACEOF + + +# check for function sk_OPENSSL_STRING_new_null inlined in openssl 1.1+ ... +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for sk_OPENSSL_STRING_new_null" >&5 +$as_echo_n "checking for sk_OPENSSL_STRING_new_null... " >&6; } +if ${ac_cv_func_sk_OPENSSL_STRING_new_null+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + #include + +int +main () +{ + + void *q; + q = sk_OPENSSL_STRING_new_null(); + + ; + return 0; +} + +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_func_sk_OPENSSL_STRING_new_null=yes +else + ac_cv_func_sk_OPENSSL_STRING_new_null=no + +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_sk_OPENSSL_STRING_new_null" >&5 +$as_echo "$ac_cv_func_sk_OPENSSL_STRING_new_null" >&6; } +if test "x$ac_cv_func_sk_OPENSSL_STRING_new_null" = xyes; then + +$as_echo "#define HAVE_SK_OPENSSL_STRING_NEW_NULL 1" >>confdefs.h + +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether store find method uses const criteria" >&5 +$as_echo_n "checking whether store find method uses const criteria... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include +typedef int (*OSSL_STORE_find_fn)(OSSL_STORE_LOADER_CTX *ctx, + const OSSL_STORE_SEARCH *criteria); + +int +main () +{ + + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + store_find_criterion_const="const" + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + store_find_criterion_const="/* not const */" + + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +cat >>confdefs.h <<_ACEOF +#define STORE_FIND_CRITERION_CONST $store_find_criterion_const +_ACEOF + + + +# FIPS enabled OpenSSL + + +OPENSSL_FIPS_MODE=no +# Check whether --enable-openssl-fips was given. +if test "${enable_openssl_fips+set}" = set; then : + enableval=$enable_openssl_fips; ac_openssl_fips=$enableval +else + ac_openssl_fips=none + +fi + + +if test "x$ac_openssl_fips" = "xyes"; then : + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include + +int +main () +{ + +#ifndef OPENSSL_FIPS +error OPENSSL_FIPS is not defined +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +else + as_fn_error $? "cannot found fips capable openssl header" "$LINENO" 5 + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_fn_c_check_func "$LINENO" "FIPS_mode" "ac_cv_func_FIPS_mode" +if test "x$ac_cv_func_FIPS_mode" = xyes; then : + +else + as_fn_error $? "cannot found fips capable openssl library" "$LINENO" 5 + +fi + + OPENSSL_FIPS_MODE=yes + +fi + + +FIPS_LIBS= +FIPSHMAC=: +if test "x$OPENSSL_FIPS_MODE" = "xyes"; then : + + # some system distribute openssl/fips.h + for ac_header in openssl/fips.h +do : + ac_fn_c_check_header_compile "$LINENO" "openssl/fips.h" "ac_cv_header_openssl_fips_h" " +/* Header in fips module 2.0* refer to elementary keys like RSA, + DSA, EVP* structures, and etc. i.e. unusable without OpenSSL + types declarations. Also header uses size_t. + */ +#include +#include + +" +if test "x$ac_cv_header_openssl_fips_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_OPENSSL_FIPS_H 1 +_ACEOF + +fi + +done + + + # on some systems FIPS error string are not loaded with other errors!? + ac_fn_c_check_decl "$LINENO" "ERR_load_FIPS_strings" "ac_cv_have_decl_ERR_load_FIPS_strings" " +#include +#include +#ifdef HAVE_OPENSSL_FIPS_H +# include +#endif + +" +if test "x$ac_cv_have_decl_ERR_load_FIPS_strings" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_ERR_LOAD_FIPS_STRINGS $ac_have_decl +_ACEOF + + for ac_func in \ + ERR_load_FIPS_strings \ + +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + + # check for Red Hat specific fips library + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for FIPSCHECK_verify in -lfipscheck" >&5 +$as_echo_n "checking for FIPSCHECK_verify in -lfipscheck... " >&6; } +if ${ac_cv_lib_fipscheck_FIPSCHECK_verify+:} false; then : + $as_echo_n "(cached) " >&6 +else ac_check_lib_save_LIBS=$LIBS -LIBS="-lfido2 $OTHERLIBS - $LIBS" +LIBS="-lfipscheck $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ -char fido_init (); +#ifdef __cplusplus +extern "C" +#endif +char FIPSCHECK_verify (); int -main (void) +main () { -return fido_init (); +return FIPSCHECK_verify (); ; return 0; } _ACEOF -if ac_fn_c_try_link "$LINENO" -then : - ac_cv_lib_fido2_fido_init=yes -else $as_nop - ac_cv_lib_fido2_fido_init=no +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_fipscheck_FIPSCHECK_verify=yes +else + ac_cv_lib_fipscheck_FIPSCHECK_verify=no fi -rm -f core conftest.err conftest.$ac_objext conftest.beam \ +rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_fido2_fido_init" >&5 -printf "%s\n" "$ac_cv_lib_fido2_fido_init" >&6; } -if test "x$ac_cv_lib_fido2_fido_init" = xyes -then : - -else $as_nop - fido2_error="missing/unusable libfido2" -fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_fipscheck_FIPSCHECK_verify" >&5 +$as_echo "$ac_cv_lib_fipscheck_FIPSCHECK_verify" >&6; } +if test "x$ac_cv_lib_fipscheck_FIPSCHECK_verify" = xyes; then : - ac_fn_c_check_header_compile "$LINENO" "fido.h" "ac_cv_header_fido_h" "$ac_includes_default" -if test "x$ac_cv_header_fido_h" = xyes -then : + FIPS_LIBS="-lfipscheck" + for ac_header in fipscheck.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "fipscheck.h" "ac_cv_header_fipscheck_h" "$ac_includes_default" +if test "x$ac_cv_header_fipscheck_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_FIPSCHECK_H 1 +_ACEOF -else $as_nop - fido2_error="missing fido.h from libfido2" fi - ac_fn_c_check_header_compile "$LINENO" "fido/credman.h" "ac_cv_header_fido_credman_h" " #include +done -" -if test "x$ac_cv_header_fido_credman_h" = xyes -then : + FIPSHMAC=fipshmac -else $as_nop - fido2_error="missing fido/credman.h from libfido2" fi - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for usable libfido2 installation" >&5 -printf %s "checking for usable libfido2 installation... " >&6; } - if test ! -z "$fido2_error" ; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $fido2_error" >&5 -printf "%s\n" "$fido2_error" >&6; } - if test "x$enable_sk_internal" = "xyes" ; then - as_fn_error $? "No usable libfido2 library/headers found" "$LINENO" 5 - fi - LIBFIDO2="" - else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } +fi -printf "%s\n" "#define ENABLE_SK_INTERNAL /**/" >>confdefs.h - enable_sk="built-in" - saved_LIBS="$LIBS" - LIBS="$LIBFIDO2 $LIBS" - ac_fn_c_check_func "$LINENO" "fido_assert_set_clientdata" "ac_cv_func_fido_assert_set_clientdata" -if test "x$ac_cv_func_fido_assert_set_clientdata" = xyes -then : - printf "%s\n" "#define HAVE_FIDO_ASSERT_SET_CLIENTDATA 1" >>confdefs.h + +use_dl=false +# PKCS#11 depends on OpenSSL and requires dlopen() and co. +if test $PKCS11_MSG = yes ; then + use_dl=: fi -ac_fn_c_check_func "$LINENO" "fido_cred_prot" "ac_cv_func_fido_cred_prot" -if test "x$ac_cv_func_fido_cred_prot" = xyes -then : - printf "%s\n" "#define HAVE_FIDO_CRED_PROT 1" >>confdefs.h +if $use_dl ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing dlopen" >&5 +$as_echo_n "checking for library containing dlopen... " >&6; } +if ${ac_cv_search_dlopen+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dlopen (); +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +for ac_lib in '' dl; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_c_try_link "$LINENO"; then : + ac_cv_search_dlopen=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_dlopen+:} false; then : + break fi -ac_fn_c_check_func "$LINENO" "fido_cred_set_prot" "ac_cv_func_fido_cred_set_prot" -if test "x$ac_cv_func_fido_cred_set_prot" = xyes -then : - printf "%s\n" "#define HAVE_FIDO_CRED_SET_PROT 1" >>confdefs.h +done +if ${ac_cv_search_dlopen+:} false; then : +else + ac_cv_search_dlopen=no fi -ac_fn_c_check_func "$LINENO" "fido_cred_set_clientdata" "ac_cv_func_fido_cred_set_clientdata" -if test "x$ac_cv_func_fido_cred_set_clientdata" = xyes -then : - printf "%s\n" "#define HAVE_FIDO_CRED_SET_CLIENTDATA 1" >>confdefs.h +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_dlopen" >&5 +$as_echo "$ac_cv_search_dlopen" >&6; } +ac_res=$ac_cv_search_dlopen +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" +else + use_dl=false fi -ac_fn_c_check_func "$LINENO" "fido_dev_get_touch_begin" "ac_cv_func_fido_dev_get_touch_begin" -if test "x$ac_cv_func_fido_dev_get_touch_begin" = xyes -then : - printf "%s\n" "#define HAVE_FIDO_DEV_GET_TOUCH_BEGIN 1" >>confdefs.h fi -ac_fn_c_check_func "$LINENO" "fido_dev_get_touch_status" "ac_cv_func_fido_dev_get_touch_status" -if test "x$ac_cv_func_fido_dev_get_touch_status" = xyes -then : - printf "%s\n" "#define HAVE_FIDO_DEV_GET_TOUCH_STATUS 1" >>confdefs.h +if $use_dl ; then + # LAZY mode is preferred + ac_fn_c_check_decl "$LINENO" "RTLD_LAZY" "ac_cv_have_decl_RTLD_LAZY" "#include +" +if test "x$ac_cv_have_decl_RTLD_LAZY" = xyes; then : +else + + ac_fn_c_check_decl "$LINENO" "RTLD_NOW" "ac_cv_have_decl_RTLD_NOW" "#include +" +if test "x$ac_cv_have_decl_RTLD_NOW" = xyes; then : + +else + use_dl=false fi -ac_fn_c_check_func "$LINENO" "fido_dev_supports_cred_prot" "ac_cv_func_fido_dev_supports_cred_prot" -if test "x$ac_cv_func_fido_dev_supports_cred_prot" = xyes -then : - printf "%s\n" "#define HAVE_FIDO_DEV_SUPPORTS_CRED_PROT 1" >>confdefs.h + fi -ac_fn_c_check_func "$LINENO" "fido_dev_is_winhello" "ac_cv_func_fido_dev_is_winhello" -if test "x$ac_cv_func_fido_dev_is_winhello" = xyes -then : - printf "%s\n" "#define HAVE_FIDO_DEV_IS_WINHELLO 1" >>confdefs.h fi +if $use_dl ; then + if test $PKCS11_MSG = yes; then + +$as_echo "#define ENABLE_PKCS11 1" >>confdefs.h - LIBS="$saved_LIBS" + fi +else + if test $PKCS11_MSG = yes; then + as_fn_error $? " + PKCS#11 support was requested, but dynamic loading is not detected! +" "$LINENO" 5 fi fi -ac_fn_c_check_func "$LINENO" "arc4random" "ac_cv_func_arc4random" -if test "x$ac_cv_func_arc4random" = xyes -then : - printf "%s\n" "#define HAVE_ARC4RANDOM 1" >>confdefs.h +ac_fn_c_check_decl "$LINENO" "arc4random" "ac_cv_have_decl_arc4random" "$ac_includes_default" +if test "x$ac_cv_have_decl_arc4random" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_ARC4RANDOM $ac_have_decl +_ACEOF +ac_fn_c_check_decl "$LINENO" "arc4random_buf" "ac_cv_have_decl_arc4random_buf" "$ac_includes_default" +if test "x$ac_cv_have_decl_arc4random_buf" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 fi -ac_fn_c_check_func "$LINENO" "arc4random_buf" "ac_cv_func_arc4random_buf" -if test "x$ac_cv_func_arc4random_buf" = xyes -then : - printf "%s\n" "#define HAVE_ARC4RANDOM_BUF 1" >>confdefs.h +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_ARC4RANDOM_BUF $ac_have_decl +_ACEOF + +ac_fn_c_check_decl "$LINENO" "arc4random_stir" "ac_cv_have_decl_arc4random_stir" "$ac_includes_default" +if test "x$ac_cv_have_decl_arc4random_stir" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 fi -ac_fn_c_check_func "$LINENO" "arc4random_stir" "ac_cv_func_arc4random_stir" -if test "x$ac_cv_func_arc4random_stir" = xyes -then : - printf "%s\n" "#define HAVE_ARC4RANDOM_STIR 1" >>confdefs.h +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_ARC4RANDOM_STIR $ac_have_decl +_ACEOF + +ac_fn_c_check_decl "$LINENO" "arc4random_uniform" "ac_cv_have_decl_arc4random_uniform" "$ac_includes_default" +if test "x$ac_cv_have_decl_arc4random_uniform" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 fi -ac_fn_c_check_func "$LINENO" "arc4random_uniform" "ac_cv_func_arc4random_uniform" -if test "x$ac_cv_func_arc4random_uniform" = xyes -then : - printf "%s\n" "#define HAVE_ARC4RANDOM_UNIFORM 1" >>confdefs.h + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_ARC4RANDOM_UNIFORM $ac_have_decl +_ACEOF + +for ac_func in \ + arc4random \ + arc4random_buf \ + arc4random_stir \ + arc4random_uniform \ + +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF fi +done + ### Configure cryptographic random number support # Check whether OpenSSL seeds itself if test "x$openssl" = "xyes" ; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether OpenSSL's PRNG is internally seeded" >&5 -printf %s "checking whether OpenSSL's PRNG is internally seeded... " >&6; } - if test "$cross_compiling" = yes -then : - - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: assuming yes" >&5 -printf "%s\n" "$as_me: WARNING: cross compiling: assuming yes" >&2;} - # This is safe, since we will fatal() at runtime if - # OpenSSL is not seeded correctly. - OPENSSL_SEEDS_ITSELF=yes + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether OpenSSL's PRNG is internally seeded" >&5 +$as_echo_n "checking whether OpenSSL's PRNG is internally seeded... " >&6; } +if ${ssh_cv_openssl_seeds_itself+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "$cross_compiling" = yes; then : + ssh_cv_openssl_seeds_itself=cross -else $as_nop +else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ - #include - #include #include int -main (void) +main () { - exit(RAND_status() == 1 ? 0 : 1); + if (RAND_status() != 1) + return 1; ; return 0; } _ACEOF -if ac_fn_c_try_run "$LINENO" -then : - - OPENSSL_SEEDS_ITSELF=yes - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } - -else $as_nop - - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } - +if ac_fn_c_try_run "$LINENO"; then : + ssh_cv_openssl_seeds_itself=yes +else + ssh_cv_openssl_seeds_itself=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ssh_cv_openssl_seeds_itself" >&5 +$as_echo "$ssh_cv_openssl_seeds_itself" >&6; } + if test "x$ssh_cv_openssl_seeds_itself" = "xcross"; then : + + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: assuming internally seeded" >&5 +$as_echo "$as_me: WARNING: cross compiling: assuming internally seeded" >&2;} + # This is safe, since program call fatal() at runtime if + # OpenSSL is not seeded correctly. + ssh_cv_openssl_seeds_itself=yes + +fi fi # PRNGD TCP socket # Check whether --with-prngd-port was given. -if test ${with_prngd_port+y} -then : +if test "${with_prngd_port+set}" = set; then : withval=$with_prngd_port; case "$withval" in no) @@ -16548,7 +14909,9 @@ if test ! -z "$withval" ; then PRNGD_PORT="$withval" -printf "%s\n" "#define PRNGD_PORT $PRNGD_PORT" >>confdefs.h +cat >>confdefs.h <<_ACEOF +#define PRNGD_PORT $PRNGD_PORT +_ACEOF fi @@ -16559,8 +14922,7 @@ # PRNGD Unix domain socket # Check whether --with-prngd-socket was given. -if test ${with_prngd_socket+y} -then : +if test "${with_prngd_socket+set}" = set; then : withval=$with_prngd_socket; case "$withval" in yes) @@ -16581,36 +14943,40 @@ as_fn_error $? "You may not specify both a PRNGD/EGD port and socket" "$LINENO" 5 fi if test ! -r "$withval" ; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: Entropy socket is not readable" >&5 -printf "%s\n" "$as_me: WARNING: Entropy socket is not readable" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Entropy socket is not readable" >&5 +$as_echo "$as_me: WARNING: Entropy socket is not readable" >&2;} fi PRNGD_SOCKET="$withval" -printf "%s\n" "#define PRNGD_SOCKET \"$PRNGD_SOCKET\"" >>confdefs.h +cat >>confdefs.h <<_ACEOF +#define PRNGD_SOCKET "$PRNGD_SOCKET" +_ACEOF fi -else $as_nop +else # Check for existing socket only if we don't have a random device already - if test "x$OPENSSL_SEEDS_ITSELF" != "xyes" ; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for PRNGD/EGD socket" >&5 -printf %s "checking for PRNGD/EGD socket... " >&6; } + if test "x$ssh_cv_openssl_seeds_itself" != "xyes" ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for PRNGD/EGD socket" >&5 +$as_echo_n "checking for PRNGD/EGD socket... " >&6; } # Insert other locations here for sock in /var/run/egd-pool /dev/egd-pool /etc/entropy; do - if test -r $sock && $TEST_MINUS_S_SH -c "test -S $sock -o -p $sock" ; then + if test -r $sock && $SHELL -c "test -S $sock -o -p $sock" ; then PRNGD_SOCKET="$sock" - printf "%s\n" "#define PRNGD_SOCKET \"$PRNGD_SOCKET\"" >>confdefs.h + cat >>confdefs.h <<_ACEOF +#define PRNGD_SOCKET "$PRNGD_SOCKET" +_ACEOF break; fi done if test ! -z "$PRNGD_SOCKET" ; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $PRNGD_SOCKET" >&5 -printf "%s\n" "$PRNGD_SOCKET" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PRNGD_SOCKET" >&5 +$as_echo "$PRNGD_SOCKET" >&6; } else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: not found" >&5 -printf "%s\n" "not found" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5 +$as_echo "not found" >&6; } fi fi @@ -16623,26 +14989,24 @@ RAND_MSG="PRNGd port $PRNGD_PORT" elif test ! -z "$PRNGD_SOCKET" ; then RAND_MSG="PRNGd socket $PRNGD_SOCKET" -elif test ! -z "$OPENSSL_SEEDS_ITSELF" ; then +elif test "x$ssh_cv_openssl_seeds_itself" = "xyes" ; then -printf "%s\n" "#define OPENSSL_PRNG_ONLY 1" >>confdefs.h +$as_echo "#define OPENSSL_PRNG_ONLY 1" >>confdefs.h RAND_MSG="OpenSSL internal ONLY" elif test "x$openssl" = "xno" ; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: OpenSSH will use /dev/urandom as a source of random numbers. It will fail if this device is not supported or accessible" >&5 -printf "%s\n" "$as_me: WARNING: OpenSSH will use /dev/urandom as a source of random numbers. It will fail if this device is not supported or accessible" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $PACKAGE_NAME will use /dev/urandom as a source of random numbers. It will fail if this device is not supported or accessible" >&5 +$as_echo "$as_me: WARNING: $PACKAGE_NAME will use /dev/urandom as a source of random numbers. It will fail if this device is not supported or accessible" >&2;} else - as_fn_error $? "OpenSSH has no source of random numbers. Please configure OpenSSL with an entropy source or re-run configure using one of the --with-prngd-port or --with-prngd-socket options" "$LINENO" 5 + as_fn_error $? "$PACKAGE_NAME has no source of random numbers. Please configure OpenSSL with an entropy source or re-run configure using one of the --with-prngd-port or --with-prngd-socket options" "$LINENO" 5 fi -LIBS="$nocrypto_saved_LIBS" saved_LIBS="$LIBS" -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ia_openinfo in -liaf" >&5 -printf %s "checking for ia_openinfo in -liaf... " >&6; } -if test ${ac_cv_lib_iaf_ia_openinfo+y} -then : - printf %s "(cached) " >&6 -else $as_nop +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ia_openinfo in -liaf" >&5 +$as_echo_n "checking for ia_openinfo in -liaf... " >&6; } +if ${ac_cv_lib_iaf_ia_openinfo+:} false; then : + $as_echo_n "(cached) " >&6 +else ac_check_lib_save_LIBS=$LIBS LIBS="-liaf $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -16651,59 +15015,59 @@ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif char ia_openinfo (); int -main (void) +main () { return ia_openinfo (); ; return 0; } _ACEOF -if ac_fn_c_try_link "$LINENO" -then : +if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_iaf_ia_openinfo=yes -else $as_nop +else ac_cv_lib_iaf_ia_openinfo=no fi -rm -f core conftest.err conftest.$ac_objext conftest.beam \ +rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_iaf_ia_openinfo" >&5 -printf "%s\n" "$ac_cv_lib_iaf_ia_openinfo" >&6; } -if test "x$ac_cv_lib_iaf_ia_openinfo" = xyes -then : +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_iaf_ia_openinfo" >&5 +$as_echo "$ac_cv_lib_iaf_ia_openinfo" >&6; } +if test "x$ac_cv_lib_iaf_ia_openinfo" = xyes; then : LIBS="$LIBS -liaf" - - for ac_func in set_id + for ac_func in set_id do : ac_fn_c_check_func "$LINENO" "set_id" "ac_cv_func_set_id" -if test "x$ac_cv_func_set_id" = xyes -then : - printf "%s\n" "#define HAVE_SET_ID 1" >>confdefs.h +if test "x$ac_cv_func_set_id" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_SET_ID 1 +_ACEOF SSHDLIBS="$SSHDLIBS -liaf" -printf "%s\n" "#define HAVE_LIBIAF 1" >>confdefs.h +$as_echo "#define HAVE_LIBIAF 1" >>confdefs.h fi - done + fi LIBS="$saved_LIBS" # Check for crypt() in libcrypt. If we have it, we only need it for sshd. saved_LIBS="$LIBS" -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for crypt in -lcrypt" >&5 -printf %s "checking for crypt in -lcrypt... " >&6; } -if test ${ac_cv_lib_crypt_crypt+y} -then : - printf %s "(cached) " >&6 -else $as_nop +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for crypt in -lcrypt" >&5 +$as_echo_n "checking for crypt in -lcrypt... " >&6; } +if ${ac_cv_lib_crypt_crypt+:} false; then : + $as_echo_n "(cached) " >&6 +else ac_check_lib_save_LIBS=$LIBS LIBS="-lcrypt $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -16712,41 +15076,46 @@ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif char crypt (); int -main (void) +main () { return crypt (); ; return 0; } _ACEOF -if ac_fn_c_try_link "$LINENO" -then : +if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_crypt_crypt=yes -else $as_nop +else ac_cv_lib_crypt_crypt=no fi -rm -f core conftest.err conftest.$ac_objext conftest.beam \ +rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_crypt_crypt" >&5 -printf "%s\n" "$ac_cv_lib_crypt_crypt" >&6; } -if test "x$ac_cv_lib_crypt_crypt" = xyes -then : +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_crypt_crypt" >&5 +$as_echo "$ac_cv_lib_crypt_crypt" >&6; } +if test "x$ac_cv_lib_crypt_crypt" = xyes; then : LIBS="-lcrypt $LIBS" SSHDLIBS="-lcrypt $SSHDLIBS" fi -ac_fn_c_check_func "$LINENO" "crypt" "ac_cv_func_crypt" -if test "x$ac_cv_func_crypt" = xyes -then : - printf "%s\n" "#define HAVE_CRYPT 1" >>confdefs.h +for ac_func in crypt +do : + ac_fn_c_check_func "$LINENO" "crypt" "ac_cv_func_crypt" +if test "x$ac_cv_func_crypt" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_CRYPT 1 +_ACEOF fi +done LIBS="$saved_LIBS" @@ -16754,8 +15123,7 @@ PAM_MSG="no" # Check whether --with-pam was given. -if test ${with_pam+y} -then : +if test "${with_pam+set}" = set; then : withval=$with_pam; if test "x$withval" != "xno" ; then if test "x$ac_cv_header_security_pam_appl_h" != "xyes" && \ @@ -16764,12 +15132,11 @@ fi saved_LIBS="$LIBS" - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 -printf %s "checking for dlopen in -ldl... " >&6; } -if test ${ac_cv_lib_dl_dlopen+y} -then : - printf %s "(cached) " >&6 -else $as_nop + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 +$as_echo_n "checking for dlopen in -ldl... " >&6; } +if ${ac_cv_lib_dl_dlopen+:} false; then : + $as_echo_n "(cached) " >&6 +else ac_check_lib_save_LIBS=$LIBS LIBS="-ldl $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -16778,41 +15145,43 @@ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif char dlopen (); int -main (void) +main () { return dlopen (); ; return 0; } _ACEOF -if ac_fn_c_try_link "$LINENO" -then : +if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dl_dlopen=yes -else $as_nop +else ac_cv_lib_dl_dlopen=no fi -rm -f core conftest.err conftest.$ac_objext conftest.beam \ +rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 -printf "%s\n" "$ac_cv_lib_dl_dlopen" >&6; } -if test "x$ac_cv_lib_dl_dlopen" = xyes -then : - printf "%s\n" "#define HAVE_LIBDL 1" >>confdefs.h +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 +$as_echo "$ac_cv_lib_dl_dlopen" >&6; } +if test "x$ac_cv_lib_dl_dlopen" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBDL 1 +_ACEOF LIBS="-ldl $LIBS" fi - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for pam_set_item in -lpam" >&5 -printf %s "checking for pam_set_item in -lpam... " >&6; } -if test ${ac_cv_lib_pam_pam_set_item+y} -then : - printf %s "(cached) " >&6 -else $as_nop + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pam_set_item in -lpam" >&5 +$as_echo_n "checking for pam_set_item in -lpam... " >&6; } +if ${ac_cv_lib_pam_pam_set_item+:} false; then : + $as_echo_n "(cached) " >&6 +else ac_check_lib_save_LIBS=$LIBS LIBS="-lpam $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -16821,50 +15190,61 @@ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif char pam_set_item (); int -main (void) +main () { return pam_set_item (); ; return 0; } _ACEOF -if ac_fn_c_try_link "$LINENO" -then : +if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_pam_pam_set_item=yes -else $as_nop +else ac_cv_lib_pam_pam_set_item=no fi -rm -f core conftest.err conftest.$ac_objext conftest.beam \ +rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pam_pam_set_item" >&5 -printf "%s\n" "$ac_cv_lib_pam_pam_set_item" >&6; } -if test "x$ac_cv_lib_pam_pam_set_item" = xyes -then : - printf "%s\n" "#define HAVE_LIBPAM 1" >>confdefs.h +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pam_pam_set_item" >&5 +$as_echo "$ac_cv_lib_pam_pam_set_item" >&6; } +if test "x$ac_cv_lib_pam_pam_set_item" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBPAM 1 +_ACEOF LIBS="-lpam $LIBS" -else $as_nop +else as_fn_error $? "*** libpam missing" "$LINENO" 5 fi - ac_fn_c_check_func "$LINENO" "pam_getenvlist" "ac_cv_func_pam_getenvlist" -if test "x$ac_cv_func_pam_getenvlist" = xyes -then : - printf "%s\n" "#define HAVE_PAM_GETENVLIST 1" >>confdefs.h + for ac_func in pam_getenvlist +do : + ac_fn_c_check_func "$LINENO" "pam_getenvlist" "ac_cv_func_pam_getenvlist" +if test "x$ac_cv_func_pam_getenvlist" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_PAM_GETENVLIST 1 +_ACEOF fi +done - ac_fn_c_check_func "$LINENO" "pam_putenv" "ac_cv_func_pam_putenv" -if test "x$ac_cv_func_pam_putenv" = xyes -then : - printf "%s\n" "#define HAVE_PAM_PUTENV 1" >>confdefs.h + for ac_func in pam_putenv +do : + ac_fn_c_check_func "$LINENO" "pam_putenv" "ac_cv_func_pam_putenv" +if test "x$ac_cv_func_pam_putenv" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_PAM_PUTENV 1 +_ACEOF fi +done LIBS="$saved_LIBS" @@ -16872,7 +15252,7 @@ SSHDLIBS="$SSHDLIBS -lpam" -printf "%s\n" "#define USE_PAM 1" >>confdefs.h +$as_echo "#define USE_PAM 1" >>confdefs.h if test $ac_cv_lib_dl_dlopen = yes; then @@ -16893,13 +15273,14 @@ # Check whether --with-pam-service was given. -if test ${with_pam_service+y} -then : +if test "${with_pam_service+set}" = set; then : withval=$with_pam_service; if test "x$withval" != "xno" && \ test "x$withval" != "xyes" ; then -printf "%s\n" "#define SSHD_PAM_SERVICE \"$withval\"" >>confdefs.h +cat >>confdefs.h <<_ACEOF +#define SSHD_PAM_SERVICE "$withval" +_ACEOF fi @@ -16910,8 +15291,8 @@ # Check for older PAM if test "x$PAM_MSG" = "xyes" ; then # Check PAM strerror arguments (old PAM) - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether pam_strerror takes only one argument" >&5 -printf %s "checking whether pam_strerror takes only one argument... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether pam_strerror takes only one argument" >&5 +$as_echo_n "checking whether pam_strerror takes only one argument... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -16923,7 +15304,7 @@ #endif int -main (void) +main () { (void)pam_strerror((pam_handle_t *)NULL, -1); @@ -16932,22 +15313,21 @@ return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO" -then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } -else $as_nop +if ac_fn_c_try_compile "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +else -printf "%s\n" "#define HAVE_OLD_PAM 1" >>confdefs.h +$as_echo "#define HAVE_OLD_PAM 1" >>confdefs.h - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } PAM_MSG="yes (old library)" fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi case "$host" in @@ -16960,8 +15340,7 @@ esac # Check whether --with-privsep-user was given. -if test ${with_privsep_user+y} -then : +if test "${with_privsep_user+set}" = set; then : withval=$with_privsep_user; if test -n "$withval" && test "x$withval" != "xno" && \ test "x${withval}" != "xyes"; then @@ -16973,29 +15352,33 @@ if test "x$SSH_PRIVSEP_USER" = "xCYGWIN_SSH_PRIVSEP_USER" ; then -printf "%s\n" "#define SSH_PRIVSEP_USER CYGWIN_SSH_PRIVSEP_USER" >>confdefs.h +cat >>confdefs.h <<_ACEOF +#define SSH_PRIVSEP_USER CYGWIN_SSH_PRIVSEP_USER +_ACEOF else -printf "%s\n" "#define SSH_PRIVSEP_USER \"$SSH_PRIVSEP_USER\"" >>confdefs.h +cat >>confdefs.h <<_ACEOF +#define SSH_PRIVSEP_USER "$SSH_PRIVSEP_USER" +_ACEOF fi if test "x$have_linux_no_new_privs" = "x1" ; then -ac_fn_check_decl "$LINENO" "SECCOMP_MODE_FILTER" "ac_cv_have_decl_SECCOMP_MODE_FILTER" " +ac_fn_c_check_decl "$LINENO" "SECCOMP_MODE_FILTER" "ac_cv_have_decl_SECCOMP_MODE_FILTER" " #include #include -" "$ac_c_undeclared_builtin_options" "CFLAGS" -if test "x$ac_cv_have_decl_SECCOMP_MODE_FILTER" = xyes -then : +" +if test "x$ac_cv_have_decl_SECCOMP_MODE_FILTER" = xyes; then : have_seccomp_filter=1 fi + fi if test "x$have_seccomp_filter" = "x1" ; then -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking kernel for seccomp_filter support" >&5 -printf %s "checking kernel for seccomp_filter support... " >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking kernel for seccomp_filter support" >&5 +$as_echo_n "checking kernel for seccomp_filter support... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -17007,47 +15390,50 @@ #include int -main (void) +main () { - int i = $seccomp_audit_arch; + + int i = $seccomp_audit_arch; errno = 0; prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, NULL, 0, 0); - exit(errno == EFAULT ? 0 : 1); + if (errno != EFAULT) return 1; + ; return 0; } _ACEOF -if ac_fn_c_try_link "$LINENO" -then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } -else $as_nop +if ac_fn_c_try_link "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } # Disable seccomp filter as a target have_seccomp_filter=0 fi -rm -f core conftest.err conftest.$ac_objext conftest.beam \ +rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi ac_fn_c_check_member "$LINENO" "struct pollfd" "fd" "ac_cv_member_struct_pollfd_fd" " #include #ifdef HAVE_POLL_H -#include -#endif -#ifdef HAVE_SYS_POLL_H -#include +# include +#else +# ifdef HAVE_SYS_POLL_H +# include +# endif #endif " -if test "x$ac_cv_member_struct_pollfd_fd" = xyes -then : +if test "x$ac_cv_member_struct_pollfd_fd" = xyes; then : -printf "%s\n" "#define HAVE_STRUCT_POLLFD_FD 1" >>confdefs.h +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_POLLFD_FD 1 +_ACEOF fi @@ -17056,17 +15442,19 @@ ac_fn_c_check_type "$LINENO" "nfds_t" "ac_cv_type_nfds_t" " #include #ifdef HAVE_POLL_H -#include -#endif -#ifdef HAVE_SYS_POLL_H -#include +# include +#else +# ifdef HAVE_SYS_POLL_H +# include +# endif #endif " -if test "x$ac_cv_type_nfds_t" = xyes -then : +if test "x$ac_cv_type_nfds_t" = xyes; then : -printf "%s\n" "#define HAVE_NFDS_T 1" >>confdefs.h +cat >>confdefs.h <<_ACEOF +#define HAVE_NFDS_T 1 +_ACEOF fi @@ -17076,8 +15464,7 @@ sandbox_arg="" # Check whether --with-sandbox was given. -if test ${with_sandbox+y} -then : +if test "${with_sandbox+set}" = set; then : withval=$with_sandbox; if test "x$withval" = "xyes" ; then sandbox_arg="" @@ -17089,100 +15476,16 @@ fi -if test "x$sandbox_arg" != "xno"; then -# POSIX specifies that poll() "shall fail with EINVAL if the nfds argument -# is greater than OPEN_MAX". On some platforms that includes implementions -# of select in userspace on top of poll() so check both work with rlimit -# NOFILES so check that both work before enabling the rlimit sandbox. - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if select and/or poll works with descriptor rlimit" >&5 -printf %s "checking if select and/or poll works with descriptor rlimit... " >&6; } - if test "$cross_compiling" = yes -then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: assuming no" >&5 -printf "%s\n" "$as_me: WARNING: cross compiling: assuming no" >&2;} - select_works_with_rlimit=no - -else $as_nop - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -#include -#ifdef HAVE_SYS_TIME_H -# include -#endif -#include -#ifdef HAVE_SYS_SELECT_H -# include -#endif -#ifdef HAVE_POLL_H -# include -#elif HAVE_SYS_POLL_H -# include -#endif -#include -#include -#include - -int -main (void) -{ - - struct rlimit rl_zero; - int fd, r; - fd_set fds; - struct timeval tv; -#ifdef HAVE_POLL - struct pollfd pfd; -#endif - - fd = open("/dev/null", O_RDONLY); - FD_ZERO(&fds); - FD_SET(fd, &fds); - rl_zero.rlim_cur = rl_zero.rlim_max = 0; - setrlimit(RLIMIT_FSIZE, &rl_zero); - setrlimit(RLIMIT_NOFILE, &rl_zero); - tv.tv_sec = 1; - tv.tv_usec = 0; - r = select(fd+1, &fds, NULL, NULL, &tv); - if (r == -1) - exit(1); -#ifdef HAVE_POLL - pfd.fd = fd; - pfd.events = POLLIN; - r = poll(&pfd, 1, 1); - if (r == -1) - exit(2); -#endif - exit(0); - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_run "$LINENO" -then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } - select_works_with_rlimit=yes -else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } - select_works_with_rlimit=no -fi -rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ - conftest.$ac_objext conftest.beam conftest.$ac_ext -fi - +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if setrlimit RLIMIT_FSIZE works" >&5 +$as_echo_n "checking if setrlimit RLIMIT_FSIZE works... " >&6; } +if ${ssh_cv_rlimit_fsize_work+:} false; then : + $as_echo_n "(cached) " >&6 +else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if setrlimit(RLIMIT_NOFILE,{0,0}) works" >&5 -printf %s "checking if setrlimit(RLIMIT_NOFILE,{0,0}) works... " >&6; } - if test "$cross_compiling" = yes -then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: assuming yes" >&5 -printf "%s\n" "$as_me: WARNING: cross compiling: assuming yes" >&2;} - rlimit_nofile_zero_works=yes +if test "$cross_compiling" = yes; then : + ssh_cv_rlimit_fsize_work=cross -else $as_nop +else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -17191,81 +15494,47 @@ # include #endif #include -#include -#include int -main (void) +main () { struct rlimit rl_zero; int r; rl_zero.rlim_cur = rl_zero.rlim_max = 0; - r = setrlimit(RLIMIT_NOFILE, &rl_zero); - exit (r == -1 ? 1 : 0); + r = setrlimit(RLIMIT_FSIZE, &rl_zero); + if (r == -1) return 1; ; return 0; } _ACEOF -if ac_fn_c_try_run "$LINENO" -then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } - rlimit_nofile_zero_works=yes -else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } - rlimit_nofile_zero_works=no +if ac_fn_c_try_run "$LINENO"; then : + ssh_cv_rlimit_fsize_work=yes +else + ssh_cv_rlimit_fsize_work=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if setrlimit RLIMIT_FSIZE works" >&5 -printf %s "checking if setrlimit RLIMIT_FSIZE works... " >&6; } - if test "$cross_compiling" = yes -then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: assuming yes" >&5 -printf "%s\n" "$as_me: WARNING: cross compiling: assuming yes" >&2;} - -else $as_nop - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -#include -#include -#include +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ssh_cv_rlimit_fsize_work" >&5 +$as_echo "$ssh_cv_rlimit_fsize_work" >&6; } +if test $ssh_cv_rlimit_fsize_work = cross; then : -int -main (void) -{ + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: assuming working setrlimit RLIMIT_FSIZE" >&5 +$as_echo "$as_me: WARNING: cross compiling: assuming working setrlimit RLIMIT_FSIZE" >&2;} + ssh_cv_rlimit_fsize_work=yes - struct rlimit rl_zero; +fi +if test $ssh_cv_rlimit_fsize_work != yes; then : - rl_zero.rlim_cur = rl_zero.rlim_max = 0; - exit(setrlimit(RLIMIT_FSIZE, &rl_zero) != 0); - ; - return 0; -} -_ACEOF -if ac_fn_c_try_run "$LINENO" -then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } -else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } +$as_echo "#define SANDBOX_SKIP_RLIMIT_FSIZE 1" >>confdefs.h -printf "%s\n" "#define SANDBOX_SKIP_RLIMIT_FSIZE 1" >>confdefs.h - -fi -rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ - conftest.$ac_objext conftest.beam conftest.$ac_ext -fi fi @@ -17275,7 +15544,7 @@ as_fn_error $? "pledge sandbox requires pledge(2) support" "$LINENO" 5 SANDBOX_STYLE="pledge" -printf "%s\n" "#define SANDBOX_PLEDGE 1" >>confdefs.h +$as_echo "#define SANDBOX_PLEDGE 1" >>confdefs.h elif test "x$sandbox_arg" = "xsystrace" || \ ( test -z "$sandbox_arg" && test "x$have_systr_policy_kill" = "x1" ) ; then @@ -17283,7 +15552,7 @@ as_fn_error $? "systrace sandbox requires systrace headers and SYSTR_POLICY_KILL support" "$LINENO" 5 SANDBOX_STYLE="systrace" -printf "%s\n" "#define SANDBOX_SYSTRACE 1" >>confdefs.h +$as_echo "#define SANDBOX_SYSTRACE 1" >>confdefs.h elif test "x$sandbox_arg" = "xdarwin" || \ ( test -z "$sandbox_arg" && test "x$ac_cv_func_sandbox_init" = "xyes" && \ @@ -17293,7 +15562,7 @@ as_fn_error $? "Darwin seatbelt sandbox requires sandbox.h and sandbox_init function" "$LINENO" 5 SANDBOX_STYLE="darwin" -printf "%s\n" "#define SANDBOX_DARWIN 1" >>confdefs.h +$as_echo "#define SANDBOX_DARWIN 1" >>confdefs.h elif test "x$sandbox_arg" = "xseccomp_filter" || \ ( test -z "$sandbox_arg" && \ @@ -17314,7 +15583,7 @@ as_fn_error $? "seccomp_filter sandbox requires prctl function" "$LINENO" 5 SANDBOX_STYLE="seccomp_filter" -printf "%s\n" "#define SANDBOX_SECCOMP_FILTER 1" >>confdefs.h +$as_echo "#define SANDBOX_SECCOMP_FILTER 1" >>confdefs.h elif test "x$sandbox_arg" = "xcapsicum" || \ ( test -z "$sandbox_arg" && \ @@ -17327,31 +15596,27 @@ as_fn_error $? "capsicum sandbox requires cap_rights_limit function" "$LINENO" 5 SANDBOX_STYLE="capsicum" -printf "%s\n" "#define SANDBOX_CAPSICUM 1" >>confdefs.h +$as_echo "#define SANDBOX_CAPSICUM 1" >>confdefs.h + +elif test "x$sandbox_arg" = "xsolaris" || \ + ( test -z "$sandbox_arg" && test "x$SOLARIS_PRIVS" = "xyes" ) ; then + SANDBOX_STYLE="solaris" + +$as_echo "#define SANDBOX_SOLARIS 1" >>confdefs.h elif test "x$sandbox_arg" = "xrlimit" || \ - ( test -z "$sandbox_arg" && test "x$ac_cv_func_setrlimit" = "xyes" && \ - test "x$select_works_with_rlimit" = "xyes" && \ - test "x$rlimit_nofile_zero_works" = "xyes" ) ; then + test -z "$sandbox_arg" && test "x$ac_cv_func_setrlimit" = "xyes" ; then test "x$ac_cv_func_setrlimit" != "xyes" && \ as_fn_error $? "rlimit sandbox requires setrlimit function" "$LINENO" 5 - test "x$select_works_with_rlimit" != "xyes" && \ - as_fn_error $? "rlimit sandbox requires select to work with rlimit" "$LINENO" 5 SANDBOX_STYLE="rlimit" -printf "%s\n" "#define SANDBOX_RLIMIT 1" >>confdefs.h - -elif test "x$sandbox_arg" = "xsolaris" || \ - ( test -z "$sandbox_arg" && test "x$SOLARIS_PRIVS" = "xyes" ) ; then - SANDBOX_STYLE="solaris" - -printf "%s\n" "#define SANDBOX_SOLARIS 1" >>confdefs.h +$as_echo "#define SANDBOX_RLIMIT 1" >>confdefs.h elif test -z "$sandbox_arg" || test "x$sandbox_arg" = "xno" || \ test "x$sandbox_arg" = "xnone" || test "x$sandbox_arg" = "xnull" ; then SANDBOX_STYLE="none" -printf "%s\n" "#define SANDBOX_NULL 1" >>confdefs.h +$as_echo "#define SANDBOX_NULL 1" >>confdefs.h else as_fn_error $? "unsupported --with-sandbox" "$LINENO" 5 @@ -17362,28 +15627,31 @@ LIBS="$LIBS -liberty"; fi -# Check for long long datatypes +# Check for long long datatypes ac_fn_c_check_type "$LINENO" "long long" "ac_cv_type_long_long" "$ac_includes_default" -if test "x$ac_cv_type_long_long" = xyes -then : +if test "x$ac_cv_type_long_long" = xyes; then : -printf "%s\n" "#define HAVE_LONG_LONG 1" >>confdefs.h +cat >>confdefs.h <<_ACEOF +#define HAVE_LONG_LONG 1 +_ACEOF fi ac_fn_c_check_type "$LINENO" "unsigned long long" "ac_cv_type_unsigned_long_long" "$ac_includes_default" -if test "x$ac_cv_type_unsigned_long_long" = xyes -then : +if test "x$ac_cv_type_unsigned_long_long" = xyes; then : -printf "%s\n" "#define HAVE_UNSIGNED_LONG_LONG 1" >>confdefs.h +cat >>confdefs.h <<_ACEOF +#define HAVE_UNSIGNED_LONG_LONG 1 +_ACEOF fi ac_fn_c_check_type "$LINENO" "long double" "ac_cv_type_long_double" "$ac_includes_default" -if test "x$ac_cv_type_long_double" = xyes -then : +if test "x$ac_cv_type_long_double" = xyes; then : -printf "%s\n" "#define HAVE_LONG_DOUBLE 1" >>confdefs.h +cat >>confdefs.h <<_ACEOF +#define HAVE_LONG_DOUBLE 1 +_ACEOF fi @@ -17394,19 +15662,17 @@ # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. # This bug is HP SR number 8606223364. -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking size of short int" >&5 -printf %s "checking size of short int... " >&6; } -if test ${ac_cv_sizeof_short_int+y} -then : - printf %s "(cached) " >&6 -else $as_nop - if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (short int))" "ac_cv_sizeof_short_int" "$ac_includes_default" -then : +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of short int" >&5 +$as_echo_n "checking size of short int... " >&6; } +if ${ac_cv_sizeof_short_int+:} false; then : + $as_echo_n "(cached) " >&6 +else + if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (short int))" "ac_cv_sizeof_short_int" "$ac_includes_default"; then : -else $as_nop +else if test "$ac_cv_type_short_int" = yes; then - { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "cannot compute sizeof (short int) See \`config.log' for more details" "$LINENO" 5; } else @@ -17415,31 +15681,31 @@ fi fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_short_int" >&5 -printf "%s\n" "$ac_cv_sizeof_short_int" >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_short_int" >&5 +$as_echo "$ac_cv_sizeof_short_int" >&6; } -printf "%s\n" "#define SIZEOF_SHORT_INT $ac_cv_sizeof_short_int" >>confdefs.h +cat >>confdefs.h <<_ACEOF +#define SIZEOF_SHORT_INT $ac_cv_sizeof_short_int +_ACEOF # The cast to long int works around a bug in the HP C Compiler # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. # This bug is HP SR number 8606223364. -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking size of int" >&5 -printf %s "checking size of int... " >&6; } -if test ${ac_cv_sizeof_int+y} -then : - printf %s "(cached) " >&6 -else $as_nop - if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (int))" "ac_cv_sizeof_int" "$ac_includes_default" -then : +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of int" >&5 +$as_echo_n "checking size of int... " >&6; } +if ${ac_cv_sizeof_int+:} false; then : + $as_echo_n "(cached) " >&6 +else + if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (int))" "ac_cv_sizeof_int" "$ac_includes_default"; then : -else $as_nop +else if test "$ac_cv_type_int" = yes; then - { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "cannot compute sizeof (int) See \`config.log' for more details" "$LINENO" 5; } else @@ -17448,31 +15714,31 @@ fi fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_int" >&5 -printf "%s\n" "$ac_cv_sizeof_int" >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_int" >&5 +$as_echo "$ac_cv_sizeof_int" >&6; } -printf "%s\n" "#define SIZEOF_INT $ac_cv_sizeof_int" >>confdefs.h +cat >>confdefs.h <<_ACEOF +#define SIZEOF_INT $ac_cv_sizeof_int +_ACEOF # The cast to long int works around a bug in the HP C Compiler # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. # This bug is HP SR number 8606223364. -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking size of long int" >&5 -printf %s "checking size of long int... " >&6; } -if test ${ac_cv_sizeof_long_int+y} -then : - printf %s "(cached) " >&6 -else $as_nop - if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (long int))" "ac_cv_sizeof_long_int" "$ac_includes_default" -then : +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of long int" >&5 +$as_echo_n "checking size of long int... " >&6; } +if ${ac_cv_sizeof_long_int+:} false; then : + $as_echo_n "(cached) " >&6 +else + if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (long int))" "ac_cv_sizeof_long_int" "$ac_includes_default"; then : -else $as_nop +else if test "$ac_cv_type_long_int" = yes; then - { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "cannot compute sizeof (long int) See \`config.log' for more details" "$LINENO" 5; } else @@ -17481,31 +15747,31 @@ fi fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_long_int" >&5 -printf "%s\n" "$ac_cv_sizeof_long_int" >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_long_int" >&5 +$as_echo "$ac_cv_sizeof_long_int" >&6; } -printf "%s\n" "#define SIZEOF_LONG_INT $ac_cv_sizeof_long_int" >>confdefs.h +cat >>confdefs.h <<_ACEOF +#define SIZEOF_LONG_INT $ac_cv_sizeof_long_int +_ACEOF # The cast to long int works around a bug in the HP C Compiler # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. # This bug is HP SR number 8606223364. -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking size of long long int" >&5 -printf %s "checking size of long long int... " >&6; } -if test ${ac_cv_sizeof_long_long_int+y} -then : - printf %s "(cached) " >&6 -else $as_nop - if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (long long int))" "ac_cv_sizeof_long_long_int" "$ac_includes_default" -then : +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of long long int" >&5 +$as_echo_n "checking size of long long int... " >&6; } +if ${ac_cv_sizeof_long_long_int+:} false; then : + $as_echo_n "(cached) " >&6 +else + if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (long long int))" "ac_cv_sizeof_long_long_int" "$ac_includes_default"; then : -else $as_nop +else if test "$ac_cv_type_long_long_int" = yes; then - { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "cannot compute sizeof (long long int) See \`config.log' for more details" "$LINENO" 5; } else @@ -17514,41 +15780,39 @@ fi fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_long_long_int" >&5 -printf "%s\n" "$ac_cv_sizeof_long_long_int" >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_long_long_int" >&5 +$as_echo "$ac_cv_sizeof_long_long_int" >&6; } -printf "%s\n" "#define SIZEOF_LONG_LONG_INT $ac_cv_sizeof_long_long_int" >>confdefs.h +cat >>confdefs.h <<_ACEOF +#define SIZEOF_LONG_LONG_INT $ac_cv_sizeof_long_long_int +_ACEOF # The cast to long int works around a bug in the HP C Compiler # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. # This bug is HP SR number 8606223364. -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking size of time_t" >&5 -printf %s "checking size of time_t... " >&6; } -if test ${ac_cv_sizeof_time_t+y} -then : - printf %s "(cached) " >&6 -else $as_nop +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of time_t" >&5 +$as_echo_n "checking size of time_t... " >&6; } +if ${ac_cv_sizeof_time_t+:} false; then : + $as_echo_n "(cached) " >&6 +else if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (time_t))" "ac_cv_sizeof_time_t" " - #include - #ifdef HAVE_SYS_TIME_H - # include - #endif - #ifdef HAVE_TIME_H - # include - #endif - +#ifdef HAVE_SYS_TIME_H +# include +#endif +#ifdef HAVE_TIME_H +# include +#endif -" -then : +"; then : -else $as_nop +else if test "$ac_cv_type_time_t" = yes; then - { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "cannot compute sizeof (time_t) See \`config.log' for more details" "$LINENO" 5; } else @@ -17557,12 +15821,14 @@ fi fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_time_t" >&5 -printf "%s\n" "$ac_cv_sizeof_time_t" >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_time_t" >&5 +$as_echo "$ac_cv_sizeof_time_t" >&6; } -printf "%s\n" "#define SIZEOF_TIME_T $ac_cv_sizeof_time_t" >>confdefs.h +cat >>confdefs.h <<_ACEOF +#define SIZEOF_TIME_T $ac_cv_sizeof_time_t +_ACEOF @@ -17571,23 +15837,22 @@ ac_cv_sizeof_long_long_int=0 fi +# TODO: remove computation as C99 is required # compute LLONG_MIN and LLONG_MAX if we don't know them. -if test -z "$have_llong_max" && test -z "$have_long_long_max"; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for max value of long long" >&5 -printf %s "checking for max value of long long... " >&6; } - if test "$cross_compiling" = yes -then : +if test -z "$have_llong_max"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for max value of long long" >&5 +$as_echo_n "checking for max value of long long... " >&6; } + if test "$cross_compiling" = yes; then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: not checking" >&5 -printf "%s\n" "$as_me: WARNING: cross compiling: not checking" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: not checking" >&5 +$as_echo "$as_me: WARNING: cross compiling: not checking" >&2;} -else $as_nop +else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include -#include /* Why is this so damn hard? */ #ifdef __GNUC__ # undef __GNUC__ @@ -17624,14 +15889,14 @@ } int -main (void) +main () { FILE *f; long long i, llmin, llmax = 0; if((f = fopen(DATA,"w")) == NULL) - exit(1); + return 1; #if defined(LLONG_MIN) && defined(LLONG_MAX) fprintf(stderr, "Using system header for LLONG_MIN and LLONG_MAX\n"); @@ -17650,44 +15915,46 @@ || llmax - 1 > llmax || llmin == llmax || llmin == 0 || llmax == 0 || llmax < LONG_MAX || llmin > LONG_MIN) { fprintf(f, "unknown unknown\n"); - exit(2); + return 2; } if (fprint_ll(f, llmin) < 0) - exit(3); + return 3; if (fprint_ll(f, llmax) < 0) - exit(4); + return 4; if (fclose(f) < 0) - exit(5); - exit(0); + return 5; ; return 0; } _ACEOF -if ac_fn_c_try_run "$LINENO" -then : +if ac_fn_c_try_run "$LINENO"; then : llong_min=`$AWK '{print $1}' conftest.llminmax` llong_max=`$AWK '{print $2}' conftest.llminmax` - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $llong_max" >&5 -printf "%s\n" "$llong_max" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $llong_max" >&5 +$as_echo "$llong_max" >&6; } -printf "%s\n" "#define LLONG_MAX ${llong_max}LL" >>confdefs.h +cat >>confdefs.h <<_ACEOF +#define LLONG_MAX ${llong_max}LL +_ACEOF - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for min value of long long" >&5 -printf %s "checking for min value of long long... " >&6; } - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $llong_min" >&5 -printf "%s\n" "$llong_min" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for min value of long long" >&5 +$as_echo_n "checking for min value of long long... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $llong_min" >&5 +$as_echo "$llong_min" >&6; } -printf "%s\n" "#define LLONG_MIN ${llong_min}LL" >>confdefs.h +cat >>confdefs.h <<_ACEOF +#define LLONG_MIN ${llong_min}LL +_ACEOF -else $as_nop +else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: not found" >&5 -printf "%s\n" "not found" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5 +$as_echo "not found" >&6; } fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ @@ -17696,7 +15963,7 @@ fi -ac_fn_check_decl "$LINENO" "UINT32_MAX" "ac_cv_have_decl_UINT32_MAX" " +ac_fn_c_check_decl "$LINENO" "UINT32_MAX" "ac_cv_have_decl_UINT32_MAX" " #ifdef HAVE_SYS_LIMITS_H # include #endif @@ -17707,87 +15974,85 @@ # include #endif -" "$ac_c_undeclared_builtin_options" "CFLAGS" -if test "x$ac_cv_have_decl_UINT32_MAX" = xyes -then : +" +if test "x$ac_cv_have_decl_UINT32_MAX" = xyes; then : ac_have_decl=1 -else $as_nop +else ac_have_decl=0 fi -printf "%s\n" "#define HAVE_DECL_UINT32_MAX $ac_have_decl" >>confdefs.h + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_UINT32_MAX $ac_have_decl +_ACEOF # More checks for data types -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for u_int type" >&5 -printf %s "checking for u_int type... " >&6; } -if test ${ac_cv_have_u_int+y} -then : - printf %s "(cached) " >&6 -else $as_nop +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for u_int type" >&5 +$as_echo_n "checking for u_int type... " >&6; } +if ${ac_cv_have_u_int+:} false; then : + $as_echo_n "(cached) " >&6 +else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int -main (void) +main () { u_int a; a = 1; ; return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO" -then : +if ac_fn_c_try_compile "$LINENO"; then : ac_cv_have_u_int="yes" -else $as_nop +else ac_cv_have_u_int="no" fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_u_int" >&5 -printf "%s\n" "$ac_cv_have_u_int" >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_u_int" >&5 +$as_echo "$ac_cv_have_u_int" >&6; } if test "x$ac_cv_have_u_int" = "xyes" ; then -printf "%s\n" "#define HAVE_U_INT 1" >>confdefs.h +$as_echo "#define HAVE_U_INT 1" >>confdefs.h have_u_int=1 fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for intXX_t types" >&5 -printf %s "checking for intXX_t types... " >&6; } -if test ${ac_cv_have_intxx_t+y} -then : - printf %s "(cached) " >&6 -else $as_nop +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for intXX_t types" >&5 +$as_echo_n "checking for intXX_t types... " >&6; } +if ${ac_cv_have_intxx_t+:} false; then : + $as_echo_n "(cached) " >&6 +else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int -main (void) +main () { int8_t a; int16_t b; int32_t c; a = b = c = 1; ; return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO" -then : +if ac_fn_c_try_compile "$LINENO"; then : ac_cv_have_intxx_t="yes" -else $as_nop +else ac_cv_have_intxx_t="no" fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_intxx_t" >&5 -printf "%s\n" "$ac_cv_have_intxx_t" >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_intxx_t" >&5 +$as_echo "$ac_cv_have_intxx_t" >&6; } if test "x$ac_cv_have_intxx_t" = "xyes" ; then -printf "%s\n" "#define HAVE_INTXX_T 1" >>confdefs.h +$as_echo "#define HAVE_INTXX_T 1" >>confdefs.h have_intxx_t=1 fi @@ -17795,41 +16060,39 @@ if (test -z "$have_intxx_t" && \ test "x$ac_cv_header_stdint_h" = "xyes") then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for intXX_t types in stdint.h" >&5 -printf %s "checking for intXX_t types in stdint.h... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for intXX_t types in stdint.h" >&5 +$as_echo_n "checking for intXX_t types in stdint.h... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int -main (void) +main () { int8_t a; int16_t b; int32_t c; a = b = c = 1; ; return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO" -then : +if ac_fn_c_try_compile "$LINENO"; then : - printf "%s\n" "#define HAVE_INTXX_T 1" >>confdefs.h + $as_echo "#define HAVE_INTXX_T 1" >>confdefs.h - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } -else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for int64_t type" >&5 -printf %s "checking for int64_t type... " >&6; } -if test ${ac_cv_have_int64_t+y} -then : - printf %s "(cached) " >&6 -else $as_nop +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for int64_t type" >&5 +$as_echo_n "checking for int64_t type... " >&6; } +if ${ac_cv_have_int64_t+:} false; then : + $as_echo_n "(cached) " >&6 +else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -17844,7 +16107,7 @@ #endif int -main (void) +main () { int64_t a; a = 1; @@ -17853,124 +16116,118 @@ return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO" -then : +if ac_fn_c_try_compile "$LINENO"; then : ac_cv_have_int64_t="yes" -else $as_nop +else ac_cv_have_int64_t="no" fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_int64_t" >&5 -printf "%s\n" "$ac_cv_have_int64_t" >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_int64_t" >&5 +$as_echo "$ac_cv_have_int64_t" >&6; } if test "x$ac_cv_have_int64_t" = "xyes" ; then -printf "%s\n" "#define HAVE_INT64_T 1" >>confdefs.h +$as_echo "#define HAVE_INT64_T 1" >>confdefs.h fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for u_intXX_t types" >&5 -printf %s "checking for u_intXX_t types... " >&6; } -if test ${ac_cv_have_u_intxx_t+y} -then : - printf %s "(cached) " >&6 -else $as_nop +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for u_intXX_t types" >&5 +$as_echo_n "checking for u_intXX_t types... " >&6; } +if ${ac_cv_have_u_intxx_t+:} false; then : + $as_echo_n "(cached) " >&6 +else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int -main (void) +main () { u_int8_t a; u_int16_t b; u_int32_t c; a = b = c = 1; ; return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO" -then : +if ac_fn_c_try_compile "$LINENO"; then : ac_cv_have_u_intxx_t="yes" -else $as_nop +else ac_cv_have_u_intxx_t="no" fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_u_intxx_t" >&5 -printf "%s\n" "$ac_cv_have_u_intxx_t" >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_u_intxx_t" >&5 +$as_echo "$ac_cv_have_u_intxx_t" >&6; } if test "x$ac_cv_have_u_intxx_t" = "xyes" ; then -printf "%s\n" "#define HAVE_U_INTXX_T 1" >>confdefs.h +$as_echo "#define HAVE_U_INTXX_T 1" >>confdefs.h have_u_intxx_t=1 fi if test -z "$have_u_intxx_t" ; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for u_intXX_t types in sys/socket.h" >&5 -printf %s "checking for u_intXX_t types in sys/socket.h... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for u_intXX_t types in sys/socket.h" >&5 +$as_echo_n "checking for u_intXX_t types in sys/socket.h... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int -main (void) +main () { u_int8_t a; u_int16_t b; u_int32_t c; a = b = c = 1; ; return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO" -then : +if ac_fn_c_try_compile "$LINENO"; then : - printf "%s\n" "#define HAVE_U_INTXX_T 1" >>confdefs.h + $as_echo "#define HAVE_U_INTXX_T 1" >>confdefs.h - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } -else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for u_int64_t types" >&5 -printf %s "checking for u_int64_t types... " >&6; } -if test ${ac_cv_have_u_int64_t+y} -then : - printf %s "(cached) " >&6 -else $as_nop +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for u_int64_t types" >&5 +$as_echo_n "checking for u_int64_t types... " >&6; } +if ${ac_cv_have_u_int64_t+:} false; then : + $as_echo_n "(cached) " >&6 +else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int -main (void) +main () { u_int64_t a; a = 1; ; return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO" -then : +if ac_fn_c_try_compile "$LINENO"; then : ac_cv_have_u_int64_t="yes" -else $as_nop +else ac_cv_have_u_int64_t="no" fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_u_int64_t" >&5 -printf "%s\n" "$ac_cv_have_u_int64_t" >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_u_int64_t" >&5 +$as_echo "$ac_cv_have_u_int64_t" >&6; } if test "x$ac_cv_have_u_int64_t" = "xyes" ; then -printf "%s\n" "#define HAVE_U_INT64_T 1" >>confdefs.h +$as_echo "#define HAVE_U_INT64_T 1" >>confdefs.h have_u_int64_t=1 fi @@ -17978,42 +16235,40 @@ if (test -z "$have_u_int64_t" && \ test "x$ac_cv_header_sys_bitypes_h" = "xyes") then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for u_int64_t type in sys/bitypes.h" >&5 -printf %s "checking for u_int64_t type in sys/bitypes.h... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for u_int64_t type in sys/bitypes.h" >&5 +$as_echo_n "checking for u_int64_t type in sys/bitypes.h... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int -main (void) +main () { u_int64_t a; a = 1 ; return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO" -then : +if ac_fn_c_try_compile "$LINENO"; then : - printf "%s\n" "#define HAVE_U_INT64_T 1" >>confdefs.h + $as_echo "#define HAVE_U_INT64_T 1" >>confdefs.h - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } -else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi if test -z "$have_u_intxx_t" ; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for uintXX_t types" >&5 -printf %s "checking for uintXX_t types... " >&6; } -if test ${ac_cv_have_uintxx_t+y} -then : - printf %s "(cached) " >&6 -else $as_nop + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for uintXX_t types" >&5 +$as_echo_n "checking for uintXX_t types... " >&6; } +if ${ac_cv_have_uintxx_t+:} false; then : + $as_echo_n "(cached) " >&6 +else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -18021,7 +16276,7 @@ #include int -main (void) +main () { uint8_t a; @@ -18033,21 +16288,20 @@ return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO" -then : +if ac_fn_c_try_compile "$LINENO"; then : ac_cv_have_uintxx_t="yes" -else $as_nop +else ac_cv_have_uintxx_t="no" fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_uintxx_t" >&5 -printf "%s\n" "$ac_cv_have_uintxx_t" >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_uintxx_t" >&5 +$as_echo "$ac_cv_have_uintxx_t" >&6; } if test "x$ac_cv_have_uintxx_t" = "xyes" ; then -printf "%s\n" "#define HAVE_UINTXX_T 1" >>confdefs.h +$as_echo "#define HAVE_UINTXX_T 1" >>confdefs.h fi fi @@ -18055,79 +16309,77 @@ if (test -z "$have_uintxx_t" && \ test "x$ac_cv_header_stdint_h" = "xyes") then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for uintXX_t types in stdint.h" >&5 -printf %s "checking for uintXX_t types in stdint.h... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for uintXX_t types in stdint.h" >&5 +$as_echo_n "checking for uintXX_t types in stdint.h... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int -main (void) +main () { uint8_t a; uint16_t b; uint32_t c; a = b = c = 1; ; return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO" -then : +if ac_fn_c_try_compile "$LINENO"; then : - printf "%s\n" "#define HAVE_UINTXX_T 1" >>confdefs.h + $as_echo "#define HAVE_UINTXX_T 1" >>confdefs.h - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } -else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi if (test -z "$have_uintxx_t" && \ test "x$ac_cv_header_inttypes_h" = "xyes") then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for uintXX_t types in inttypes.h" >&5 -printf %s "checking for uintXX_t types in inttypes.h... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for uintXX_t types in inttypes.h" >&5 +$as_echo_n "checking for uintXX_t types in inttypes.h... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int -main (void) +main () { uint8_t a; uint16_t b; uint32_t c; a = b = c = 1; ; return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO" -then : +if ac_fn_c_try_compile "$LINENO"; then : - printf "%s\n" "#define HAVE_UINTXX_T 1" >>confdefs.h + $as_echo "#define HAVE_UINTXX_T 1" >>confdefs.h - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } -else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi if (test -z "$have_u_intxx_t" || test -z "$have_intxx_t" && \ test "x$ac_cv_header_sys_bitypes_h" = "xyes") then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for intXX_t and u_intXX_t types in sys/bitypes.h" >&5 -printf %s "checking for intXX_t and u_intXX_t types in sys/bitypes.h... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for intXX_t and u_intXX_t types in sys/bitypes.h" >&5 +$as_echo_n "checking for intXX_t and u_intXX_t types in sys/bitypes.h... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int -main (void) +main () { int8_t a; int16_t b; int32_t c; @@ -18138,58 +16390,55 @@ return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO" -then : +if ac_fn_c_try_compile "$LINENO"; then : - printf "%s\n" "#define HAVE_U_INTXX_T 1" >>confdefs.h + $as_echo "#define HAVE_U_INTXX_T 1" >>confdefs.h - printf "%s\n" "#define HAVE_INTXX_T 1" >>confdefs.h + $as_echo "#define HAVE_INTXX_T 1" >>confdefs.h - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } -else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for u_char" >&5 -printf %s "checking for u_char... " >&6; } -if test ${ac_cv_have_u_char+y} -then : - printf %s "(cached) " >&6 -else $as_nop +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for u_char" >&5 +$as_echo_n "checking for u_char... " >&6; } +if ${ac_cv_have_u_char+:} false; then : + $as_echo_n "(cached) " >&6 +else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int -main (void) +main () { u_char foo; foo = 125; ; return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO" -then : +if ac_fn_c_try_compile "$LINENO"; then : ac_cv_have_u_char="yes" -else $as_nop +else ac_cv_have_u_char="no" fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_u_char" >&5 -printf "%s\n" "$ac_cv_have_u_char" >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_u_char" >&5 +$as_echo "$ac_cv_have_u_char" >&6; } if test "x$ac_cv_have_u_char" = "xyes" ; then -printf "%s\n" "#define HAVE_U_CHAR 1" >>confdefs.h +$as_echo "#define HAVE_U_CHAR 1" >>confdefs.h fi @@ -18200,10 +16449,11 @@ #endif " -if test "x$ac_cv_type_intmax_t" = xyes -then : +if test "x$ac_cv_type_intmax_t" = xyes; then : -printf "%s\n" "#define HAVE_INTMAX_T 1" >>confdefs.h +cat >>confdefs.h <<_ACEOF +#define HAVE_INTMAX_T 1 +_ACEOF fi @@ -18214,10 +16464,11 @@ #endif " -if test "x$ac_cv_type_uintmax_t" = xyes -then : +if test "x$ac_cv_type_uintmax_t" = xyes; then : -printf "%s\n" "#define HAVE_UINTMAX_T 1" >>confdefs.h +cat >>confdefs.h <<_ACEOF +#define HAVE_UINTMAX_T 1 +_ACEOF fi @@ -18227,17 +16478,15 @@ ac_fn_c_check_type "$LINENO" "socklen_t" "ac_cv_type_socklen_t" "#include #include " -if test "x$ac_cv_type_socklen_t" = xyes -then : +if test "x$ac_cv_type_socklen_t" = xyes; then : -else $as_nop +else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for socklen_t equivalent" >&5 -printf %s "checking for socklen_t equivalent... " >&6; } - if test ${curl_cv_socklen_t_equiv+y} -then : - printf %s "(cached) " >&6 -else $as_nop + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for socklen_t equivalent" >&5 +$as_echo_n "checking for socklen_t equivalent... " >&6; } + if ${curl_cv_socklen_t_equiv+:} false; then : + $as_echo_n "(cached) " >&6 +else # Systems have either "struct sockaddr *" or # "void *" as the second argument to getpeername @@ -18253,7 +16502,7 @@ int getpeername (int, $arg2 *, $t *); int -main (void) +main () { $t len; @@ -18264,14 +16513,13 @@ } _ACEOF -if ac_fn_c_try_compile "$LINENO" -then : +if ac_fn_c_try_compile "$LINENO"; then : curl_cv_socklen_t_equiv="$t" break fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext done done @@ -18281,10 +16529,12 @@ fi - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $curl_cv_socklen_t_equiv" >&5 -printf "%s\n" "$curl_cv_socklen_t_equiv" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $curl_cv_socklen_t_equiv" >&5 +$as_echo "$curl_cv_socklen_t_equiv" >&6; } -printf "%s\n" "#define socklen_t $curl_cv_socklen_t_equiv" >>confdefs.h +cat >>confdefs.h <<_ACEOF +#define socklen_t $curl_cv_socklen_t_equiv +_ACEOF fi @@ -18292,19 +16542,11 @@ ac_fn_c_check_type "$LINENO" "sig_atomic_t" "ac_cv_type_sig_atomic_t" "#include " -if test "x$ac_cv_type_sig_atomic_t" = xyes -then : +if test "x$ac_cv_type_sig_atomic_t" = xyes; then : -printf "%s\n" "#define HAVE_SIG_ATOMIC_T 1" >>confdefs.h - - -fi -ac_fn_c_check_type "$LINENO" "sighandler_t" "ac_cv_type_sighandler_t" "#include -" -if test "x$ac_cv_type_sighandler_t" = xyes -then : - -printf "%s\n" "#define HAVE_SIGHANDLER_T 1" >>confdefs.h +cat >>confdefs.h <<_ACEOF +#define HAVE_SIG_ATOMIC_T 1 +_ACEOF fi @@ -18322,10 +16564,11 @@ #endif " -if test "x$ac_cv_type_fsblkcnt_t" = xyes -then : +if test "x$ac_cv_type_fsblkcnt_t" = xyes; then : -printf "%s\n" "#define HAVE_FSBLKCNT_T 1" >>confdefs.h +cat >>confdefs.h <<_ACEOF +#define HAVE_FSBLKCNT_T 1 +_ACEOF fi @@ -18342,15 +16585,17 @@ #endif " -if test "x$ac_cv_type_fsfilcnt_t" = xyes -then : +if test "x$ac_cv_type_fsfilcnt_t" = xyes; then : -printf "%s\n" "#define HAVE_FSFILCNT_T 1" >>confdefs.h +cat >>confdefs.h <<_ACEOF +#define HAVE_FSFILCNT_T 1 +_ACEOF fi + ac_fn_c_check_member "$LINENO" "struct statfs" "f_files" "ac_cv_member_struct_statfs_f_files" " #include #include @@ -18371,11 +16616,13 @@ #endif " -if test "x$ac_cv_member_struct_statfs_f_files" = xyes -then : +if test "x$ac_cv_member_struct_statfs_f_files" = xyes; then : + +fi -printf "%s\n" "#define HAVE_STRUCT_STATFS_F_FILES 1" >>confdefs.h +if test "x$ac_cv_member_struct_statfs_f_files" = "xyes" ; then +$as_echo "#define USE_STRUCT_STATFS 1" >>confdefs.h fi ac_fn_c_check_member "$LINENO" "struct statfs" "f_flags" "ac_cv_member_struct_statfs_f_flags" " @@ -18398,152 +16645,166 @@ #endif " -if test "x$ac_cv_member_struct_statfs_f_flags" = xyes -then : +if test "x$ac_cv_member_struct_statfs_f_flags" = xyes; then : -printf "%s\n" "#define HAVE_STRUCT_STATFS_F_FLAGS 1" >>confdefs.h +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_STATFS_F_FLAGS 1 +_ACEOF fi +for ac_header in arpa/inet.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "arpa/inet.h" "ac_cv_header_arpa_inet_h" "$ac_includes_default" +if test "x$ac_cv_header_arpa_inet_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_ARPA_INET_H 1 +_ACEOF + +fi + +done + ac_fn_c_check_type "$LINENO" "in_addr_t" "ac_cv_type_in_addr_t" "#include +#ifdef HAVE_ARPA_INET_H +#include +#endif #include " -if test "x$ac_cv_type_in_addr_t" = xyes -then : +if test "x$ac_cv_type_in_addr_t" = xyes; then : -printf "%s\n" "#define HAVE_IN_ADDR_T 1" >>confdefs.h +cat >>confdefs.h <<_ACEOF +#define HAVE_IN_ADDR_T 1 +_ACEOF fi ac_fn_c_check_type "$LINENO" "in_port_t" "ac_cv_type_in_port_t" "#include +#ifdef HAVE_ARPA_INET_H +#include +#endif #include " -if test "x$ac_cv_type_in_port_t" = xyes -then : +if test "x$ac_cv_type_in_port_t" = xyes; then : -printf "%s\n" "#define HAVE_IN_PORT_T 1" >>confdefs.h +cat >>confdefs.h <<_ACEOF +#define HAVE_IN_PORT_T 1 +_ACEOF fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for size_t" >&5 -printf %s "checking for size_t... " >&6; } -if test ${ac_cv_have_size_t+y} -then : - printf %s "(cached) " >&6 -else $as_nop +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for size_t" >&5 +$as_echo_n "checking for size_t... " >&6; } +if ${ac_cv_have_size_t+:} false; then : + $as_echo_n "(cached) " >&6 +else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int -main (void) +main () { size_t foo; foo = 1235; ; return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO" -then : +if ac_fn_c_try_compile "$LINENO"; then : ac_cv_have_size_t="yes" -else $as_nop +else ac_cv_have_size_t="no" fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_size_t" >&5 -printf "%s\n" "$ac_cv_have_size_t" >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_size_t" >&5 +$as_echo "$ac_cv_have_size_t" >&6; } if test "x$ac_cv_have_size_t" = "xyes" ; then -printf "%s\n" "#define HAVE_SIZE_T 1" >>confdefs.h +$as_echo "#define HAVE_SIZE_T 1" >>confdefs.h fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ssize_t" >&5 -printf %s "checking for ssize_t... " >&6; } -if test ${ac_cv_have_ssize_t+y} -then : - printf %s "(cached) " >&6 -else $as_nop +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ssize_t" >&5 +$as_echo_n "checking for ssize_t... " >&6; } +if ${ac_cv_have_ssize_t+:} false; then : + $as_echo_n "(cached) " >&6 +else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int -main (void) +main () { ssize_t foo; foo = 1235; ; return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO" -then : +if ac_fn_c_try_compile "$LINENO"; then : ac_cv_have_ssize_t="yes" -else $as_nop +else ac_cv_have_ssize_t="no" fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_ssize_t" >&5 -printf "%s\n" "$ac_cv_have_ssize_t" >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_ssize_t" >&5 +$as_echo "$ac_cv_have_ssize_t" >&6; } if test "x$ac_cv_have_ssize_t" = "xyes" ; then -printf "%s\n" "#define HAVE_SSIZE_T 1" >>confdefs.h +$as_echo "#define HAVE_SSIZE_T 1" >>confdefs.h fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for clock_t" >&5 -printf %s "checking for clock_t... " >&6; } -if test ${ac_cv_have_clock_t+y} -then : - printf %s "(cached) " >&6 -else $as_nop +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for clock_t" >&5 +$as_echo_n "checking for clock_t... " >&6; } +if ${ac_cv_have_clock_t+:} false; then : + $as_echo_n "(cached) " >&6 +else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int -main (void) +main () { clock_t foo; foo = 1235; ; return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO" -then : +if ac_fn_c_try_compile "$LINENO"; then : ac_cv_have_clock_t="yes" -else $as_nop +else ac_cv_have_clock_t="no" fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_clock_t" >&5 -printf "%s\n" "$ac_cv_have_clock_t" >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_clock_t" >&5 +$as_echo "$ac_cv_have_clock_t" >&6; } if test "x$ac_cv_have_clock_t" = "xyes" ; then -printf "%s\n" "#define HAVE_CLOCK_T 1" >>confdefs.h +$as_echo "#define HAVE_CLOCK_T 1" >>confdefs.h fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for sa_family_t" >&5 -printf %s "checking for sa_family_t... " >&6; } -if test ${ac_cv_have_sa_family_t+y} -then : - printf %s "(cached) " >&6 -else $as_nop +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for sa_family_t" >&5 +$as_echo_n "checking for sa_family_t... " >&6; } +if ${ac_cv_have_sa_family_t+:} false; then : + $as_echo_n "(cached) " >&6 +else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -18552,17 +16813,16 @@ #include int -main (void) +main () { sa_family_t foo; foo = 1235; ; return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO" -then : +if ac_fn_c_try_compile "$LINENO"; then : ac_cv_have_sa_family_t="yes" -else $as_nop +else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -18571,113 +16831,107 @@ #include int -main (void) +main () { sa_family_t foo; foo = 1235; ; return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO" -then : +if ac_fn_c_try_compile "$LINENO"; then : ac_cv_have_sa_family_t="yes" -else $as_nop +else ac_cv_have_sa_family_t="no" fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_sa_family_t" >&5 -printf "%s\n" "$ac_cv_have_sa_family_t" >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_sa_family_t" >&5 +$as_echo "$ac_cv_have_sa_family_t" >&6; } if test "x$ac_cv_have_sa_family_t" = "xyes" ; then -printf "%s\n" "#define HAVE_SA_FAMILY_T 1" >>confdefs.h +$as_echo "#define HAVE_SA_FAMILY_T 1" >>confdefs.h fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for pid_t" >&5 -printf %s "checking for pid_t... " >&6; } -if test ${ac_cv_have_pid_t+y} -then : - printf %s "(cached) " >&6 -else $as_nop +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for pid_t" >&5 +$as_echo_n "checking for pid_t... " >&6; } +if ${ac_cv_have_pid_t+:} false; then : + $as_echo_n "(cached) " >&6 +else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int -main (void) +main () { pid_t foo; foo = 1235; ; return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO" -then : +if ac_fn_c_try_compile "$LINENO"; then : ac_cv_have_pid_t="yes" -else $as_nop +else ac_cv_have_pid_t="no" fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_pid_t" >&5 -printf "%s\n" "$ac_cv_have_pid_t" >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_pid_t" >&5 +$as_echo "$ac_cv_have_pid_t" >&6; } if test "x$ac_cv_have_pid_t" = "xyes" ; then -printf "%s\n" "#define HAVE_PID_T 1" >>confdefs.h +$as_echo "#define HAVE_PID_T 1" >>confdefs.h fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for mode_t" >&5 -printf %s "checking for mode_t... " >&6; } -if test ${ac_cv_have_mode_t+y} -then : - printf %s "(cached) " >&6 -else $as_nop +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for mode_t" >&5 +$as_echo_n "checking for mode_t... " >&6; } +if ${ac_cv_have_mode_t+:} false; then : + $as_echo_n "(cached) " >&6 +else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int -main (void) +main () { mode_t foo; foo = 1235; ; return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO" -then : +if ac_fn_c_try_compile "$LINENO"; then : ac_cv_have_mode_t="yes" -else $as_nop +else ac_cv_have_mode_t="no" fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_mode_t" >&5 -printf "%s\n" "$ac_cv_have_mode_t" >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_mode_t" >&5 +$as_echo "$ac_cv_have_mode_t" >&6; } if test "x$ac_cv_have_mode_t" = "xyes" ; then -printf "%s\n" "#define HAVE_MODE_T 1" >>confdefs.h +$as_echo "#define HAVE_MODE_T 1" >>confdefs.h fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for struct sockaddr_storage" >&5 -printf %s "checking for struct sockaddr_storage... " >&6; } -if test ${ac_cv_have_struct_sockaddr_storage+y} -then : - printf %s "(cached) " >&6 -else $as_nop +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for struct sockaddr_storage" >&5 +$as_echo_n "checking for struct sockaddr_storage... " >&6; } +if ${ac_cv_have_struct_sockaddr_storage+:} false; then : + $as_echo_n "(cached) " >&6 +else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -18686,37 +16940,35 @@ #include int -main (void) +main () { struct sockaddr_storage s; ; return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO" -then : +if ac_fn_c_try_compile "$LINENO"; then : ac_cv_have_struct_sockaddr_storage="yes" -else $as_nop +else ac_cv_have_struct_sockaddr_storage="no" fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_struct_sockaddr_storage" >&5 -printf "%s\n" "$ac_cv_have_struct_sockaddr_storage" >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_struct_sockaddr_storage" >&5 +$as_echo "$ac_cv_have_struct_sockaddr_storage" >&6; } if test "x$ac_cv_have_struct_sockaddr_storage" = "xyes" ; then -printf "%s\n" "#define HAVE_STRUCT_SOCKADDR_STORAGE 1" >>confdefs.h +$as_echo "#define HAVE_STRUCT_SOCKADDR_STORAGE 1" >>confdefs.h fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for struct sockaddr_in6" >&5 -printf %s "checking for struct sockaddr_in6... " >&6; } -if test ${ac_cv_have_struct_sockaddr_in6+y} -then : - printf %s "(cached) " >&6 -else $as_nop +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for struct sockaddr_in6" >&5 +$as_echo_n "checking for struct sockaddr_in6... " >&6; } +if ${ac_cv_have_struct_sockaddr_in6+:} false; then : + $as_echo_n "(cached) " >&6 +else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -18725,37 +16977,35 @@ #include int -main (void) +main () { struct sockaddr_in6 s; s.sin6_family = 0; ; return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO" -then : +if ac_fn_c_try_compile "$LINENO"; then : ac_cv_have_struct_sockaddr_in6="yes" -else $as_nop +else ac_cv_have_struct_sockaddr_in6="no" fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_struct_sockaddr_in6" >&5 -printf "%s\n" "$ac_cv_have_struct_sockaddr_in6" >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_struct_sockaddr_in6" >&5 +$as_echo "$ac_cv_have_struct_sockaddr_in6" >&6; } if test "x$ac_cv_have_struct_sockaddr_in6" = "xyes" ; then -printf "%s\n" "#define HAVE_STRUCT_SOCKADDR_IN6 1" >>confdefs.h +$as_echo "#define HAVE_STRUCT_SOCKADDR_IN6 1" >>confdefs.h fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for struct in6_addr" >&5 -printf %s "checking for struct in6_addr... " >&6; } -if test ${ac_cv_have_struct_in6_addr+y} -then : - printf %s "(cached) " >&6 -else $as_nop +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for struct in6_addr" >&5 +$as_echo_n "checking for struct in6_addr... " >&6; } +if ${ac_cv_have_struct_in6_addr+:} false; then : + $as_echo_n "(cached) " >&6 +else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -18764,28 +17014,27 @@ #include int -main (void) +main () { struct in6_addr s; s.s6_addr[0] = 0; ; return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO" -then : +if ac_fn_c_try_compile "$LINENO"; then : ac_cv_have_struct_in6_addr="yes" -else $as_nop +else ac_cv_have_struct_in6_addr="no" fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_struct_in6_addr" >&5 -printf "%s\n" "$ac_cv_have_struct_in6_addr" >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_struct_in6_addr" >&5 +$as_echo "$ac_cv_have_struct_in6_addr" >&6; } if test "x$ac_cv_have_struct_in6_addr" = "xyes" ; then -printf "%s\n" "#define HAVE_STRUCT_IN6_ADDR 1" >>confdefs.h +$as_echo "#define HAVE_STRUCT_IN6_ADDR 1" >>confdefs.h ac_fn_c_check_member "$LINENO" "struct sockaddr_in6" "sin6_scope_id" "ac_cv_member_struct_sockaddr_in6_sin6_scope_id" " @@ -18795,22 +17044,22 @@ #include " -if test "x$ac_cv_member_struct_sockaddr_in6_sin6_scope_id" = xyes -then : +if test "x$ac_cv_member_struct_sockaddr_in6_sin6_scope_id" = xyes; then : -printf "%s\n" "#define HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID 1" >>confdefs.h +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID 1 +_ACEOF fi fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for struct addrinfo" >&5 -printf %s "checking for struct addrinfo... " >&6; } -if test ${ac_cv_have_struct_addrinfo+y} -then : - printf %s "(cached) " >&6 -else $as_nop +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for struct addrinfo" >&5 +$as_echo_n "checking for struct addrinfo... " >&6; } +if ${ac_cv_have_struct_addrinfo+:} false; then : + $as_echo_n "(cached) " >&6 +else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -18820,178 +17069,355 @@ #include int -main (void) +main () { struct addrinfo s; s.ai_flags = AI_PASSIVE; ; return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO" -then : +if ac_fn_c_try_compile "$LINENO"; then : ac_cv_have_struct_addrinfo="yes" -else $as_nop +else ac_cv_have_struct_addrinfo="no" fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_struct_addrinfo" >&5 -printf "%s\n" "$ac_cv_have_struct_addrinfo" >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_struct_addrinfo" >&5 +$as_echo "$ac_cv_have_struct_addrinfo" >&6; } if test "x$ac_cv_have_struct_addrinfo" = "xyes" ; then -printf "%s\n" "#define HAVE_STRUCT_ADDRINFO 1" >>confdefs.h +$as_echo "#define HAVE_STRUCT_ADDRINFO 1" >>confdefs.h fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for struct timeval" >&5 -printf %s "checking for struct timeval... " >&6; } -if test ${ac_cv_have_struct_timeval+y} -then : - printf %s "(cached) " >&6 -else $as_nop +# useless checks as progmam code uses time* structures unconditionally +ac_fn_c_check_type "$LINENO" "struct timeval" "ac_cv_type_struct_timeval" " +#ifdef HAVE_SYS_TIME_H +# include +#endif - cat confdefs.h - <<_ACEOF >conftest.$ac_ext +" +if test "x$ac_cv_type_struct_timeval" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_TIMEVAL 1 +_ACEOF + + +fi + +ac_fn_c_check_type "$LINENO" "struct timespec" "ac_cv_type_struct_timespec" "$ac_includes_default" +if test "x$ac_cv_type_struct_timespec" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_TIMESPEC 1 +_ACEOF + + +fi + + +# We need int64_t or else certain parts of the compile will fail. +if test "x$ac_cv_have_int64_t" = "xno" && \ + test "x$ac_cv_sizeof_long_int" != "x8" && \ + test "x$ac_cv_sizeof_long_long_int" = "x0" ; then + as_fn_error $? "*** $PACKAGE_NAME requires int64_t support. + Contact your vendor or install an alternative compiler (I.E., GCC) before continuing. + " "$LINENO" 5 +fi + + +if test "x$ac_cv_func_snprintf" = "xyes" ; then +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether snprintf correctly terminates long strings" >&5 +$as_echo_n "checking whether snprintf correctly terminates long strings... " >&6; } +if ${ssh_cv_func_snprintf_long_string+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "$cross_compiling" = yes; then : + ssh_cv_func_snprintf_long_string=cross + +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ - #include + +#include + int -main (void) +main () { - struct timeval tv; tv.tv_sec = 1; + +char b[5]; +snprintf(b,5,"123456789"); +if (b[4] != '\0') + return 1; + ; return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO" -then : - ac_cv_have_struct_timeval="yes" -else $as_nop - ac_cv_have_struct_timeval="no" - +if ac_fn_c_try_run "$LINENO"; then : + ssh_cv_func_snprintf_long_string=yes +else + ssh_cv_func_snprintf_long_string=no fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext - +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_struct_timeval" >&5 -printf "%s\n" "$ac_cv_have_struct_timeval" >&6; } -if test "x$ac_cv_have_struct_timeval" = "xyes" ; then - -printf "%s\n" "#define HAVE_STRUCT_TIMEVAL 1" >>confdefs.h - have_struct_timeval=1 +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ssh_cv_func_snprintf_long_string" >&5 +$as_echo "$ssh_cv_func_snprintf_long_string" >&6; } +if test $ssh_cv_func_snprintf_long_string = cross ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: assuming snprintf correctly terminates long strings" >&5 +$as_echo "$as_me: WARNING: cross compiling: assuming snprintf correctly terminates long strings" >&2;} + ssh_cv_func_snprintf_long_string=yes +fi +if test $ssh_cv_func_snprintf_long_string != yes ; then + ssh_snprintf_broken=yes + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: *** Broken function snprintf() - does not correctly terminates long strings" >&5 +$as_echo "$as_me: WARNING: *** Broken function snprintf() - does not correctly terminates long strings" >&2;} +fi fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for struct timespec" >&5 -printf %s "checking for struct timespec... " >&6; } -if test ${ac_cv_have_struct_timespec+y} -then : - printf %s "(cached) " >&6 -else $as_nop +if test "x$ac_cv_func_vsnprintf" = "xyes" && test "x$ssh_snprintf_broken" != xyes ; then +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether vsnprintf returns correct values on overflow" >&5 +$as_echo_n "checking whether vsnprintf returns correct values on overflow... " >&6; } +if ${ssh_cv_func_vsnprintf_overflow+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "$cross_compiling" = yes; then : + ssh_cv_func_vsnprintf_overflow=cross - cat confdefs.h - <<_ACEOF >conftest.$ac_ext +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ - #ifdef HAVE_SYS_TIME_H - # include - #endif - #ifdef HAVE_TIME_H - # include - #endif +#include +#include +#include + +int +x_snprintf(char *str, size_t count, const char *fmt, ...) { + size_t ret; + va_list ap; + + va_start(ap, fmt); + ret = vsnprintf(str, count, fmt, ap); + va_end(ap); + + return ret; +} int -main (void) +main () { - struct timespec ts; ts.tv_sec = 1; + +char x[1]; +if (x_snprintf(x, 1, "%s %d", "hello", 12345) != 11) + return 1; +if (x_snprintf(NULL, 0, "%s %d", "hello", 12345) != 11) + return 1; + ; return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO" -then : - ac_cv_have_struct_timespec="yes" -else $as_nop - ac_cv_have_struct_timespec="no" - +if ac_fn_c_try_run "$LINENO"; then : + ssh_cv_func_vsnprintf_overflow=yes +else + ssh_cv_func_vsnprintf_overflow=no fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext - +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_struct_timespec" >&5 -printf "%s\n" "$ac_cv_have_struct_timespec" >&6; } -if test "x$ac_cv_have_struct_timespec" = "xyes" ; then - -printf "%s\n" "#define HAVE_STRUCT_TIMESPEC 1" >>confdefs.h - have_struct_timespec=1 +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ssh_cv_func_vsnprintf_overflow" >&5 +$as_echo "$ssh_cv_func_vsnprintf_overflow" >&6; } +if test $ssh_cv_func_vsnprintf_overflow = cross ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: assuming vsnprintf() returns correct values on overflow" >&5 +$as_echo "$as_me: WARNING: cross compiling: assuming vsnprintf() returns correct values on overflow" >&2;} + ssh_cv_func_vsnprintf_overflow=yes +fi +if test $ssh_cv_func_vsnprintf_overflow != yes ; then + ssh_snprintf_broken=yes + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: *** Broken function vsnprintf() - does not returns correct values on overflow" >&5 +$as_echo "$as_me: WARNING: *** Broken function vsnprintf() - does not returns correct values on overflow" >&2;} +fi fi -# We need int64_t or else certain parts of the compile will fail. -if test "x$ac_cv_have_int64_t" = "xno" && \ - test "x$ac_cv_sizeof_long_int" != "x8" && \ - test "x$ac_cv_sizeof_long_long_int" = "x0" ; then - echo "OpenSSH requires int64_t support. Contact your vendor or install" - echo "an alternative compiler (I.E., GCC) before continuing." - echo "" - exit 1; +if test "x$ac_cv_func_snprintf" = "xyes" && test "x$ssh_snprintf_broken" != xyes ; then +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether snprintf understands %lld format" >&5 +$as_echo_n "checking whether snprintf understands %lld format... " >&6; } +if ${ssh_cv_func_snprintf_fmt_lld+:} false; then : + $as_echo_n "(cached) " >&6 else - if test "$cross_compiling" = yes -then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: Assuming working snprintf()" >&5 -printf "%s\n" "$as_me: WARNING: cross compiling: Assuming working snprintf()" >&2;} + if test "$cross_compiling" = yes; then : + ssh_cv_func_snprintf_fmt_lld=cross -else $as_nop +else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include -#include #include -#ifdef HAVE_SNPRINTF -int main(void) + +int +main () { - char buf[50]; - char expected_out[50]; - int mazsize = 50 ; + +char buf[50]; +char expected_out[50]; +int mazsize = 50 ; #if (SIZEOF_LONG_INT == 8) - long int num = 0x7fffffffffffffff; +long int num = 0x7fffffffffffffff; #else - long long num = 0x7fffffffffffffffll; -#endif - strcpy(expected_out, "9223372036854775807"); - snprintf(buf, mazsize, "%lld", num); - if(strcmp(buf, expected_out) != 0) - exit(1); - exit(0); -} -#else -int main(void) { exit(0); } +long long num = 0x7fffffffffffffffll; #endif +strcpy(expected_out, "9223372036854775807"); +snprintf(buf, mazsize, "%lld", num); +if (strcmp(buf, expected_out) != 0) + return 1; + ; + return 0; +} _ACEOF -if ac_fn_c_try_run "$LINENO" -then : - true -else $as_nop - printf "%s\n" "#define BROKEN_SNPRINTF 1" >>confdefs.h +if ac_fn_c_try_run "$LINENO"; then : + ssh_cv_func_snprintf_fmt_lld=yes +else + ssh_cv_func_snprintf_fmt_lld=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ssh_cv_func_snprintf_fmt_lld" >&5 +$as_echo "$ssh_cv_func_snprintf_fmt_lld" >&6; } +if test $ssh_cv_func_snprintf_fmt_lld = cross ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: assuming snprintf() understands %lld format" >&5 +$as_echo "$as_me: WARNING: cross compiling: assuming snprintf() understands %lld format" >&2;} + ssh_cv_func_snprintf_fmt_lld=yes +fi +if test $ssh_cv_func_snprintf_fmt_lld != yes ; then + ssh_snprintf_broken=yes + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: *** Outdated function snprintf() - does not understand %lld format" >&5 +$as_echo "$as_me: WARNING: *** Outdated function snprintf() - does not understand %lld format" >&2;} +fi +fi + +if test "x$ac_cv_func_snprintf" = "xyes" && test "x$ssh_snprintf_broken" != xyes ; then +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether snprintf understands %zu format" >&5 +$as_echo_n "checking whether snprintf understands %zu format... " >&6; } +if ${ssh_cv_func_snprintf_fmt_zu+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "$cross_compiling" = yes; then : + ssh_cv_func_snprintf_fmt_zu=cross + +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include +#include +#include + +int +main () +{ + +size_t a = 1, b = 2; +char z[128]; +snprintf(z, sizeof z, "%zu%zu", a, b); +if (strcmp(z, "12") != 0) + return 1; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + ssh_cv_func_snprintf_fmt_zu=yes +else + ssh_cv_func_snprintf_fmt_zu=no +fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ssh_cv_func_snprintf_fmt_zu" >&5 +$as_echo "$ssh_cv_func_snprintf_fmt_zu" >&6; } +if test $ssh_cv_func_snprintf_fmt_zu = cross ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: assuming snprintf() understands %zu format" >&5 +$as_echo "$as_me: WARNING: cross compiling: assuming snprintf() understands %zu format" >&2;} + ssh_cv_func_snprintf_fmt_zu=yes +fi +if test $ssh_cv_func_snprintf_fmt_zu != yes ; then + ssh_snprintf_broken=yes + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: *** Outdated function snprintf() - does not understand %zu format" >&5 +$as_echo "$as_me: WARNING: *** Outdated function snprintf() - does not understand %zu format" >&2;} +fi +fi + +if test "x$ssh_snprintf_broken" = xyes ; then + +$as_echo "#define BROKEN_SNPRINTF 1" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether snprintf declare const char *fmt" >&5 +$as_echo_n "checking whether snprintf declare const char *fmt... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include +int snprintf(char *a, size_t b, const char *c, ...) +#ifndef NO_ATTRIBUTE_ON_PROTOTYPE_ARGS +__attribute__ ((__format__ (__printf__, 3, 4))) +#endif +; +int snprintf(char *a, size_t b, const char *c, ...) { return 0; } + +int +main () +{ + +snprintf(0, 0, 0); + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ssh_snprintf_const_fmt=yes +else + ssh_snprintf_const_fmt=no + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ssh_snprintf_const_fmt" >&5 +$as_echo "$ssh_snprintf_const_fmt" >&6; } +fi +if test "x$ssh_snprintf_const_fmt" = xyes ; then + +$as_echo "#define SNPRINTF_CONST const" >>confdefs.h + +fi + # look for field 'ut_host' in header 'utmp.h' ossh_safe=`echo "utmp.h" | sed 'y%./+-%__p_%'` ossh_varname="ossh_cv_$ossh_safe""_has_"ut_host - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ut_host field in utmp.h" >&5 -printf %s "checking for ut_host field in utmp.h... " >&6; } - if eval test \${$ossh_varname+y} -then : - printf %s "(cached) " >&6 -else $as_nop + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ut_host field in utmp.h" >&5 +$as_echo_n "checking for ut_host field in utmp.h... " >&6; } + if eval \${$ossh_varname+:} false; then : + $as_echo_n "(cached) " >&6 +else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -18999,40 +17425,38 @@ _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - $EGREP "ut_host" >/dev/null 2>&1 -then : + $EGREP "ut_host" >/dev/null 2>&1; then : eval "$ossh_varname=yes" -else $as_nop +else eval "$ossh_varname=no" fi -rm -rf conftest* +rm -f conftest* fi ossh_result=`eval 'echo $'"$ossh_varname"` if test -n "`echo $ossh_varname`"; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ossh_result" >&5 -printf "%s\n" "$ossh_result" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ossh_result" >&5 +$as_echo "$ossh_result" >&6; } if test "x$ossh_result" = "xyes"; then -printf "%s\n" "#define HAVE_HOST_IN_UTMP 1" >>confdefs.h +$as_echo "#define HAVE_HOST_IN_UTMP 1" >>confdefs.h fi else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } fi # look for field 'ut_host' in header 'utmpx.h' ossh_safe=`echo "utmpx.h" | sed 'y%./+-%__p_%'` ossh_varname="ossh_cv_$ossh_safe""_has_"ut_host - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ut_host field in utmpx.h" >&5 -printf %s "checking for ut_host field in utmpx.h... " >&6; } - if eval test \${$ossh_varname+y} -then : - printf %s "(cached) " >&6 -else $as_nop + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ut_host field in utmpx.h" >&5 +$as_echo_n "checking for ut_host field in utmpx.h... " >&6; } + if eval \${$ossh_varname+:} false; then : + $as_echo_n "(cached) " >&6 +else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -19040,40 +17464,38 @@ _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - $EGREP "ut_host" >/dev/null 2>&1 -then : + $EGREP "ut_host" >/dev/null 2>&1; then : eval "$ossh_varname=yes" -else $as_nop +else eval "$ossh_varname=no" fi -rm -rf conftest* +rm -f conftest* fi ossh_result=`eval 'echo $'"$ossh_varname"` if test -n "`echo $ossh_varname`"; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ossh_result" >&5 -printf "%s\n" "$ossh_result" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ossh_result" >&5 +$as_echo "$ossh_result" >&6; } if test "x$ossh_result" = "xyes"; then -printf "%s\n" "#define HAVE_HOST_IN_UTMPX 1" >>confdefs.h +$as_echo "#define HAVE_HOST_IN_UTMPX 1" >>confdefs.h fi else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } fi # look for field 'syslen' in header 'utmpx.h' ossh_safe=`echo "utmpx.h" | sed 'y%./+-%__p_%'` ossh_varname="ossh_cv_$ossh_safe""_has_"syslen - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for syslen field in utmpx.h" >&5 -printf %s "checking for syslen field in utmpx.h... " >&6; } - if eval test \${$ossh_varname+y} -then : - printf %s "(cached) " >&6 -else $as_nop + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for syslen field in utmpx.h" >&5 +$as_echo_n "checking for syslen field in utmpx.h... " >&6; } + if eval \${$ossh_varname+:} false; then : + $as_echo_n "(cached) " >&6 +else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -19081,40 +17503,38 @@ _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - $EGREP "syslen" >/dev/null 2>&1 -then : + $EGREP "syslen" >/dev/null 2>&1; then : eval "$ossh_varname=yes" -else $as_nop +else eval "$ossh_varname=no" fi -rm -rf conftest* +rm -f conftest* fi ossh_result=`eval 'echo $'"$ossh_varname"` if test -n "`echo $ossh_varname`"; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ossh_result" >&5 -printf "%s\n" "$ossh_result" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ossh_result" >&5 +$as_echo "$ossh_result" >&6; } if test "x$ossh_result" = "xyes"; then -printf "%s\n" "#define HAVE_SYSLEN_IN_UTMPX 1" >>confdefs.h +$as_echo "#define HAVE_SYSLEN_IN_UTMPX 1" >>confdefs.h fi else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } fi # look for field 'ut_pid' in header 'utmp.h' ossh_safe=`echo "utmp.h" | sed 'y%./+-%__p_%'` ossh_varname="ossh_cv_$ossh_safe""_has_"ut_pid - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ut_pid field in utmp.h" >&5 -printf %s "checking for ut_pid field in utmp.h... " >&6; } - if eval test \${$ossh_varname+y} -then : - printf %s "(cached) " >&6 -else $as_nop + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ut_pid field in utmp.h" >&5 +$as_echo_n "checking for ut_pid field in utmp.h... " >&6; } + if eval \${$ossh_varname+:} false; then : + $as_echo_n "(cached) " >&6 +else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -19122,40 +17542,38 @@ _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - $EGREP "ut_pid" >/dev/null 2>&1 -then : + $EGREP "ut_pid" >/dev/null 2>&1; then : eval "$ossh_varname=yes" -else $as_nop +else eval "$ossh_varname=no" fi -rm -rf conftest* +rm -f conftest* fi ossh_result=`eval 'echo $'"$ossh_varname"` if test -n "`echo $ossh_varname`"; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ossh_result" >&5 -printf "%s\n" "$ossh_result" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ossh_result" >&5 +$as_echo "$ossh_result" >&6; } if test "x$ossh_result" = "xyes"; then -printf "%s\n" "#define HAVE_PID_IN_UTMP 1" >>confdefs.h +$as_echo "#define HAVE_PID_IN_UTMP 1" >>confdefs.h fi else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } fi # look for field 'ut_type' in header 'utmp.h' ossh_safe=`echo "utmp.h" | sed 'y%./+-%__p_%'` ossh_varname="ossh_cv_$ossh_safe""_has_"ut_type - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ut_type field in utmp.h" >&5 -printf %s "checking for ut_type field in utmp.h... " >&6; } - if eval test \${$ossh_varname+y} -then : - printf %s "(cached) " >&6 -else $as_nop + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ut_type field in utmp.h" >&5 +$as_echo_n "checking for ut_type field in utmp.h... " >&6; } + if eval \${$ossh_varname+:} false; then : + $as_echo_n "(cached) " >&6 +else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -19163,40 +17581,38 @@ _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - $EGREP "ut_type" >/dev/null 2>&1 -then : + $EGREP "ut_type" >/dev/null 2>&1; then : eval "$ossh_varname=yes" -else $as_nop +else eval "$ossh_varname=no" fi -rm -rf conftest* +rm -f conftest* fi ossh_result=`eval 'echo $'"$ossh_varname"` if test -n "`echo $ossh_varname`"; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ossh_result" >&5 -printf "%s\n" "$ossh_result" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ossh_result" >&5 +$as_echo "$ossh_result" >&6; } if test "x$ossh_result" = "xyes"; then -printf "%s\n" "#define HAVE_TYPE_IN_UTMP 1" >>confdefs.h +$as_echo "#define HAVE_TYPE_IN_UTMP 1" >>confdefs.h fi else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } fi # look for field 'ut_type' in header 'utmpx.h' ossh_safe=`echo "utmpx.h" | sed 'y%./+-%__p_%'` ossh_varname="ossh_cv_$ossh_safe""_has_"ut_type - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ut_type field in utmpx.h" >&5 -printf %s "checking for ut_type field in utmpx.h... " >&6; } - if eval test \${$ossh_varname+y} -then : - printf %s "(cached) " >&6 -else $as_nop + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ut_type field in utmpx.h" >&5 +$as_echo_n "checking for ut_type field in utmpx.h... " >&6; } + if eval \${$ossh_varname+:} false; then : + $as_echo_n "(cached) " >&6 +else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -19204,40 +17620,38 @@ _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - $EGREP "ut_type" >/dev/null 2>&1 -then : + $EGREP "ut_type" >/dev/null 2>&1; then : eval "$ossh_varname=yes" -else $as_nop +else eval "$ossh_varname=no" fi -rm -rf conftest* +rm -f conftest* fi ossh_result=`eval 'echo $'"$ossh_varname"` if test -n "`echo $ossh_varname`"; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ossh_result" >&5 -printf "%s\n" "$ossh_result" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ossh_result" >&5 +$as_echo "$ossh_result" >&6; } if test "x$ossh_result" = "xyes"; then -printf "%s\n" "#define HAVE_TYPE_IN_UTMPX 1" >>confdefs.h +$as_echo "#define HAVE_TYPE_IN_UTMPX 1" >>confdefs.h fi else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } fi # look for field 'ut_tv' in header 'utmp.h' ossh_safe=`echo "utmp.h" | sed 'y%./+-%__p_%'` ossh_varname="ossh_cv_$ossh_safe""_has_"ut_tv - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ut_tv field in utmp.h" >&5 -printf %s "checking for ut_tv field in utmp.h... " >&6; } - if eval test \${$ossh_varname+y} -then : - printf %s "(cached) " >&6 -else $as_nop + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ut_tv field in utmp.h" >&5 +$as_echo_n "checking for ut_tv field in utmp.h... " >&6; } + if eval \${$ossh_varname+:} false; then : + $as_echo_n "(cached) " >&6 +else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -19245,40 +17659,38 @@ _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - $EGREP "ut_tv" >/dev/null 2>&1 -then : + $EGREP "ut_tv" >/dev/null 2>&1; then : eval "$ossh_varname=yes" -else $as_nop +else eval "$ossh_varname=no" fi -rm -rf conftest* +rm -f conftest* fi ossh_result=`eval 'echo $'"$ossh_varname"` if test -n "`echo $ossh_varname`"; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ossh_result" >&5 -printf "%s\n" "$ossh_result" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ossh_result" >&5 +$as_echo "$ossh_result" >&6; } if test "x$ossh_result" = "xyes"; then -printf "%s\n" "#define HAVE_TV_IN_UTMP 1" >>confdefs.h +$as_echo "#define HAVE_TV_IN_UTMP 1" >>confdefs.h fi else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } fi # look for field 'ut_id' in header 'utmp.h' ossh_safe=`echo "utmp.h" | sed 'y%./+-%__p_%'` ossh_varname="ossh_cv_$ossh_safe""_has_"ut_id - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ut_id field in utmp.h" >&5 -printf %s "checking for ut_id field in utmp.h... " >&6; } - if eval test \${$ossh_varname+y} -then : - printf %s "(cached) " >&6 -else $as_nop + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ut_id field in utmp.h" >&5 +$as_echo_n "checking for ut_id field in utmp.h... " >&6; } + if eval \${$ossh_varname+:} false; then : + $as_echo_n "(cached) " >&6 +else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -19286,40 +17698,38 @@ _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - $EGREP "ut_id" >/dev/null 2>&1 -then : + $EGREP "ut_id" >/dev/null 2>&1; then : eval "$ossh_varname=yes" -else $as_nop +else eval "$ossh_varname=no" fi -rm -rf conftest* +rm -f conftest* fi ossh_result=`eval 'echo $'"$ossh_varname"` if test -n "`echo $ossh_varname`"; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ossh_result" >&5 -printf "%s\n" "$ossh_result" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ossh_result" >&5 +$as_echo "$ossh_result" >&6; } if test "x$ossh_result" = "xyes"; then -printf "%s\n" "#define HAVE_ID_IN_UTMP 1" >>confdefs.h +$as_echo "#define HAVE_ID_IN_UTMP 1" >>confdefs.h fi else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } fi # look for field 'ut_id' in header 'utmpx.h' ossh_safe=`echo "utmpx.h" | sed 'y%./+-%__p_%'` ossh_varname="ossh_cv_$ossh_safe""_has_"ut_id - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ut_id field in utmpx.h" >&5 -printf %s "checking for ut_id field in utmpx.h... " >&6; } - if eval test \${$ossh_varname+y} -then : - printf %s "(cached) " >&6 -else $as_nop + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ut_id field in utmpx.h" >&5 +$as_echo_n "checking for ut_id field in utmpx.h... " >&6; } + if eval \${$ossh_varname+:} false; then : + $as_echo_n "(cached) " >&6 +else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -19327,40 +17737,38 @@ _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - $EGREP "ut_id" >/dev/null 2>&1 -then : + $EGREP "ut_id" >/dev/null 2>&1; then : eval "$ossh_varname=yes" -else $as_nop +else eval "$ossh_varname=no" fi -rm -rf conftest* +rm -f conftest* fi ossh_result=`eval 'echo $'"$ossh_varname"` if test -n "`echo $ossh_varname`"; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ossh_result" >&5 -printf "%s\n" "$ossh_result" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ossh_result" >&5 +$as_echo "$ossh_result" >&6; } if test "x$ossh_result" = "xyes"; then -printf "%s\n" "#define HAVE_ID_IN_UTMPX 1" >>confdefs.h +$as_echo "#define HAVE_ID_IN_UTMPX 1" >>confdefs.h fi else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } fi # look for field 'ut_addr' in header 'utmp.h' ossh_safe=`echo "utmp.h" | sed 'y%./+-%__p_%'` ossh_varname="ossh_cv_$ossh_safe""_has_"ut_addr - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ut_addr field in utmp.h" >&5 -printf %s "checking for ut_addr field in utmp.h... " >&6; } - if eval test \${$ossh_varname+y} -then : - printf %s "(cached) " >&6 -else $as_nop + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ut_addr field in utmp.h" >&5 +$as_echo_n "checking for ut_addr field in utmp.h... " >&6; } + if eval \${$ossh_varname+:} false; then : + $as_echo_n "(cached) " >&6 +else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -19368,40 +17776,38 @@ _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - $EGREP "ut_addr" >/dev/null 2>&1 -then : + $EGREP "ut_addr" >/dev/null 2>&1; then : eval "$ossh_varname=yes" -else $as_nop +else eval "$ossh_varname=no" fi -rm -rf conftest* +rm -f conftest* fi ossh_result=`eval 'echo $'"$ossh_varname"` if test -n "`echo $ossh_varname`"; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ossh_result" >&5 -printf "%s\n" "$ossh_result" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ossh_result" >&5 +$as_echo "$ossh_result" >&6; } if test "x$ossh_result" = "xyes"; then -printf "%s\n" "#define HAVE_ADDR_IN_UTMP 1" >>confdefs.h +$as_echo "#define HAVE_ADDR_IN_UTMP 1" >>confdefs.h fi else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } fi # look for field 'ut_addr' in header 'utmpx.h' ossh_safe=`echo "utmpx.h" | sed 'y%./+-%__p_%'` ossh_varname="ossh_cv_$ossh_safe""_has_"ut_addr - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ut_addr field in utmpx.h" >&5 -printf %s "checking for ut_addr field in utmpx.h... " >&6; } - if eval test \${$ossh_varname+y} -then : - printf %s "(cached) " >&6 -else $as_nop + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ut_addr field in utmpx.h" >&5 +$as_echo_n "checking for ut_addr field in utmpx.h... " >&6; } + if eval \${$ossh_varname+:} false; then : + $as_echo_n "(cached) " >&6 +else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -19409,40 +17815,38 @@ _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - $EGREP "ut_addr" >/dev/null 2>&1 -then : + $EGREP "ut_addr" >/dev/null 2>&1; then : eval "$ossh_varname=yes" -else $as_nop +else eval "$ossh_varname=no" fi -rm -rf conftest* +rm -f conftest* fi ossh_result=`eval 'echo $'"$ossh_varname"` if test -n "`echo $ossh_varname`"; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ossh_result" >&5 -printf "%s\n" "$ossh_result" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ossh_result" >&5 +$as_echo "$ossh_result" >&6; } if test "x$ossh_result" = "xyes"; then -printf "%s\n" "#define HAVE_ADDR_IN_UTMPX 1" >>confdefs.h +$as_echo "#define HAVE_ADDR_IN_UTMPX 1" >>confdefs.h fi else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } fi # look for field 'ut_addr_v6' in header 'utmp.h' ossh_safe=`echo "utmp.h" | sed 'y%./+-%__p_%'` ossh_varname="ossh_cv_$ossh_safe""_has_"ut_addr_v6 - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ut_addr_v6 field in utmp.h" >&5 -printf %s "checking for ut_addr_v6 field in utmp.h... " >&6; } - if eval test \${$ossh_varname+y} -then : - printf %s "(cached) " >&6 -else $as_nop + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ut_addr_v6 field in utmp.h" >&5 +$as_echo_n "checking for ut_addr_v6 field in utmp.h... " >&6; } + if eval \${$ossh_varname+:} false; then : + $as_echo_n "(cached) " >&6 +else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -19450,40 +17854,38 @@ _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - $EGREP "ut_addr_v6" >/dev/null 2>&1 -then : + $EGREP "ut_addr_v6" >/dev/null 2>&1; then : eval "$ossh_varname=yes" -else $as_nop +else eval "$ossh_varname=no" fi -rm -rf conftest* +rm -f conftest* fi ossh_result=`eval 'echo $'"$ossh_varname"` if test -n "`echo $ossh_varname`"; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ossh_result" >&5 -printf "%s\n" "$ossh_result" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ossh_result" >&5 +$as_echo "$ossh_result" >&6; } if test "x$ossh_result" = "xyes"; then -printf "%s\n" "#define HAVE_ADDR_V6_IN_UTMP 1" >>confdefs.h +$as_echo "#define HAVE_ADDR_V6_IN_UTMP 1" >>confdefs.h fi else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } fi # look for field 'ut_addr_v6' in header 'utmpx.h' ossh_safe=`echo "utmpx.h" | sed 'y%./+-%__p_%'` ossh_varname="ossh_cv_$ossh_safe""_has_"ut_addr_v6 - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ut_addr_v6 field in utmpx.h" >&5 -printf %s "checking for ut_addr_v6 field in utmpx.h... " >&6; } - if eval test \${$ossh_varname+y} -then : - printf %s "(cached) " >&6 -else $as_nop + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ut_addr_v6 field in utmpx.h" >&5 +$as_echo_n "checking for ut_addr_v6 field in utmpx.h... " >&6; } + if eval \${$ossh_varname+:} false; then : + $as_echo_n "(cached) " >&6 +else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -19491,40 +17893,38 @@ _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - $EGREP "ut_addr_v6" >/dev/null 2>&1 -then : + $EGREP "ut_addr_v6" >/dev/null 2>&1; then : eval "$ossh_varname=yes" -else $as_nop +else eval "$ossh_varname=no" fi -rm -rf conftest* +rm -f conftest* fi ossh_result=`eval 'echo $'"$ossh_varname"` if test -n "`echo $ossh_varname`"; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ossh_result" >&5 -printf "%s\n" "$ossh_result" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ossh_result" >&5 +$as_echo "$ossh_result" >&6; } if test "x$ossh_result" = "xyes"; then -printf "%s\n" "#define HAVE_ADDR_V6_IN_UTMPX 1" >>confdefs.h +$as_echo "#define HAVE_ADDR_V6_IN_UTMPX 1" >>confdefs.h fi else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } fi # look for field 'ut_exit' in header 'utmp.h' ossh_safe=`echo "utmp.h" | sed 'y%./+-%__p_%'` ossh_varname="ossh_cv_$ossh_safe""_has_"ut_exit - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ut_exit field in utmp.h" >&5 -printf %s "checking for ut_exit field in utmp.h... " >&6; } - if eval test \${$ossh_varname+y} -then : - printf %s "(cached) " >&6 -else $as_nop + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ut_exit field in utmp.h" >&5 +$as_echo_n "checking for ut_exit field in utmp.h... " >&6; } + if eval \${$ossh_varname+:} false; then : + $as_echo_n "(cached) " >&6 +else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -19532,40 +17932,38 @@ _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - $EGREP "ut_exit" >/dev/null 2>&1 -then : + $EGREP "ut_exit" >/dev/null 2>&1; then : eval "$ossh_varname=yes" -else $as_nop +else eval "$ossh_varname=no" fi -rm -rf conftest* +rm -f conftest* fi ossh_result=`eval 'echo $'"$ossh_varname"` if test -n "`echo $ossh_varname`"; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ossh_result" >&5 -printf "%s\n" "$ossh_result" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ossh_result" >&5 +$as_echo "$ossh_result" >&6; } if test "x$ossh_result" = "xyes"; then -printf "%s\n" "#define HAVE_EXIT_IN_UTMP 1" >>confdefs.h +$as_echo "#define HAVE_EXIT_IN_UTMP 1" >>confdefs.h fi else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } fi # look for field 'ut_time' in header 'utmp.h' ossh_safe=`echo "utmp.h" | sed 'y%./+-%__p_%'` ossh_varname="ossh_cv_$ossh_safe""_has_"ut_time - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ut_time field in utmp.h" >&5 -printf %s "checking for ut_time field in utmp.h... " >&6; } - if eval test \${$ossh_varname+y} -then : - printf %s "(cached) " >&6 -else $as_nop + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ut_time field in utmp.h" >&5 +$as_echo_n "checking for ut_time field in utmp.h... " >&6; } + if eval \${$ossh_varname+:} false; then : + $as_echo_n "(cached) " >&6 +else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -19573,40 +17971,38 @@ _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - $EGREP "ut_time" >/dev/null 2>&1 -then : + $EGREP "ut_time" >/dev/null 2>&1; then : eval "$ossh_varname=yes" -else $as_nop +else eval "$ossh_varname=no" fi -rm -rf conftest* +rm -f conftest* fi ossh_result=`eval 'echo $'"$ossh_varname"` if test -n "`echo $ossh_varname`"; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ossh_result" >&5 -printf "%s\n" "$ossh_result" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ossh_result" >&5 +$as_echo "$ossh_result" >&6; } if test "x$ossh_result" = "xyes"; then -printf "%s\n" "#define HAVE_TIME_IN_UTMP 1" >>confdefs.h +$as_echo "#define HAVE_TIME_IN_UTMP 1" >>confdefs.h fi else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } fi # look for field 'ut_time' in header 'utmpx.h' ossh_safe=`echo "utmpx.h" | sed 'y%./+-%__p_%'` ossh_varname="ossh_cv_$ossh_safe""_has_"ut_time - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ut_time field in utmpx.h" >&5 -printf %s "checking for ut_time field in utmpx.h... " >&6; } - if eval test \${$ossh_varname+y} -then : - printf %s "(cached) " >&6 -else $as_nop + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ut_time field in utmpx.h" >&5 +$as_echo_n "checking for ut_time field in utmpx.h... " >&6; } + if eval \${$ossh_varname+:} false; then : + $as_echo_n "(cached) " >&6 +else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -19614,40 +18010,38 @@ _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - $EGREP "ut_time" >/dev/null 2>&1 -then : + $EGREP "ut_time" >/dev/null 2>&1; then : eval "$ossh_varname=yes" -else $as_nop +else eval "$ossh_varname=no" fi -rm -rf conftest* +rm -f conftest* fi ossh_result=`eval 'echo $'"$ossh_varname"` if test -n "`echo $ossh_varname`"; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ossh_result" >&5 -printf "%s\n" "$ossh_result" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ossh_result" >&5 +$as_echo "$ossh_result" >&6; } if test "x$ossh_result" = "xyes"; then -printf "%s\n" "#define HAVE_TIME_IN_UTMPX 1" >>confdefs.h +$as_echo "#define HAVE_TIME_IN_UTMPX 1" >>confdefs.h fi else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } fi # look for field 'ut_tv' in header 'utmpx.h' ossh_safe=`echo "utmpx.h" | sed 'y%./+-%__p_%'` ossh_varname="ossh_cv_$ossh_safe""_has_"ut_tv - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ut_tv field in utmpx.h" >&5 -printf %s "checking for ut_tv field in utmpx.h... " >&6; } - if eval test \${$ossh_varname+y} -then : - printf %s "(cached) " >&6 -else $as_nop + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ut_tv field in utmpx.h" >&5 +$as_echo_n "checking for ut_tv field in utmpx.h... " >&6; } + if eval \${$ossh_varname+:} false; then : + $as_echo_n "(cached) " >&6 +else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -19655,40 +18049,38 @@ _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - $EGREP "ut_tv" >/dev/null 2>&1 -then : + $EGREP "ut_tv" >/dev/null 2>&1; then : eval "$ossh_varname=yes" -else $as_nop +else eval "$ossh_varname=no" fi -rm -rf conftest* +rm -f conftest* fi ossh_result=`eval 'echo $'"$ossh_varname"` if test -n "`echo $ossh_varname`"; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ossh_result" >&5 -printf "%s\n" "$ossh_result" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ossh_result" >&5 +$as_echo "$ossh_result" >&6; } if test "x$ossh_result" = "xyes"; then -printf "%s\n" "#define HAVE_TV_IN_UTMPX 1" >>confdefs.h +$as_echo "#define HAVE_TV_IN_UTMPX 1" >>confdefs.h fi else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } fi # look for field 'ut_ss' in header 'utmpx.h' ossh_safe=`echo "utmpx.h" | sed 'y%./+-%__p_%'` ossh_varname="ossh_cv_$ossh_safe""_has_"ut_ss - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ut_ss field in utmpx.h" >&5 -printf %s "checking for ut_ss field in utmpx.h... " >&6; } - if eval test \${$ossh_varname+y} -then : - printf %s "(cached) " >&6 -else $as_nop + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ut_ss field in utmpx.h" >&5 +$as_echo_n "checking for ut_ss field in utmpx.h... " >&6; } + if eval \${$ossh_varname+:} false; then : + $as_echo_n "(cached) " >&6 +else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -19696,54 +18088,56 @@ _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - $EGREP "ut_ss" >/dev/null 2>&1 -then : + $EGREP "ut_ss" >/dev/null 2>&1; then : eval "$ossh_varname=yes" -else $as_nop +else eval "$ossh_varname=no" fi -rm -rf conftest* +rm -f conftest* fi ossh_result=`eval 'echo $'"$ossh_varname"` if test -n "`echo $ossh_varname`"; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ossh_result" >&5 -printf "%s\n" "$ossh_result" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ossh_result" >&5 +$as_echo "$ossh_result" >&6; } if test "x$ossh_result" = "xyes"; then -printf "%s\n" "#define HAVE_SS_IN_UTMPX 1" >>confdefs.h +$as_echo "#define HAVE_SS_IN_UTMPX 1" >>confdefs.h fi else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } fi ac_fn_c_check_member "$LINENO" "struct stat" "st_blksize" "ac_cv_member_struct_stat_st_blksize" "$ac_includes_default" -if test "x$ac_cv_member_struct_stat_st_blksize" = xyes -then : +if test "x$ac_cv_member_struct_stat_st_blksize" = xyes; then : -printf "%s\n" "#define HAVE_STRUCT_STAT_ST_BLKSIZE 1" >>confdefs.h +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_STAT_ST_BLKSIZE 1 +_ACEOF fi ac_fn_c_check_member "$LINENO" "struct stat" "st_mtim" "ac_cv_member_struct_stat_st_mtim" "$ac_includes_default" -if test "x$ac_cv_member_struct_stat_st_mtim" = xyes -then : +if test "x$ac_cv_member_struct_stat_st_mtim" = xyes; then : -printf "%s\n" "#define HAVE_STRUCT_STAT_ST_MTIM 1" >>confdefs.h +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_STAT_ST_MTIM 1 +_ACEOF fi ac_fn_c_check_member "$LINENO" "struct stat" "st_mtime" "ac_cv_member_struct_stat_st_mtime" "$ac_includes_default" -if test "x$ac_cv_member_struct_stat_st_mtime" = xyes -then : +if test "x$ac_cv_member_struct_stat_st_mtime" = xyes; then : -printf "%s\n" "#define HAVE_STRUCT_STAT_ST_MTIME 1" >>confdefs.h +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_STAT_ST_MTIME 1 +_ACEOF fi @@ -19751,48 +18145,68 @@ ac_fn_c_check_member "$LINENO" "struct passwd" "pw_gecos" "ac_cv_member_struct_passwd_pw_gecos" " #include #include +/* Avoid inappropriate definition from Android unified headers + * to impact detection of structure members. + */ +#undef pw_gecos " -if test "x$ac_cv_member_struct_passwd_pw_gecos" = xyes -then : +if test "x$ac_cv_member_struct_passwd_pw_gecos" = xyes; then : -printf "%s\n" "#define HAVE_STRUCT_PASSWD_PW_GECOS 1" >>confdefs.h +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_PASSWD_PW_GECOS 1 +_ACEOF fi ac_fn_c_check_member "$LINENO" "struct passwd" "pw_class" "ac_cv_member_struct_passwd_pw_class" " #include #include +/* Avoid inappropriate definition from Android unified headers + * to impact detection of structure members. + */ +#undef pw_gecos " -if test "x$ac_cv_member_struct_passwd_pw_class" = xyes -then : +if test "x$ac_cv_member_struct_passwd_pw_class" = xyes; then : -printf "%s\n" "#define HAVE_STRUCT_PASSWD_PW_CLASS 1" >>confdefs.h +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_PASSWD_PW_CLASS 1 +_ACEOF fi ac_fn_c_check_member "$LINENO" "struct passwd" "pw_change" "ac_cv_member_struct_passwd_pw_change" " #include #include +/* Avoid inappropriate definition from Android unified headers + * to impact detection of structure members. + */ +#undef pw_gecos " -if test "x$ac_cv_member_struct_passwd_pw_change" = xyes -then : +if test "x$ac_cv_member_struct_passwd_pw_change" = xyes; then : -printf "%s\n" "#define HAVE_STRUCT_PASSWD_PW_CHANGE 1" >>confdefs.h +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_PASSWD_PW_CHANGE 1 +_ACEOF fi ac_fn_c_check_member "$LINENO" "struct passwd" "pw_expire" "ac_cv_member_struct_passwd_pw_expire" " #include #include +/* Avoid inappropriate definition from Android unified headers + * to impact detection of structure members. + */ +#undef pw_gecos " -if test "x$ac_cv_member_struct_passwd_pw_expire" = xyes -then : +if test "x$ac_cv_member_struct_passwd_pw_expire" = xyes; then : -printf "%s\n" "#define HAVE_STRUCT_PASSWD_PW_EXPIRE 1" >>confdefs.h +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_PASSWD_PW_EXPIRE 1 +_ACEOF fi @@ -19808,12 +18222,11 @@ #include " -if test "x$ac_cv_member_struct___res_state_retrans" = xyes -then : +if test "x$ac_cv_member_struct___res_state_retrans" = xyes; then : -else $as_nop +else -printf "%s\n" "#define __res_state state" >>confdefs.h +$as_echo "#define __res_state state" >>confdefs.h fi @@ -19823,22 +18236,19 @@ #include #include - " -if test "x$ac_cv_member_struct_sockaddr_in_sin_len" = xyes -then : +if test "x$ac_cv_member_struct_sockaddr_in_sin_len" = xyes; then : -printf "%s\n" "#define SOCK_HAS_LEN 1" >>confdefs.h +$as_echo "#define SOCK_HAS_LEN 1" >>confdefs.h fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ss_family field in struct sockaddr_storage" >&5 -printf %s "checking for ss_family field in struct sockaddr_storage... " >&6; } -if test ${ac_cv_have_ss_family_in_struct_ss+y} -then : - printf %s "(cached) " >&6 -else $as_nop +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ss_family field in struct sockaddr_storage" >&5 +$as_echo_n "checking for ss_family field in struct sockaddr_storage... " >&6; } +if ${ac_cv_have_ss_family_in_struct_ss+:} false; then : + $as_echo_n "(cached) " >&6 +else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -19847,36 +18257,34 @@ #include int -main (void) +main () { struct sockaddr_storage s; s.ss_family = 1; ; return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO" -then : +if ac_fn_c_try_compile "$LINENO"; then : ac_cv_have_ss_family_in_struct_ss="yes" -else $as_nop +else ac_cv_have_ss_family_in_struct_ss="no" fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_ss_family_in_struct_ss" >&5 -printf "%s\n" "$ac_cv_have_ss_family_in_struct_ss" >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_ss_family_in_struct_ss" >&5 +$as_echo "$ac_cv_have_ss_family_in_struct_ss" >&6; } if test "x$ac_cv_have_ss_family_in_struct_ss" = "xyes" ; then -printf "%s\n" "#define HAVE_SS_FAMILY_IN_SS 1" >>confdefs.h +$as_echo "#define HAVE_SS_FAMILY_IN_SS 1" >>confdefs.h fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for __ss_family field in struct sockaddr_storage" >&5 -printf %s "checking for __ss_family field in struct sockaddr_storage... " >&6; } -if test ${ac_cv_have___ss_family_in_struct_ss+y} -then : - printf %s "(cached) " >&6 -else $as_nop +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for __ss_family field in struct sockaddr_storage" >&5 +$as_echo_n "checking for __ss_family field in struct sockaddr_storage... " >&6; } +if ${ac_cv_have___ss_family_in_struct_ss+:} false; then : + $as_echo_n "(cached) " >&6 +else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -19885,37 +18293,35 @@ #include int -main (void) +main () { struct sockaddr_storage s; s.__ss_family = 1; ; return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO" -then : +if ac_fn_c_try_compile "$LINENO"; then : ac_cv_have___ss_family_in_struct_ss="yes" -else $as_nop +else ac_cv_have___ss_family_in_struct_ss="no" fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have___ss_family_in_struct_ss" >&5 -printf "%s\n" "$ac_cv_have___ss_family_in_struct_ss" >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have___ss_family_in_struct_ss" >&5 +$as_echo "$ac_cv_have___ss_family_in_struct_ss" >&6; } if test "x$ac_cv_have___ss_family_in_struct_ss" = "xyes" ; then -printf "%s\n" "#define HAVE___SS_FAMILY_IN_SS 1" >>confdefs.h +$as_echo "#define HAVE___SS_FAMILY_IN_SS 1" >>confdefs.h fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for msg_accrights field in struct msghdr" >&5 -printf %s "checking for msg_accrights field in struct msghdr... " >&6; } -if test ${ac_cv_have_accrights_in_msghdr+y} -then : - printf %s "(cached) " >&6 -else $as_nop +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for msg_accrights field in struct msghdr" >&5 +$as_echo_n "checking for msg_accrights field in struct msghdr... " >&6; } +if ${ac_cv_have_accrights_in_msghdr+:} false; then : + $as_echo_n "(cached) " >&6 +else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -19923,44 +18329,41 @@ #include #include #include -#include int -main (void) +main () { #ifdef msg_accrights #error "msg_accrights is a macro" -exit(1); +return 1; #endif struct msghdr m; m.msg_accrights = 0; -exit(0); ; return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO" -then : +if ac_fn_c_try_compile "$LINENO"; then : ac_cv_have_accrights_in_msghdr="yes" -else $as_nop +else ac_cv_have_accrights_in_msghdr="no" fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_accrights_in_msghdr" >&5 -printf "%s\n" "$ac_cv_have_accrights_in_msghdr" >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_accrights_in_msghdr" >&5 +$as_echo "$ac_cv_have_accrights_in_msghdr" >&6; } if test "x$ac_cv_have_accrights_in_msghdr" = "xyes" ; then -printf "%s\n" "#define HAVE_ACCRIGHTS_IN_MSGHDR 1" >>confdefs.h +$as_echo "#define HAVE_ACCRIGHTS_IN_MSGHDR 1" >>confdefs.h fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if struct statvfs.f_fsid is integral type" >&5 -printf %s "checking if struct statvfs.f_fsid is integral type... " >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if struct statvfs.f_fsid is integral type" >&5 +$as_echo_n "checking if struct statvfs.f_fsid is integral type... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -19977,88 +18380,88 @@ #endif int -main (void) +main () { struct statvfs s; s.f_fsid = 0; ; return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO" -then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } -else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } +if ac_fn_c_try_compile "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if fsid_t has member val" >&5 -printf %s "checking if fsid_t has member val... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if fsid_t has member val" >&5 +$as_echo_n "checking if fsid_t has member val... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include +#ifdef HAVE_SYS_STATVFS_H #include +#endif int -main (void) +main () { fsid_t t; t.val[0] = 0; ; return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO" -then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } +if ac_fn_c_try_compile "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } -printf "%s\n" "#define FSID_HAS_VAL 1" >>confdefs.h +$as_echo "#define FSID_HAS_VAL 1" >>confdefs.h -else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if f_fsid has member __val" >&5 -printf %s "checking if f_fsid has member __val... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if f_fsid has member __val" >&5 +$as_echo_n "checking if f_fsid has member __val... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include +#ifdef HAVE_SYS_STATVFS_H #include +#endif int -main (void) +main () { fsid_t t; t.__val[0] = 0; ; return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO" -then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } +if ac_fn_c_try_compile "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } -printf "%s\n" "#define FSID_HAS___VAL 1" >>confdefs.h +$as_echo "#define FSID_HAS___VAL 1" >>confdefs.h -else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for msg_control field in struct msghdr" >&5 -printf %s "checking for msg_control field in struct msghdr... " >&6; } -if test ${ac_cv_have_control_in_msghdr+y} -then : - printf %s "(cached) " >&6 -else $as_nop +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for msg_control field in struct msghdr" >&5 +$as_echo_n "checking for msg_control field in struct msghdr... " >&6; } +if ${ac_cv_have_control_in_msghdr+:} false; then : + $as_echo_n "(cached) " >&6 +else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -20066,159 +18469,149 @@ #include #include #include -#include int -main (void) +main () { #ifdef msg_control #error "msg_control is a macro" -exit(1); +return 1; #endif struct msghdr m; m.msg_control = 0; -exit(0); ; return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO" -then : +if ac_fn_c_try_compile "$LINENO"; then : ac_cv_have_control_in_msghdr="yes" -else $as_nop +else ac_cv_have_control_in_msghdr="no" fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_control_in_msghdr" >&5 -printf "%s\n" "$ac_cv_have_control_in_msghdr" >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_control_in_msghdr" >&5 +$as_echo "$ac_cv_have_control_in_msghdr" >&6; } if test "x$ac_cv_have_control_in_msghdr" = "xyes" ; then -printf "%s\n" "#define HAVE_CONTROL_IN_MSGHDR 1" >>confdefs.h +$as_echo "#define HAVE_CONTROL_IN_MSGHDR 1" >>confdefs.h fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if libc defines __progname" >&5 -printf %s "checking if libc defines __progname... " >&6; } -if test ${ac_cv_libc_defines___progname+y} -then : - printf %s "(cached) " >&6 -else $as_nop +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if libc defines __progname" >&5 +$as_echo_n "checking if libc defines __progname... " >&6; } +if ${ac_cv_libc_defines___progname+:} false; then : + $as_echo_n "(cached) " >&6 +else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int -main (void) +main () { extern char *__progname; printf("%s", __progname); ; return 0; } _ACEOF -if ac_fn_c_try_link "$LINENO" -then : +if ac_fn_c_try_link "$LINENO"; then : ac_cv_libc_defines___progname="yes" -else $as_nop +else ac_cv_libc_defines___progname="no" fi -rm -f core conftest.err conftest.$ac_objext conftest.beam \ +rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_libc_defines___progname" >&5 -printf "%s\n" "$ac_cv_libc_defines___progname" >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_libc_defines___progname" >&5 +$as_echo "$ac_cv_libc_defines___progname" >&6; } if test "x$ac_cv_libc_defines___progname" = "xyes" ; then -printf "%s\n" "#define HAVE___PROGNAME 1" >>confdefs.h +$as_echo "#define HAVE___PROGNAME 1" >>confdefs.h fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CC implements __FUNCTION__" >&5 -printf %s "checking whether $CC implements __FUNCTION__... " >&6; } -if test ${ac_cv_cc_implements___FUNCTION__+y} -then : - printf %s "(cached) " >&6 -else $as_nop +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC implements __FUNCTION__" >&5 +$as_echo_n "checking whether $CC implements __FUNCTION__... " >&6; } +if ${ac_cv_cc_implements___FUNCTION__+:} false; then : + $as_echo_n "(cached) " >&6 +else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int -main (void) +main () { printf("%s", __FUNCTION__); ; return 0; } _ACEOF -if ac_fn_c_try_link "$LINENO" -then : +if ac_fn_c_try_link "$LINENO"; then : ac_cv_cc_implements___FUNCTION__="yes" -else $as_nop +else ac_cv_cc_implements___FUNCTION__="no" fi -rm -f core conftest.err conftest.$ac_objext conftest.beam \ +rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cc_implements___FUNCTION__" >&5 -printf "%s\n" "$ac_cv_cc_implements___FUNCTION__" >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cc_implements___FUNCTION__" >&5 +$as_echo "$ac_cv_cc_implements___FUNCTION__" >&6; } if test "x$ac_cv_cc_implements___FUNCTION__" = "xyes" ; then -printf "%s\n" "#define HAVE___FUNCTION__ 1" >>confdefs.h +$as_echo "#define HAVE___FUNCTION__ 1" >>confdefs.h fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CC implements __func__" >&5 -printf %s "checking whether $CC implements __func__... " >&6; } -if test ${ac_cv_cc_implements___func__+y} -then : - printf %s "(cached) " >&6 -else $as_nop +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC implements __func__" >&5 +$as_echo_n "checking whether $CC implements __func__... " >&6; } +if ${ac_cv_cc_implements___func__+:} false; then : + $as_echo_n "(cached) " >&6 +else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int -main (void) +main () { printf("%s", __func__); ; return 0; } _ACEOF -if ac_fn_c_try_link "$LINENO" -then : +if ac_fn_c_try_link "$LINENO"; then : ac_cv_cc_implements___func__="yes" -else $as_nop +else ac_cv_cc_implements___func__="no" fi -rm -f core conftest.err conftest.$ac_objext conftest.beam \ +rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cc_implements___func__" >&5 -printf "%s\n" "$ac_cv_cc_implements___func__" >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cc_implements___func__" >&5 +$as_echo "$ac_cv_cc_implements___func__" >&6; } if test "x$ac_cv_cc_implements___func__" = "xyes" ; then -printf "%s\n" "#define HAVE___func__ 1" >>confdefs.h +$as_echo "#define HAVE___func__ 1" >>confdefs.h fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether va_copy exists" >&5 -printf %s "checking whether va_copy exists... " >&6; } -if test ${ac_cv_have_va_copy+y} -then : - printf %s "(cached) " >&6 -else $as_nop +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether va_copy exists" >&5 +$as_echo_n "checking whether va_copy exists... " >&6; } +if ${ac_cv_have_va_copy+:} false; then : + $as_echo_n "(cached) " >&6 +else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -20227,38 +18620,36 @@ va_list x,y; int -main (void) +main () { va_copy(x,y); ; return 0; } _ACEOF -if ac_fn_c_try_link "$LINENO" -then : +if ac_fn_c_try_link "$LINENO"; then : ac_cv_have_va_copy="yes" -else $as_nop +else ac_cv_have_va_copy="no" fi -rm -f core conftest.err conftest.$ac_objext conftest.beam \ +rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_va_copy" >&5 -printf "%s\n" "$ac_cv_have_va_copy" >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_va_copy" >&5 +$as_echo "$ac_cv_have_va_copy" >&6; } if test "x$ac_cv_have_va_copy" = "xyes" ; then -printf "%s\n" "#define HAVE_VA_COPY 1" >>confdefs.h +$as_echo "#define HAVE_VA_COPY 1" >>confdefs.h fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether __va_copy exists" >&5 -printf %s "checking whether __va_copy exists... " >&6; } -if test ${ac_cv_have___va_copy+y} -then : - printf %s "(cached) " >&6 -else $as_nop +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether __va_copy exists" >&5 +$as_echo_n "checking whether __va_copy exists... " >&6; } +if ${ac_cv_have___va_copy+:} false; then : + $as_echo_n "(cached) " >&6 +else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -20267,151 +18658,143 @@ va_list x,y; int -main (void) +main () { __va_copy(x,y); ; return 0; } _ACEOF -if ac_fn_c_try_link "$LINENO" -then : +if ac_fn_c_try_link "$LINENO"; then : ac_cv_have___va_copy="yes" -else $as_nop +else ac_cv_have___va_copy="no" fi -rm -f core conftest.err conftest.$ac_objext conftest.beam \ +rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have___va_copy" >&5 -printf "%s\n" "$ac_cv_have___va_copy" >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have___va_copy" >&5 +$as_echo "$ac_cv_have___va_copy" >&6; } if test "x$ac_cv_have___va_copy" = "xyes" ; then -printf "%s\n" "#define HAVE___VA_COPY 1" >>confdefs.h +$as_echo "#define HAVE___VA_COPY 1" >>confdefs.h fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether getopt has optreset support" >&5 -printf %s "checking whether getopt has optreset support... " >&6; } -if test ${ac_cv_have_getopt_optreset+y} -then : - printf %s "(cached) " >&6 -else $as_nop +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether getopt has optreset support" >&5 +$as_echo_n "checking whether getopt has optreset support... " >&6; } +if ${ac_cv_have_getopt_optreset+:} false; then : + $as_echo_n "(cached) " >&6 +else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int -main (void) +main () { extern int optreset; optreset = 0; ; return 0; } _ACEOF -if ac_fn_c_try_link "$LINENO" -then : +if ac_fn_c_try_link "$LINENO"; then : ac_cv_have_getopt_optreset="yes" -else $as_nop +else ac_cv_have_getopt_optreset="no" fi -rm -f core conftest.err conftest.$ac_objext conftest.beam \ +rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_getopt_optreset" >&5 -printf "%s\n" "$ac_cv_have_getopt_optreset" >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_getopt_optreset" >&5 +$as_echo "$ac_cv_have_getopt_optreset" >&6; } if test "x$ac_cv_have_getopt_optreset" = "xyes" ; then -printf "%s\n" "#define HAVE_GETOPT_OPTRESET 1" >>confdefs.h +$as_echo "#define HAVE_GETOPT_OPTRESET 1" >>confdefs.h fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if libc defines sys_errlist" >&5 -printf %s "checking if libc defines sys_errlist... " >&6; } -if test ${ac_cv_libc_defines_sys_errlist+y} -then : - printf %s "(cached) " >&6 -else $as_nop +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if libc defines sys_errlist" >&5 +$as_echo_n "checking if libc defines sys_errlist... " >&6; } +if ${ac_cv_libc_defines_sys_errlist+:} false; then : + $as_echo_n "(cached) " >&6 +else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int -main (void) +main () { extern const char *const sys_errlist[]; printf("%s", sys_errlist[0]); ; return 0; } _ACEOF -if ac_fn_c_try_link "$LINENO" -then : +if ac_fn_c_try_link "$LINENO"; then : ac_cv_libc_defines_sys_errlist="yes" -else $as_nop +else ac_cv_libc_defines_sys_errlist="no" fi -rm -f core conftest.err conftest.$ac_objext conftest.beam \ +rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_libc_defines_sys_errlist" >&5 -printf "%s\n" "$ac_cv_libc_defines_sys_errlist" >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_libc_defines_sys_errlist" >&5 +$as_echo "$ac_cv_libc_defines_sys_errlist" >&6; } if test "x$ac_cv_libc_defines_sys_errlist" = "xyes" ; then -printf "%s\n" "#define HAVE_SYS_ERRLIST 1" >>confdefs.h +$as_echo "#define HAVE_SYS_ERRLIST 1" >>confdefs.h fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if libc defines sys_nerr" >&5 -printf %s "checking if libc defines sys_nerr... " >&6; } -if test ${ac_cv_libc_defines_sys_nerr+y} -then : - printf %s "(cached) " >&6 -else $as_nop +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if libc defines sys_nerr" >&5 +$as_echo_n "checking if libc defines sys_nerr... " >&6; } +if ${ac_cv_libc_defines_sys_nerr+:} false; then : + $as_echo_n "(cached) " >&6 +else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int -main (void) +main () { extern int sys_nerr; printf("%i", sys_nerr); ; return 0; } _ACEOF -if ac_fn_c_try_link "$LINENO" -then : +if ac_fn_c_try_link "$LINENO"; then : ac_cv_libc_defines_sys_nerr="yes" -else $as_nop +else ac_cv_libc_defines_sys_nerr="no" fi -rm -f core conftest.err conftest.$ac_objext conftest.beam \ +rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_libc_defines_sys_nerr" >&5 -printf "%s\n" "$ac_cv_libc_defines_sys_nerr" >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_libc_defines_sys_nerr" >&5 +$as_echo "$ac_cv_libc_defines_sys_nerr" >&6; } if test "x$ac_cv_libc_defines_sys_nerr" = "xyes" ; then -printf "%s\n" "#define HAVE_SYS_NERR 1" >>confdefs.h +$as_echo "#define HAVE_SYS_NERR 1" >>confdefs.h fi # Check libraries needed by DNS fingerprint support -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for library containing getrrsetbyname" >&5 -printf %s "checking for library containing getrrsetbyname... " >&6; } -if test ${ac_cv_search_getrrsetbyname+y} -then : - printf %s "(cached) " >&6 -else $as_nop +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing getrrsetbyname" >&5 +$as_echo_n "checking for library containing getrrsetbyname... " >&6; } +if ${ac_cv_search_getrrsetbyname+:} false; then : + $as_echo_n "(cached) " >&6 +else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -20419,61 +18802,58 @@ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif char getrrsetbyname (); int -main (void) +main () { return getrrsetbyname (); ; return 0; } _ACEOF -for ac_lib in '' resolv -do +for ac_lib in '' resolv; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi - if ac_fn_c_try_link "$LINENO" -then : + if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_getrrsetbyname=$ac_res fi -rm -f core conftest.err conftest.$ac_objext conftest.beam \ +rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext - if test ${ac_cv_search_getrrsetbyname+y} -then : + if ${ac_cv_search_getrrsetbyname+:} false; then : break fi done -if test ${ac_cv_search_getrrsetbyname+y} -then : +if ${ac_cv_search_getrrsetbyname+:} false; then : -else $as_nop +else ac_cv_search_getrrsetbyname=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_getrrsetbyname" >&5 -printf "%s\n" "$ac_cv_search_getrrsetbyname" >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_getrrsetbyname" >&5 +$as_echo "$ac_cv_search_getrrsetbyname" >&6; } ac_res=$ac_cv_search_getrrsetbyname -if test "$ac_res" != no -then : +if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" -printf "%s\n" "#define HAVE_GETRRSETBYNAME 1" >>confdefs.h +$as_echo "#define HAVE_GETRRSETBYNAME 1" >>confdefs.h -else $as_nop +else # Needed by our getrrsetbyname() - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for library containing res_query" >&5 -printf %s "checking for library containing res_query... " >&6; } -if test ${ac_cv_search_res_query+y} -then : - printf %s "(cached) " >&6 -else $as_nop + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing res_query" >&5 +$as_echo_n "checking for library containing res_query... " >&6; } +if ${ac_cv_search_res_query+:} false; then : + $as_echo_n "(cached) " >&6 +else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -20481,58 +18861,55 @@ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif char res_query (); int -main (void) +main () { return res_query (); ; return 0; } _ACEOF -for ac_lib in '' resolv -do +for ac_lib in '' resolv; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi - if ac_fn_c_try_link "$LINENO" -then : + if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_res_query=$ac_res fi -rm -f core conftest.err conftest.$ac_objext conftest.beam \ +rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext - if test ${ac_cv_search_res_query+y} -then : + if ${ac_cv_search_res_query+:} false; then : break fi done -if test ${ac_cv_search_res_query+y} -then : +if ${ac_cv_search_res_query+:} false; then : -else $as_nop +else ac_cv_search_res_query=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_res_query" >&5 -printf "%s\n" "$ac_cv_search_res_query" >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_res_query" >&5 +$as_echo "$ac_cv_search_res_query" >&6; } ac_res=$ac_cv_search_res_query -if test "$ac_res" != no -then : +if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" fi - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for library containing dn_expand" >&5 -printf %s "checking for library containing dn_expand... " >&6; } -if test ${ac_cv_search_dn_expand+y} -then : - printf %s "(cached) " >&6 -else $as_nop + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing dn_expand" >&5 +$as_echo_n "checking for library containing dn_expand... " >&6; } +if ${ac_cv_search_dn_expand+:} false; then : + $as_echo_n "(cached) " >&6 +else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -20540,54 +18917,52 @@ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif char dn_expand (); int -main (void) +main () { return dn_expand (); ; return 0; } _ACEOF -for ac_lib in '' resolv -do +for ac_lib in '' resolv; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi - if ac_fn_c_try_link "$LINENO" -then : + if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_dn_expand=$ac_res fi -rm -f core conftest.err conftest.$ac_objext conftest.beam \ +rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext - if test ${ac_cv_search_dn_expand+y} -then : + if ${ac_cv_search_dn_expand+:} false; then : break fi done -if test ${ac_cv_search_dn_expand+y} -then : +if ${ac_cv_search_dn_expand+:} false; then : -else $as_nop +else ac_cv_search_dn_expand=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_dn_expand" >&5 -printf "%s\n" "$ac_cv_search_dn_expand" >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_dn_expand" >&5 +$as_echo "$ac_cv_search_dn_expand" >&6; } ac_res=$ac_cv_search_dn_expand -if test "$ac_res" != no -then : +if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" fi - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if res_query will link" >&5 -printf %s "checking if res_query will link... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if res_query will link" >&5 +$as_echo_n "checking if res_query will link... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -20598,7 +18973,7 @@ #include int -main (void) +main () { res_query (0, 0, 0, 0, 0); @@ -20607,17 +18982,16 @@ return 0; } _ACEOF -if ac_fn_c_try_link "$LINENO" -then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } -else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } +if ac_fn_c_try_link "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } saved_LIBS="$LIBS" LIBS="$LIBS -lresolv" - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for res_query in -lresolv" >&5 -printf %s "checking for res_query in -lresolv... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for res_query in -lresolv" >&5 +$as_echo_n "checking for res_query in -lresolv... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -20628,7 +19002,7 @@ #include int -main (void) +main () { res_query (0, 0, 0, 0, 0); @@ -20637,61 +19011,62 @@ return 0; } _ACEOF -if ac_fn_c_try_link "$LINENO" -then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } -else $as_nop +if ac_fn_c_try_link "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else LIBS="$saved_LIBS" - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } fi -rm -f core conftest.err conftest.$ac_objext conftest.beam \ +rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi -rm -f core conftest.err conftest.$ac_objext conftest.beam \ +rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext - ac_fn_c_check_func "$LINENO" "_getshort" "ac_cv_func__getshort" -if test "x$ac_cv_func__getshort" = xyes -then : - printf "%s\n" "#define HAVE__GETSHORT 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "_getlong" "ac_cv_func__getlong" -if test "x$ac_cv_func__getlong" = xyes -then : - printf "%s\n" "#define HAVE__GETLONG 1" >>confdefs.h + for ac_func in _getshort _getlong +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF fi +done - ac_fn_check_decl "$LINENO" "_getshort" "ac_cv_have_decl__getshort" "#include + ac_fn_c_check_decl "$LINENO" "_getshort" "ac_cv_have_decl__getshort" "#include #include -" "$ac_c_undeclared_builtin_options" "CFLAGS" -if test "x$ac_cv_have_decl__getshort" = xyes -then : +" +if test "x$ac_cv_have_decl__getshort" = xyes; then : ac_have_decl=1 -else $as_nop +else ac_have_decl=0 fi -printf "%s\n" "#define HAVE_DECL__GETSHORT $ac_have_decl" >>confdefs.h -ac_fn_check_decl "$LINENO" "_getlong" "ac_cv_have_decl__getlong" "#include + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL__GETSHORT $ac_have_decl +_ACEOF +ac_fn_c_check_decl "$LINENO" "_getlong" "ac_cv_have_decl__getlong" "#include #include -" "$ac_c_undeclared_builtin_options" "CFLAGS" -if test "x$ac_cv_have_decl__getlong" = xyes -then : +" +if test "x$ac_cv_have_decl__getlong" = xyes; then : ac_have_decl=1 -else $as_nop +else ac_have_decl=0 fi -printf "%s\n" "#define HAVE_DECL__GETLONG $ac_have_decl" >>confdefs.h + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL__GETLONG $ac_have_decl +_ACEOF ac_fn_c_check_member "$LINENO" "HEADER" "ad" "ac_cv_member_HEADER_ad" "#include " -if test "x$ac_cv_member_HEADER_ad" = xyes -then : +if test "x$ac_cv_member_HEADER_ad" = xyes; then : -printf "%s\n" "#define HAVE_HEADER_AD 1" >>confdefs.h +$as_echo "#define HAVE_HEADER_AD 1" >>confdefs.h fi @@ -20699,8 +19074,8 @@ fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if struct __res_state _res is an extern" >&5 -printf %s "checking if struct __res_state _res is an extern... " >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if struct __res_state _res is an extern" >&5 +$as_echo_n "checking if struct __res_state _res is an extern... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -20714,7 +19089,7 @@ extern struct __res_state _res; int -main (void) +main () { struct __res_state *volatile p = &_res; /* force resolution of _res */ @@ -20724,20 +19099,19 @@ return 0; } _ACEOF -if ac_fn_c_try_link "$LINENO" -then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } +if ac_fn_c_try_link "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } -printf "%s\n" "#define HAVE__RES_EXTERN 1" >>confdefs.h +$as_echo "#define HAVE__RES_EXTERN 1" >>confdefs.h -else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } fi -rm -f core conftest.err conftest.$ac_objext conftest.beam \ +rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext # Check whether user wants SELinux support @@ -20745,28 +19119,26 @@ LIBSELINUX="" # Check whether --with-selinux was given. -if test ${with_selinux+y} -then : +if test "${with_selinux+set}" = set; then : withval=$with_selinux; if test "x$withval" != "xno" ; then save_LIBS="$LIBS" -printf "%s\n" "#define WITH_SELINUX 1" >>confdefs.h +$as_echo "#define WITH_SELINUX 1" >>confdefs.h SELINUX_MSG="yes" - ac_fn_c_check_header_compile "$LINENO" "selinux/selinux.h" "ac_cv_header_selinux_selinux_h" "$ac_includes_default" -if test "x$ac_cv_header_selinux_selinux_h" = xyes -then : + ac_fn_c_check_header_mongrel "$LINENO" "selinux/selinux.h" "ac_cv_header_selinux_selinux_h" "$ac_includes_default" +if test "x$ac_cv_header_selinux_selinux_h" = xyes; then : -else $as_nop +else as_fn_error $? "SELinux support requires selinux.h header" "$LINENO" 5 fi - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for setexeccon in -lselinux" >&5 -printf %s "checking for setexeccon in -lselinux... " >&6; } -if test ${ac_cv_lib_selinux_setexeccon+y} -then : - printf %s "(cached) " >&6 -else $as_nop + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for setexeccon in -lselinux" >&5 +$as_echo_n "checking for setexeccon in -lselinux... " >&6; } +if ${ac_cv_lib_selinux_setexeccon+:} false; then : + $as_echo_n "(cached) " >&6 +else ac_check_lib_save_LIBS=$LIBS LIBS="-lselinux $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -20775,48 +19147,48 @@ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif char setexeccon (); int -main (void) +main () { return setexeccon (); ; return 0; } _ACEOF -if ac_fn_c_try_link "$LINENO" -then : +if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_selinux_setexeccon=yes -else $as_nop +else ac_cv_lib_selinux_setexeccon=no fi -rm -f core conftest.err conftest.$ac_objext conftest.beam \ +rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_selinux_setexeccon" >&5 -printf "%s\n" "$ac_cv_lib_selinux_setexeccon" >&6; } -if test "x$ac_cv_lib_selinux_setexeccon" = xyes -then : +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_selinux_setexeccon" >&5 +$as_echo "$ac_cv_lib_selinux_setexeccon" >&6; } +if test "x$ac_cv_lib_selinux_setexeccon" = xyes; then : LIBSELINUX="-lselinux" LIBS="$LIBS -lselinux" -else $as_nop +else as_fn_error $? "SELinux support requires libselinux library" "$LINENO" 5 fi - ac_fn_c_check_func "$LINENO" "getseuserbyname" "ac_cv_func_getseuserbyname" -if test "x$ac_cv_func_getseuserbyname" = xyes -then : - printf "%s\n" "#define HAVE_GETSEUSERBYNAME 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "get_default_context_with_level" "ac_cv_func_get_default_context_with_level" -if test "x$ac_cv_func_get_default_context_with_level" = xyes -then : - printf "%s\n" "#define HAVE_GET_DEFAULT_CONTEXT_WITH_LEVEL 1" >>confdefs.h + for ac_func in getseuserbyname get_default_context_with_level +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF fi +done LIBS="$save_LIBS $LIBSELINUX" fi @@ -20826,93 +19198,63 @@ # Check whether user wants Kerberos 5 support + + KRB5_MSG="no" # Check whether --with-kerberos5 was given. -if test ${with_kerberos5+y} -then : - withval=$with_kerberos5; if test "x$withval" != "xno" ; then - if test "x$withval" = "xyes" ; then +if test "${with_kerberos5+set}" = set; then : + withval=$with_kerberos5; if test "x$withval" != "xno"; then : + + defect_krb5=config + if test "x$withval" = "xyes"; then : + KRB5ROOT="/usr/local" - else + if test "x$PKGCONFIG" != "xno"; then : + + defect_krb5=package + +fi + +else + KRB5ROOT=${withval} - fi +fi -printf "%s\n" "#define KRB5 1" >>confdefs.h - KRB5_MSG="yes" +$as_echo "#define KRB5 1" >>confdefs.h - use_pkgconfig_for_krb5= - if test "x$PKGCONFIG" != "xno"; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $PKGCONFIG knows about kerberos5" >&5 -printf %s "checking if $PKGCONFIG knows about kerberos5... " >&6; } - if "$PKGCONFIG" krb5; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } - use_pkgconfig_for_krb5=yes - else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } - fi - fi - if test "x$use_pkgconfig_for_krb5" = "xyes"; then - K5CFLAGS=`$PKGCONFIG --cflags krb5` - K5LIBS=`$PKGCONFIG --libs krb5` - CPPFLAGS="$CPPFLAGS $K5CFLAGS" + KRB5_MSG="yes" - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for gssapi support" >&5 -printf %s "checking for gssapi support... " >&6; } - if "$PKGCONFIG" krb5-gssapi; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } + if test "x$defect_krb5" == "xpackage"; then : -printf "%s\n" "#define GSSAPI 1" >>confdefs.h + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $PKGCONFIG knows about kerberos5" >&5 +$as_echo_n "checking if $PKGCONFIG knows about kerberos5... " >&6; } + if "$PKGCONFIG" krb5; then : - GSSCFLAGS="`$PKGCONFIG --cflags krb5-gssapi`" - GSSLIBS="`$PKGCONFIG --libs krb5-gssapi`" - CPPFLAGS="$CPPFLAGS $GSSCFLAGS" - else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } - fi - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether we are using Heimdal" >&5 -printf %s "checking whether we are using Heimdal... " >&6; } - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - #include + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } -int -main (void) -{ - char *tmp = heimdal_version; - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO" -then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } +else -printf "%s\n" "#define HEIMDAL 1" >>confdefs.h + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + defect_krb5=config -else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } +fi fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext - else + if test "x$defect_krb5" == "xconfig"; then : + if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}krb5-config", so it can be a program name with args. set dummy ${ac_tool_prefix}krb5-config; ac_word=$2 -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -printf %s "checking for $ac_word... " >&6; } -if test ${ac_cv_path_KRB5CONF+y} -then : - printf %s "(cached) " >&6 -else $as_nop +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_KRB5CONF+:} false; then : + $as_echo_n "(cached) " >&6 +else case $KRB5CONF in [\\/]* | ?:[\\/]*) ac_cv_path_KRB5CONF="$KRB5CONF" # Let the user override the test with a path. @@ -20923,15 +19265,11 @@ for as_dir in $as_dummy do IFS=$as_save_IFS - case $as_dir in #((( - '') as_dir=./ ;; - */) ;; - *) as_dir=$as_dir/ ;; - esac + test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then - ac_cv_path_KRB5CONF="$as_dir$ac_word$ac_exec_ext" - printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_KRB5CONF="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done @@ -20943,11 +19281,11 @@ fi KRB5CONF=$ac_cv_path_KRB5CONF if test -n "$KRB5CONF"; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $KRB5CONF" >&5 -printf "%s\n" "$KRB5CONF" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $KRB5CONF" >&5 +$as_echo "$KRB5CONF" >&6; } else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } fi @@ -20956,12 +19294,11 @@ ac_pt_KRB5CONF=$KRB5CONF # Extract the first word of "krb5-config", so it can be a program name with args. set dummy krb5-config; ac_word=$2 -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -printf %s "checking for $ac_word... " >&6; } -if test ${ac_cv_path_ac_pt_KRB5CONF+y} -then : - printf %s "(cached) " >&6 -else $as_nop +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_ac_pt_KRB5CONF+:} false; then : + $as_echo_n "(cached) " >&6 +else case $ac_pt_KRB5CONF in [\\/]* | ?:[\\/]*) ac_cv_path_ac_pt_KRB5CONF="$ac_pt_KRB5CONF" # Let the user override the test with a path. @@ -20972,15 +19309,11 @@ for as_dir in $as_dummy do IFS=$as_save_IFS - case $as_dir in #((( - '') as_dir=./ ;; - */) ;; - *) as_dir=$as_dir/ ;; - esac + test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then - ac_cv_path_ac_pt_KRB5CONF="$as_dir$ac_word$ac_exec_ext" - printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_ac_pt_KRB5CONF="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done @@ -20992,20 +19325,20 @@ fi ac_pt_KRB5CONF=$ac_cv_path_ac_pt_KRB5CONF if test -n "$ac_pt_KRB5CONF"; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_pt_KRB5CONF" >&5 -printf "%s\n" "$ac_pt_KRB5CONF" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_KRB5CONF" >&5 +$as_echo "$ac_pt_KRB5CONF" >&6; } else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } fi if test "x$ac_pt_KRB5CONF" = x; then - KRB5CONF="$KRB5ROOT/bin/krb5-config" + KRB5CONF="false" else case $cross_compiling:$ac_tool_warned in yes:) -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac KRB5CONF=$ac_pt_KRB5CONF @@ -21014,172 +19347,180 @@ KRB5CONF="$ac_cv_path_KRB5CONF" fi - if test -x $KRB5CONF ; then - K5CFLAGS="`$KRB5CONF --cflags`" - K5LIBS="`$KRB5CONF --libs`" - CPPFLAGS="$CPPFLAGS $K5CFLAGS" - - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for gssapi support" >&5 -printf %s "checking for gssapi support... " >&6; } - if $KRB5CONF | grep gssapi >/dev/null ; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } + if $KRB5CONF --version > /dev/null 2>&1; then : + + +else + + defect_krb5=direct + +fi + +fi + + if test "x$defect_krb5" = "xpackage"; then : + + K5CFLAGS=`$PKGCONFIG --cflags krb5` + K5LIBS=`$PKGCONFIG --libs krb5` + CPPFLAGS="$CPPFLAGS $K5CFLAGS" -printf "%s\n" "#define GSSAPI 1" >>confdefs.h + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gssapi support" >&5 +$as_echo_n "checking for gssapi support... " >&6; } + if "$PKGCONFIG" krb5-gssapi; then : + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + $as_echo "#define GSSAPI 1" >>confdefs.h + + GSSCFLAGS="`$PKGCONFIG --cflags krb5-gssapi`" + GSSLIBS="`$PKGCONFIG --libs krb5-gssapi`" + if test "x$K5CFLAGS" != "x$GSSCFLAGS"; then : - GSSCFLAGS="`$KRB5CONF --cflags gssapi`" - GSSLIBS="`$KRB5CONF --libs gssapi`" CPPFLAGS="$CPPFLAGS $GSSCFLAGS" - else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } - fi - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether we are using Heimdal" >&5 -printf %s "checking whether we are using Heimdal... " >&6; } - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - #include -int -main (void) -{ - char *tmp = heimdal_version; - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO" -then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } +fi -printf "%s\n" "#define HEIMDAL 1" >>confdefs.h +else -else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext - else - CPPFLAGS="$CPPFLAGS -I${KRB5ROOT}/include" - LDFLAGS="$LDFLAGS -L${KRB5ROOT}/lib" - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether we are using Heimdal" >&5 -printf %s "checking whether we are using Heimdal... " >&6; } - cat confdefs.h - <<_ACEOF >conftest.$ac_ext + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using Heimdal" >&5 +$as_echo_n "checking whether we are using Heimdal... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ - #include + +#include int -main (void) +main () { - char *tmp = heimdal_version; + +char *tmp = heimdal_version; + ; return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO" -then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } - printf "%s\n" "#define HEIMDAL 1" >>confdefs.h +if ac_fn_c_try_compile "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + krb5_implementation=heimdal +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + krb5_implementation=mit - K5LIBS="-lkrb5" - K5LIBS="$K5LIBS -lcom_err -lasn1" - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for net_write in -lroken" >&5 -printf %s "checking for net_write in -lroken... " >&6; } -if test ${ac_cv_lib_roken_net_write+y} -then : - printf %s "(cached) " >&6 -else $as_nop - ac_check_lib_save_LIBS=$LIBS -LIBS="-lroken $LIBS" -cat confdefs.h - <<_ACEOF >conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + + +elif test "x$defect_krb5" == "xconfig"; then : + + K5CFLAGS="`$KRB5CONF --cflags`" + K5LIBS="`$KRB5CONF --libs`" + CPPFLAGS="$CPPFLAGS $K5CFLAGS" + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gssapi support" >&5 +$as_echo_n "checking for gssapi support... " >&6; } + if $KRB5CONF | grep gssapi >/dev/null; then : + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + $as_echo "#define GSSAPI 1" >>confdefs.h + + GSSCFLAGS="`$KRB5CONF --cflags gssapi`" + GSSLIBS="`$KRB5CONF --libs gssapi`" + if test "x$K5CFLAGS" != "x$GSSCFLAGS"; then : + + CPPFLAGS="$CPPFLAGS $GSSCFLAGS" + +fi + +else + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +fi + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using Heimdal" >&5 +$as_echo_n "checking whether we are using Heimdal... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -char net_write (); +#include + int -main (void) +main () { -return net_write (); + +char *tmp = heimdal_version; + ; return 0; } _ACEOF -if ac_fn_c_try_link "$LINENO" -then : - ac_cv_lib_roken_net_write=yes -else $as_nop - ac_cv_lib_roken_net_write=no -fi -rm -f core conftest.err conftest.$ac_objext conftest.beam \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_roken_net_write" >&5 -printf "%s\n" "$ac_cv_lib_roken_net_write" >&6; } -if test "x$ac_cv_lib_roken_net_write" = xyes -then : - K5LIBS="$K5LIBS -lroken" +if ac_fn_c_try_compile "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + krb5_implementation=heimdal +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + krb5_implementation=mit + fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for des_cbc_encrypt in -ldes" >&5 -printf %s "checking for des_cbc_encrypt in -ldes... " >&6; } -if test ${ac_cv_lib_des_des_cbc_encrypt+y} -then : - printf %s "(cached) " >&6 -else $as_nop - ac_check_lib_save_LIBS=$LIBS -LIBS="-ldes $LIBS" -cat confdefs.h - <<_ACEOF >conftest.$ac_ext + +else + + CPPFLAGS="$CPPFLAGS -I${KRB5ROOT}/include" + LDFLAGS="$LDFLAGS -L${KRB5ROOT}/lib" + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using Heimdal" >&5 +$as_echo_n "checking whether we are using Heimdal... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -char des_cbc_encrypt (); +#include + int -main (void) +main () { -return des_cbc_encrypt (); + +char *tmp = heimdal_version; + ; return 0; } _ACEOF -if ac_fn_c_try_link "$LINENO" -then : - ac_cv_lib_des_des_cbc_encrypt=yes -else $as_nop - ac_cv_lib_des_des_cbc_encrypt=no -fi -rm -f core conftest.err conftest.$ac_objext conftest.beam \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_des_des_cbc_encrypt" >&5 -printf "%s\n" "$ac_cv_lib_des_des_cbc_encrypt" >&6; } -if test "x$ac_cv_lib_des_des_cbc_encrypt" = xyes -then : - K5LIBS="$K5LIBS -ldes" +if ac_fn_c_try_compile "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + krb5_implementation=heimdal +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + krb5_implementation=mit + fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + if test "x$krb5_implementation" = "xheimdal"; then : -else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } - K5LIBS="-lkrb5 -lk5crypto -lcom_err" - -fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for library containing dn_expand" >&5 -printf %s "checking for library containing dn_expand... " >&6; } -if test ${ac_cv_search_dn_expand+y} -then : - printf %s "(cached) " >&6 -else $as_nop + K5LIBS="-lkrb5 -lasn1 -lroken -lcom_err" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing dn_expand" >&5 +$as_echo_n "checking for library containing dn_expand... " >&6; } +if ${ac_cv_search_dn_expand+:} false; then : + $as_echo_n "(cached) " >&6 +else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -21187,59 +19528,62 @@ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif char dn_expand (); int -main (void) +main () { return dn_expand (); ; return 0; } _ACEOF -for ac_lib in '' resolv -do +for ac_lib in '' resolv; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi - if ac_fn_c_try_link "$LINENO" -then : + if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_dn_expand=$ac_res fi -rm -f core conftest.err conftest.$ac_objext conftest.beam \ +rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext - if test ${ac_cv_search_dn_expand+y} -then : + if ${ac_cv_search_dn_expand+:} false; then : break fi done -if test ${ac_cv_search_dn_expand+y} -then : +if ${ac_cv_search_dn_expand+:} false; then : -else $as_nop +else ac_cv_search_dn_expand=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_dn_expand" >&5 -printf "%s\n" "$ac_cv_search_dn_expand" >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_dn_expand" >&5 +$as_echo "$ac_cv_search_dn_expand" >&6; } ac_res=$ac_cv_search_dn_expand -if test "$ac_res" != no -then : +if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" fi - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for gss_init_sec_context in -lgssapi_krb5" >&5 -printf %s "checking for gss_init_sec_context in -lgssapi_krb5... " >&6; } -if test ${ac_cv_lib_gssapi_krb5_gss_init_sec_context+y} -then : - printf %s "(cached) " >&6 -else $as_nop +else + + K5LIBS="-lkrb5 -lk5crypto -lcom_err" + +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gss_init_sec_context in -lgssapi_krb5" >&5 +$as_echo_n "checking for gss_init_sec_context in -lgssapi_krb5... " >&6; } +if ${ac_cv_lib_gssapi_krb5_gss_init_sec_context+:} false; then : + $as_echo_n "(cached) " >&6 +else ac_check_lib_save_LIBS=$LIBS LIBS="-lgssapi_krb5 $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -21248,39 +19592,39 @@ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif char gss_init_sec_context (); int -main (void) +main () { return gss_init_sec_context (); ; return 0; } _ACEOF -if ac_fn_c_try_link "$LINENO" -then : +if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_gssapi_krb5_gss_init_sec_context=yes -else $as_nop +else ac_cv_lib_gssapi_krb5_gss_init_sec_context=no fi -rm -f core conftest.err conftest.$ac_objext conftest.beam \ +rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_gssapi_krb5_gss_init_sec_context" >&5 -printf "%s\n" "$ac_cv_lib_gssapi_krb5_gss_init_sec_context" >&6; } -if test "x$ac_cv_lib_gssapi_krb5_gss_init_sec_context" = xyes -then : - printf "%s\n" "#define GSSAPI 1" >>confdefs.h - - GSSLIBS="-lgssapi_krb5" -else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for gss_init_sec_context in -lgssapi" >&5 -printf %s "checking for gss_init_sec_context in -lgssapi... " >&6; } -if test ${ac_cv_lib_gssapi_gss_init_sec_context+y} -then : - printf %s "(cached) " >&6 -else $as_nop +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_gssapi_krb5_gss_init_sec_context" >&5 +$as_echo "$ac_cv_lib_gssapi_krb5_gss_init_sec_context" >&6; } +if test "x$ac_cv_lib_gssapi_krb5_gss_init_sec_context" = xyes; then : + $as_echo "#define GSSAPI 1" >>confdefs.h + + GSSLIBS="-lgssapi_krb5" +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gss_init_sec_context in -lgssapi" >&5 +$as_echo_n "checking for gss_init_sec_context in -lgssapi... " >&6; } +if ${ac_cv_lib_gssapi_gss_init_sec_context+:} false; then : + $as_echo_n "(cached) " >&6 +else ac_check_lib_save_LIBS=$LIBS LIBS="-lgssapi $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -21289,39 +19633,39 @@ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif char gss_init_sec_context (); int -main (void) +main () { return gss_init_sec_context (); ; return 0; } _ACEOF -if ac_fn_c_try_link "$LINENO" -then : +if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_gssapi_gss_init_sec_context=yes -else $as_nop +else ac_cv_lib_gssapi_gss_init_sec_context=no fi -rm -f core conftest.err conftest.$ac_objext conftest.beam \ +rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_gssapi_gss_init_sec_context" >&5 -printf "%s\n" "$ac_cv_lib_gssapi_gss_init_sec_context" >&6; } -if test "x$ac_cv_lib_gssapi_gss_init_sec_context" = xyes -then : - printf "%s\n" "#define GSSAPI 1" >>confdefs.h - - GSSLIBS="-lgssapi" -else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for gss_init_sec_context in -lgss" >&5 -printf %s "checking for gss_init_sec_context in -lgss... " >&6; } -if test ${ac_cv_lib_gss_gss_init_sec_context+y} -then : - printf %s "(cached) " >&6 -else $as_nop +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_gssapi_gss_init_sec_context" >&5 +$as_echo "$ac_cv_lib_gssapi_gss_init_sec_context" >&6; } +if test "x$ac_cv_lib_gssapi_gss_init_sec_context" = xyes; then : + $as_echo "#define GSSAPI 1" >>confdefs.h + + GSSLIBS="-lgssapi" +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gss_init_sec_context in -lgss" >&5 +$as_echo_n "checking for gss_init_sec_context in -lgss... " >&6; } +if ${ac_cv_lib_gss_gss_init_sec_context+:} false; then : + $as_echo_n "(cached) " >&6 +else ac_check_lib_save_LIBS=$LIBS LIBS="-lgss $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -21330,35 +19674,36 @@ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif char gss_init_sec_context (); int -main (void) +main () { return gss_init_sec_context (); ; return 0; } _ACEOF -if ac_fn_c_try_link "$LINENO" -then : +if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_gss_gss_init_sec_context=yes -else $as_nop +else ac_cv_lib_gss_gss_init_sec_context=no fi -rm -f core conftest.err conftest.$ac_objext conftest.beam \ +rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_gss_gss_init_sec_context" >&5 -printf "%s\n" "$ac_cv_lib_gss_gss_init_sec_context" >&6; } -if test "x$ac_cv_lib_gss_gss_init_sec_context" = xyes -then : - printf "%s\n" "#define GSSAPI 1" >>confdefs.h +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_gss_gss_init_sec_context" >&5 +$as_echo "$ac_cv_lib_gss_gss_init_sec_context" >&6; } +if test "x$ac_cv_lib_gss_gss_init_sec_context" = xyes; then : + $as_echo "#define GSSAPI 1" >>confdefs.h - GSSLIBS="-lgss" -else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: Cannot find any suitable gss-api library - build may fail" >&5 -printf "%s\n" "$as_me: WARNING: Cannot find any suitable gss-api library - build may fail" >&2;} + GSSLIBS="-lgss" +else + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Cannot find any suitable gss-api library - build may fail" >&5 +$as_echo "$as_me: WARNING: Cannot find any suitable gss-api library - build may fail" >&2;} fi @@ -21368,155 +19713,118 @@ fi - ac_fn_c_check_header_compile "$LINENO" "gssapi.h" "ac_cv_header_gssapi_h" "$ac_includes_default" -if test "x$ac_cv_header_gssapi_h" = xyes -then : + if test -n "$rpath_opt"; then : -else $as_nop - unset ac_cv_header_gssapi_h - CPPFLAGS="$CPPFLAGS -I${KRB5ROOT}/include/gssapi" - for ac_header in gssapi.h -do : - ac_fn_c_check_header_compile "$LINENO" "gssapi.h" "ac_cv_header_gssapi_h" "$ac_includes_default" -if test "x$ac_cv_header_gssapi_h" = xyes -then : - printf "%s\n" "#define HAVE_GSSAPI_H 1" >>confdefs.h - -else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: Cannot find any suitable gss-api header - build may fail" >&5 -printf "%s\n" "$as_me: WARNING: Cannot find any suitable gss-api header - build may fail" >&2;} + LDFLAGS="$LDFLAGS $rpath_opt$KRB5ROOT/lib" fi + if test ! -z "$blibpath"; then : -done + blibpath="$blibpath:$KRB5ROOT/lib" +fi fi + if test "x$krb5_implementation" = "xheimdal"; then : - oldCPP="$CPPFLAGS" - CPPFLAGS="$CPPFLAGS -I${KRB5ROOT}/include/gssapi" - ac_fn_c_check_header_compile "$LINENO" "gssapi_krb5.h" "ac_cv_header_gssapi_krb5_h" "$ac_includes_default" -if test "x$ac_cv_header_gssapi_krb5_h" = xyes -then : -else $as_nop - CPPFLAGS="$oldCPP" -fi +$as_echo "#define HEIMDAL 1" >>confdefs.h - fi - fi - if test -n "${rpath_opt}" ; then - LDFLAGS="$LDFLAGS ${rpath_opt}${KRB5ROOT}/lib" - fi - if test ! -z "$blibpath" ; then - blibpath="$blibpath:${KRB5ROOT}/lib" - fi +fi - ac_fn_c_check_header_compile "$LINENO" "gssapi.h" "ac_cv_header_gssapi_h" "$ac_includes_default" -if test "x$ac_cv_header_gssapi_h" = xyes -then : - printf "%s\n" "#define HAVE_GSSAPI_H 1" >>confdefs.h + for ac_header in gssapi.h gssapi/gssapi.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF fi -ac_fn_c_check_header_compile "$LINENO" "gssapi/gssapi.h" "ac_cv_header_gssapi_gssapi_h" "$ac_includes_default" -if test "x$ac_cv_header_gssapi_gssapi_h" = xyes -then : - printf "%s\n" "#define HAVE_GSSAPI_GSSAPI_H 1" >>confdefs.h -fi +done - ac_fn_c_check_header_compile "$LINENO" "gssapi_krb5.h" "ac_cv_header_gssapi_krb5_h" "$ac_includes_default" -if test "x$ac_cv_header_gssapi_krb5_h" = xyes -then : - printf "%s\n" "#define HAVE_GSSAPI_KRB5_H 1" >>confdefs.h + for ac_header in gssapi_krb5.h gssapi/gssapi_krb5.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF fi -ac_fn_c_check_header_compile "$LINENO" "gssapi/gssapi_krb5.h" "ac_cv_header_gssapi_gssapi_krb5_h" "$ac_includes_default" -if test "x$ac_cv_header_gssapi_gssapi_krb5_h" = xyes -then : - printf "%s\n" "#define HAVE_GSSAPI_GSSAPI_KRB5_H 1" >>confdefs.h -fi +done - ac_fn_c_check_header_compile "$LINENO" "gssapi_generic.h" "ac_cv_header_gssapi_generic_h" "$ac_includes_default" -if test "x$ac_cv_header_gssapi_generic_h" = xyes -then : - printf "%s\n" "#define HAVE_GSSAPI_GENERIC_H 1" >>confdefs.h + for ac_header in gssapi_generic.h gssapi/gssapi_generic.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF fi -ac_fn_c_check_header_compile "$LINENO" "gssapi/gssapi_generic.h" "ac_cv_header_gssapi_gssapi_generic_h" "$ac_includes_default" -if test "x$ac_cv_header_gssapi_gssapi_generic_h" = xyes -then : - printf "%s\n" "#define HAVE_GSSAPI_GSSAPI_GENERIC_H 1" >>confdefs.h -fi +done - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for library containing k_hasafs" >&5 -printf %s "checking for library containing k_hasafs... " >&6; } -if test ${ac_cv_search_k_hasafs+y} -then : - printf %s "(cached) " >&6 -else $as_nop - ac_func_search_save_LIBS=$LIBS + saved_LIBS="$LIBS" + LIBS="$LIBS $K5LIBS" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for k_hasafs in -lkafs" >&5 +$as_echo_n "checking for k_hasafs in -lkafs... " >&6; } +if ${ac_cv_lib_kafs_k_hasafs+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lkafs $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif char k_hasafs (); int -main (void) +main () { return k_hasafs (); ; return 0; } _ACEOF -for ac_lib in '' kafs -do - if test -z "$ac_lib"; then - ac_res="none required" - else - ac_res=-l$ac_lib - LIBS="-l$ac_lib $ac_func_search_save_LIBS" - fi - if ac_fn_c_try_link "$LINENO" -then : - ac_cv_search_k_hasafs=$ac_res +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_kafs_k_hasafs=yes +else + ac_cv_lib_kafs_k_hasafs=no fi -rm -f core conftest.err conftest.$ac_objext conftest.beam \ - conftest$ac_exeext - if test ${ac_cv_search_k_hasafs+y} -then : - break +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS fi -done -if test ${ac_cv_search_k_hasafs+y} -then : +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_kafs_k_hasafs" >&5 +$as_echo "$ac_cv_lib_kafs_k_hasafs" >&6; } +if test "x$ac_cv_lib_kafs_k_hasafs" = xyes; then : -else $as_nop - ac_cv_search_k_hasafs=no -fi -rm conftest.$ac_ext -LIBS=$ac_func_search_save_LIBS -fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_k_hasafs" >&5 -printf "%s\n" "$ac_cv_search_k_hasafs" >&6; } -ac_res=$ac_cv_search_k_hasafs -if test "$ac_res" != no -then : - test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + # if -L is from "config" => append library :( + K5LIBS="$K5LIBS -lkafs" + +$as_echo "#define USE_AFS 1" >>confdefs.h -printf "%s\n" "#define USE_AFS 1" >>confdefs.h fi + LIBS="$saved_LIBS" - ac_fn_check_decl "$LINENO" "GSS_C_NT_HOSTBASED_SERVICE" "ac_cv_have_decl_GSS_C_NT_HOSTBASED_SERVICE" " + ac_fn_c_check_decl "$LINENO" "GSS_C_NT_HOSTBASED_SERVICE" "ac_cv_have_decl_GSS_C_NT_HOSTBASED_SERVICE" " #ifdef HAVE_GSSAPI_H # include #elif defined(HAVE_GSSAPI_GSSAPI_H) @@ -21529,41 +19837,176 @@ # include #endif -" "$ac_c_undeclared_builtin_options" "CFLAGS" -if test "x$ac_cv_have_decl_GSS_C_NT_HOSTBASED_SERVICE" = xyes -then : +" +if test "x$ac_cv_have_decl_GSS_C_NT_HOSTBASED_SERVICE" = xyes; then : ac_have_decl=1 -else $as_nop +else ac_have_decl=0 fi -printf "%s\n" "#define HAVE_DECL_GSS_C_NT_HOSTBASED_SERVICE $ac_have_decl" >>confdefs.h + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_GSS_C_NT_HOSTBASED_SERVICE $ac_have_decl +_ACEOF saved_LIBS="$LIBS" LIBS="$LIBS $K5LIBS" - ac_fn_c_check_func "$LINENO" "krb5_cc_new_unique" "ac_cv_func_krb5_cc_new_unique" -if test "x$ac_cv_func_krb5_cc_new_unique" = xyes -then : - printf "%s\n" "#define HAVE_KRB5_CC_NEW_UNIQUE 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "krb5_get_error_message" "ac_cv_func_krb5_get_error_message" -if test "x$ac_cv_func_krb5_get_error_message" = xyes -then : - printf "%s\n" "#define HAVE_KRB5_GET_ERROR_MESSAGE 1" >>confdefs.h - -fi -ac_fn_c_check_func "$LINENO" "krb5_free_error_message" "ac_cv_func_krb5_free_error_message" -if test "x$ac_cv_func_krb5_free_error_message" = xyes -then : - printf "%s\n" "#define HAVE_KRB5_FREE_ERROR_MESSAGE 1" >>confdefs.h + for ac_func in krb5_cc_new_unique krb5_get_error_message krb5_free_error_message +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF fi +done LIBS="$saved_LIBS" - fi +fi + +fi + + + +# Postponed OpenSSL checks as ssl library may depend on kerberos. +if $ssh_ocsp; then : + + for ac_func in OCSP_sendreq_bio +do : + ac_fn_c_check_func "$LINENO" "OCSP_sendreq_bio" "ac_cv_func_OCSP_sendreq_bio" +if test "x$ac_cv_func_OCSP_sendreq_bio" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_OCSP_SENDREQ_BIO 1 +_ACEOF + + ac_fn_c_check_header_mongrel "$LINENO" "openssl/ocsp.h" "ac_cv_header_openssl_ocsp_h" "$ac_includes_default" +if test "x$ac_cv_header_openssl_ocsp_h" = xyes; then : + +else + + ssh_ocsp=false + as_fn_error $? "OCSP header not found" "$LINENO" 5 + +fi + + + +else + + ssh_ocsp=false + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Cannot find OCSP functions - OCSP is disabled" >&5 +$as_echo "$as_me: WARNING: Cannot find OCSP functions - OCSP is disabled" >&2;} + +fi +done + + +fi +if $ssh_ocsp; then : + + save_LIBS="$LIBS" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to link programs using OpenSSL OCSP functions" >&5 +$as_echo_n "checking how to link programs using OpenSSL OCSP functions... " >&6; } + if test -n "$K5LIBS"; then : + + SSL_K5LIBS="$K5LIBS" + SSL_K5LIBS_MIT= + SSL_K5LIBS_HEIMDAL= + +else + + SSL_K5LIBS= + SSL_K5LIBS_MIT="-lkrb5 -lk5crypto -lcom_err" + SSL_K5LIBS_HEIMDAL="-lkrb5 -lroken -lasn1 -lcom_err" + +fi + link_SSL=false + # first check is without extra libraries + link_SSL_first_pass=false + for L in "" "$SSL_K5LIBS" "$SSL_K5LIBS_MIT" "$SSL_K5LIBS_HEIMDAL"; do + if $link_SSL_first_pass && test -z "$L"; then : + + continue + +fi + LIBS="-lssl $L $CRYPTO_LIBS $save_LIBS" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + +#include + +int +main () +{ + +#ifdef HAVE_OPENSSL_INIT_CRYPTO + OPENSSL_init_ssl(0, NULL); +#else + SSL_library_init(); +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + link_SSL=: + +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + link_SSL_first_pass=: + $link_SSL && break + done + if $link_SSL; then : + + LIBOCSP="-lssl $L" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIBOCSP" >&5 +$as_echo "$LIBOCSP" >&6; } + +else + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: fail" >&5 +$as_echo "fail" >&6; } + as_fn_error $? "cannot link with OpenSSL ssl library" "$LINENO" 5 + +fi + # check for openssl ssl 1.1+ functions ... + for ac_func in \ + TLS_client_method \ + +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + LIBS="$save_LIBS" + + +$as_echo "#define SSH_OCSP_ENABLED 1" >>confdefs.h + + OCSP_ON='' + OCSP_OFF='#' + OCSP_MSG=yes + +else + + LIBOCSP= + OCSP_ON='#' + OCSP_OFF='' + OCSP_MSG=no + fi @@ -21575,8 +20018,7 @@ PRIVSEP_PATH=/var/empty # Check whether --with-privsep-path was given. -if test ${with_privsep_path+y} -then : +if test "${with_privsep_path+set}" = set; then : withval=$with_privsep_path; if test -n "$withval" && test "x$withval" != "xno" && \ test "x${withval}" != "xyes"; then @@ -21590,15 +20032,14 @@ # Check whether --with-xauth was given. -if test ${with_xauth+y} -then : +if test "${with_xauth+set}" = set; then : withval=$with_xauth; if test -n "$withval" && test "x$withval" != "xno" && \ test "x${withval}" != "xyes"; then xauth_path=$withval fi -else $as_nop +else TestPath="$PATH" TestPath="${TestPath}${PATH_SEPARATOR}/usr/X/bin" @@ -21607,12 +20048,11 @@ TestPath="${TestPath}${PATH_SEPARATOR}/usr/openwin/bin" # Extract the first word of "xauth", so it can be a program name with args. set dummy xauth; ac_word=$2 -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -printf %s "checking for $ac_word... " >&6; } -if test ${ac_cv_path_xauth_path+y} -then : - printf %s "(cached) " >&6 -else $as_nop +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_xauth_path+:} false; then : + $as_echo_n "(cached) " >&6 +else case $xauth_path in [\\/]* | ?:[\\/]*) ac_cv_path_xauth_path="$xauth_path" # Let the user override the test with a path. @@ -21622,15 +20062,11 @@ for as_dir in $TestPath do IFS=$as_save_IFS - case $as_dir in #((( - '') as_dir=./ ;; - */) ;; - *) as_dir=$as_dir/ ;; - esac + test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then - ac_cv_path_xauth_path="$as_dir$ac_word$ac_exec_ext" - printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_xauth_path="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done @@ -21642,11 +20078,11 @@ fi xauth_path=$ac_cv_path_xauth_path if test -n "$xauth_path"; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $xauth_path" >&5 -printf "%s\n" "$xauth_path" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $xauth_path" >&5 +$as_echo "$xauth_path" >&6; } else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } fi @@ -21660,8 +20096,7 @@ STRIP_OPT=-s # Check whether --enable-strip was given. -if test ${enable_strip+y} -then : +if test "${enable_strip+set}" = set; then : enableval=$enable_strip; if test "x$enableval" = "xno" ; then STRIP_OPT= @@ -21677,7 +20112,9 @@ else -printf "%s\n" "#define XAUTH_PATH \"$xauth_path\"" >>confdefs.h +cat >>confdefs.h <<_ACEOF +#define XAUTH_PATH "$xauth_path" +_ACEOF XAUTH_PATH=$xauth_path @@ -21686,38 +20123,38 @@ # Check for mail directory # Check whether --with-maildir was given. -if test ${with_maildir+y} -then : +if test "${with_maildir+set}" = set; then : withval=$with_maildir; if test "X$withval" != X && test "x$withval" != xno && \ test "x${withval}" != xyes; then -printf "%s\n" "#define MAIL_DIRECTORY \"$withval\"" >>confdefs.h +cat >>confdefs.h <<_ACEOF +#define MAIL_DIRECTORY "$withval" +_ACEOF fi -else $as_nop +else if test "X$maildir" != "X"; then - printf "%s\n" "#define MAIL_DIRECTORY \"$maildir\"" >>confdefs.h + cat >>confdefs.h <<_ACEOF +#define MAIL_DIRECTORY "$maildir" +_ACEOF else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking Discovering system mail directory" >&5 -printf %s "checking Discovering system mail directory... " >&6; } - if test "$cross_compiling" = yes -then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking Discovering system mail directory" >&5 +$as_echo_n "checking Discovering system mail directory... " >&6; } + if test "$cross_compiling" = yes; then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: use --with-maildir=/path/to/mail" >&5 -printf "%s\n" "$as_me: WARNING: cross compiling: use --with-maildir=/path/to/mail" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: use --with-maildir=/path/to/mail" >&5 +$as_echo "$as_me: WARNING: cross compiling: use --with-maildir=/path/to/mail" >&2;} -else $as_nop +else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include -#include -#include #ifdef HAVE_PATHS_H #include #endif @@ -21727,7 +20164,7 @@ #define DATA "conftest.maildir" int -main (void) +main () { FILE *fd; @@ -21735,51 +20172,52 @@ fd = fopen(DATA,"w"); if(fd == NULL) - exit(1); + return 1; #if defined (_PATH_MAILDIR) if ((rc = fprintf(fd ,"_PATH_MAILDIR:%s\n", _PATH_MAILDIR)) <0) - exit(1); + return 1; #elif defined (MAILDIR) if ((rc = fprintf(fd ,"MAILDIR:%s\n", MAILDIR)) <0) - exit(1); + return 1; #elif defined (_PATH_MAIL) if ((rc = fprintf(fd ,"_PATH_MAIL:%s\n", _PATH_MAIL)) <0) - exit(1); + return 1; #else - exit (2); + return 2; #endif - exit(0); - ; return 0; } _ACEOF -if ac_fn_c_try_run "$LINENO" -then : +if ac_fn_c_try_run "$LINENO"; then : maildir_what=`awk -F: '{print $1}' conftest.maildir` maildir=`awk -F: '{print $2}' conftest.maildir \ | sed 's|/$||'` - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: Using: $maildir from $maildir_what" >&5 -printf "%s\n" "Using: $maildir from $maildir_what" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: Using: $maildir from $maildir_what" >&5 +$as_echo "Using: $maildir from $maildir_what" >&6; } if test "x$maildir_what" != "x_PATH_MAILDIR"; then - printf "%s\n" "#define MAIL_DIRECTORY \"$maildir\"" >>confdefs.h + cat >>confdefs.h <<_ACEOF +#define MAIL_DIRECTORY "$maildir" +_ACEOF fi -else $as_nop +else if test "X$ac_status" = "X2";then # our test program didn't find it. Default to /var/spool/mail - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: Using: default value of /var/spool/mail" >&5 -printf "%s\n" "Using: default value of /var/spool/mail" >&6; } - printf "%s\n" "#define MAIL_DIRECTORY \"/var/spool/mail\"" >>confdefs.h + { $as_echo "$as_me:${as_lineno-$LINENO}: result: Using: default value of /var/spool/mail" >&5 +$as_echo "Using: default value of /var/spool/mail" >&6; } + cat >>confdefs.h <<_ACEOF +#define MAIL_DIRECTORY "/var/spool/mail" +_ACEOF else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: *** not found ***" >&5 -printf "%s\n" "*** not found ***" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: *** not found ***" >&5 +$as_echo "*** not found ***" >&6; } fi fi @@ -21793,20 +20231,26 @@ fi # maildir -if test ! -z "$cross_compiling" && test "x$cross_compiling" = "xyes"; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: Disabling /dev/ptmx test" >&5 -printf "%s\n" "$as_me: WARNING: cross compiling: Disabling /dev/ptmx test" >&2;} - disable_ptmx_check=yes -fi -if test -z "$no_dev_ptmx" ; then - if test "x$disable_ptmx_check" != "xyes" ; then - as_ac_File=`printf "%s\n" "ac_cv_file_"/dev/ptmx"" | $as_tr_sh` -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for \"/dev/ptmx\"" >&5 -printf %s "checking for \"/dev/ptmx\"... " >&6; } -if eval test \${$as_ac_File+y} -then : - printf %s "(cached) " >&6 -else $as_nop +if test "${ac_cv_file__dev_ptmx+set}" != set && test "x$cross_compiling" = "xyes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: Disabling /dev/ptmx test" >&5 +$as_echo "$as_me: WARNING: cross compiling: Disabling /dev/ptmx test" >&2;} + ac_cv_file__dev_ptmx=cross +else + if test "${ac_cv_file__dev_ptmx+set}" = set ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for \"/dev/ptmx\"" >&5 +$as_echo_n "checking for \"/dev/ptmx\"... " >&6; } +if ${ac_cv_file__dev_ptmx+:} false; then : + $as_echo_n "(cached) " >&6 +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_file__dev_ptmx" >&5 +$as_echo "$ac_cv_file__dev_ptmx" >&6; } + else + as_ac_File=`$as_echo "ac_cv_file_"/dev/ptmx"" | $as_tr_sh` +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for \"/dev/ptmx\"" >&5 +$as_echo_n "checking for \"/dev/ptmx\"... " >&6; } +if eval \${$as_ac_File+:} false; then : + $as_echo_n "(cached) " >&6 +else test "$cross_compiling" = yes && as_fn_error $? "cannot check for file existence when cross compiling" "$LINENO" 5 if test -r ""/dev/ptmx""; then @@ -21816,30 +20260,29 @@ fi fi eval ac_res=\$$as_ac_File - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 -printf "%s\n" "$ac_res" >&6; } -if eval test \"x\$"$as_ac_File"\" = x"yes" -then : - - -printf "%s\n" "#define HAVE_DEV_PTMX 1" >>confdefs.h - - have_dev_ptmx=1 - + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +if eval test \"x\$"$as_ac_File"\" = x"yes"; then : fi fi fi +if test "x$ac_cv_file__dev_ptmx" = xyes ; then + +cat >>confdefs.h <<_ACEOF +#define HAVE_DEV_PTMX 1 +_ACEOF + +fi if test ! -z "$cross_compiling" && test "x$cross_compiling" != "xyes"; then - as_ac_File=`printf "%s\n" "ac_cv_file_"/dev/ptc"" | $as_tr_sh` -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for \"/dev/ptc\"" >&5 -printf %s "checking for \"/dev/ptc\"... " >&6; } -if eval test \${$as_ac_File+y} -then : - printf %s "(cached) " >&6 -else $as_nop + as_ac_File=`$as_echo "ac_cv_file_"/dev/ptc"" | $as_tr_sh` +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for \"/dev/ptc\"" >&5 +$as_echo_n "checking for \"/dev/ptc\"... " >&6; } +if eval \${$as_ac_File+:} false; then : + $as_echo_n "(cached) " >&6 +else test "$cross_compiling" = yes && as_fn_error $? "cannot check for file existence when cross compiling" "$LINENO" 5 if test -r ""/dev/ptc""; then @@ -21849,13 +20292,14 @@ fi fi eval ac_res=\$$as_ac_File - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 -printf "%s\n" "$ac_res" >&6; } -if eval test \"x\$"$as_ac_File"\" = x"yes" -then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +if eval test \"x\$"$as_ac_File"\" = x"yes"; then : -printf "%s\n" "#define HAVE_DEV_PTS_AND_PTC 1" >>confdefs.h +cat >>confdefs.h <<_ACEOF +#define HAVE_DEV_PTS_AND_PTC 1 +_ACEOF have_dev_ptc=1 @@ -21863,15 +20307,14 @@ fi else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: Disabling /dev/ptc test" >&5 -printf "%s\n" "$as_me: WARNING: cross compiling: Disabling /dev/ptc test" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: Disabling /dev/ptc test" >&5 +$as_echo "$as_me: WARNING: cross compiling: Disabling /dev/ptc test" >&2;} fi # Options from here on. Some of these are preset by platform above # Check whether --with-mantype was given. -if test ${with_mantype+y} -then : +if test "${with_mantype+set}" = set; then : withval=$with_mantype; case "$withval" in man|cat|doc) @@ -21904,14 +20347,30 @@ fi +# Check whether to enable MD5 passwords +MD5_MSG="no" + +# Check whether --with-md5-passwords was given. +if test "${with_md5_passwords+set}" = set; then : + withval=$with_md5_passwords; + if test "x$withval" != "xno" ; then + +$as_echo "#define HAVE_MD5_PASSWORDS 1" >>confdefs.h + + MD5_MSG="yes" + fi + + +fi + + # Whether to disable shadow password support # Check whether --with-shadow was given. -if test ${with_shadow+y} -then : +if test "${with_shadow+set}" = set; then : withval=$with_shadow; if test "x$withval" = "xno" ; then - printf "%s\n" "#define DISABLE_SHADOW 1" >>confdefs.h + $as_echo "#define DISABLE_SHADOW 1" >>confdefs.h disable_shadow=yes fi @@ -21921,8 +20380,8 @@ if test -z "$disable_shadow" ; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if the systems has expire shadow information" >&5 -printf %s "checking if the systems has expire shadow information... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if the systems has expire shadow information" >&5 +$as_echo_n "checking if the systems has expire shadow information... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -21931,28 +20390,27 @@ struct spwd sp; int -main (void) +main () { sp.sp_expire = sp.sp_lstchg = sp.sp_inact = 0; ; return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO" -then : +if ac_fn_c_try_compile "$LINENO"; then : sp_expire_available=yes fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext if test "x$sp_expire_available" = "xyes" ; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } -printf "%s\n" "#define HAS_SHADOW_EXPIRE 1" >>confdefs.h +$as_echo "#define HAS_SHADOW_EXPIRE 1" >>confdefs.h else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } fi fi @@ -21960,17 +20418,16 @@ if test ! -z "$IPADDR_IN_DISPLAY" ; then DISPLAY_HACK_MSG="yes" -printf "%s\n" "#define IPADDR_IN_DISPLAY 1" >>confdefs.h +$as_echo "#define IPADDR_IN_DISPLAY 1" >>confdefs.h else DISPLAY_HACK_MSG="no" # Check whether --with-ipaddr-display was given. -if test ${with_ipaddr_display+y} -then : +if test "${with_ipaddr_display+set}" = set; then : withval=$with_ipaddr_display; if test "x$withval" != "xno" ; then - printf "%s\n" "#define IPADDR_IN_DISPLAY 1" >>confdefs.h + $as_echo "#define IPADDR_IN_DISPLAY 1" >>confdefs.h DISPLAY_HACK_MSG="yes" fi @@ -21982,20 +20439,19 @@ # check for /etc/default/login and use it if present. # Check whether --enable-etc-default-login was given. -if test ${enable_etc_default_login+y} -then : +if test "${enable_etc_default_login+set}" = set; then : enableval=$enable_etc_default_login; if test "x$enableval" = "xno"; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: /etc/default/login handling disabled" >&5 -printf "%s\n" "$as_me: /etc/default/login handling disabled" >&6;} + { $as_echo "$as_me:${as_lineno-$LINENO}: /etc/default/login handling disabled" >&5 +$as_echo "$as_me: /etc/default/login handling disabled" >&6;} etc_default_login=no else etc_default_login=yes fi -else $as_nop +else if test ! -z "$cross_compiling" && test "x$cross_compiling" = "xyes"; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: not checking /etc/default/login" >&5 -printf "%s\n" "$as_me: WARNING: cross compiling: not checking /etc/default/login" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: not checking /etc/default/login" >&5 +$as_echo "$as_me: WARNING: cross compiling: not checking /etc/default/login" >&2;} etc_default_login=no else etc_default_login=yes @@ -22005,13 +20461,12 @@ if test "x$etc_default_login" != "xno"; then - as_ac_File=`printf "%s\n" "ac_cv_file_"/etc/default/login"" | $as_tr_sh` -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for \"/etc/default/login\"" >&5 -printf %s "checking for \"/etc/default/login\"... " >&6; } -if eval test \${$as_ac_File+y} -then : - printf %s "(cached) " >&6 -else $as_nop + as_ac_File=`$as_echo "ac_cv_file_"/etc/default/login"" | $as_tr_sh` +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for \"/etc/default/login\"" >&5 +$as_echo_n "checking for \"/etc/default/login\"... " >&6; } +if eval \${$as_ac_File+:} false; then : + $as_echo_n "(cached) " >&6 +else test "$cross_compiling" = yes && as_fn_error $? "cannot check for file existence when cross compiling" "$LINENO" 5 if test -r ""/etc/default/login""; then @@ -22021,16 +20476,15 @@ fi fi eval ac_res=\$$as_ac_File - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 -printf "%s\n" "$ac_res" >&6; } -if eval test \"x\$"$as_ac_File"\" = x"yes" -then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +if eval test \"x\$"$as_ac_File"\" = x"yes"; then : external_path_file=/etc/default/login fi if test "x$external_path_file" = "x/etc/default/login"; then -printf "%s\n" "#define HAVE_ETC_DEFAULT_LOGIN 1" >>confdefs.h +$as_echo "#define HAVE_ETC_DEFAULT_LOGIN 1" >>confdefs.h fi fi @@ -22044,22 +20498,21 @@ SERVER_PATH_MSG="(default)" # Check whether --with-default-path was given. -if test ${with_default_path+y} -then : +if test "${with_default_path+set}" = set; then : withval=$with_default_path; if test "x$external_path_file" = "x/etc/login.conf" ; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: --with-default-path=PATH has no effect on this system. Edit /etc/login.conf instead." >&5 -printf "%s\n" "$as_me: WARNING: +$as_echo "$as_me: WARNING: --with-default-path=PATH has no effect on this system. Edit /etc/login.conf instead." >&2;} elif test "x$withval" != "xno" ; then if test ! -z "$external_path_file" ; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: --with-default-path=PATH will only be used if PATH is not defined in $external_path_file ." >&5 -printf "%s\n" "$as_me: WARNING: +$as_echo "$as_me: WARNING: --with-default-path=PATH will only be used if PATH is not defined in $external_path_file ." >&2;} fi @@ -22067,30 +20520,28 @@ SERVER_PATH_MSG="$withval" fi -else $as_nop +else if test "x$external_path_file" = "x/etc/login.conf" ; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: Make sure the path to scp is in /etc/login.conf" >&5 -printf "%s\n" "$as_me: WARNING: Make sure the path to scp is in /etc/login.conf" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Make sure the path to scp is in /etc/login.conf" >&5 +$as_echo "$as_me: WARNING: Make sure the path to scp is in /etc/login.conf" >&2;} else if test ! -z "$external_path_file" ; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: If PATH is defined in $external_path_file, ensure the path to scp is included, otherwise scp will not work." >&5 -printf "%s\n" "$as_me: WARNING: +$as_echo "$as_me: WARNING: If PATH is defined in $external_path_file, ensure the path to scp is included, otherwise scp will not work." >&2;} fi - if test "$cross_compiling" = yes -then : + if test "$cross_compiling" = yes; then : user_path="/usr/bin:/bin:/usr/sbin:/sbin" -else $as_nop +else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* find out what STDPATH is */ #include -#include #ifdef HAVE_PATHS_H # include #endif @@ -22107,7 +20558,7 @@ #define DATA "conftest.stdpath" int -main (void) +main () { FILE *fd; @@ -22115,21 +20566,18 @@ fd = fopen(DATA,"w"); if(fd == NULL) - exit(1); + return 1; if ((rc = fprintf(fd,"%s", _PATH_STDPATH)) < 0) - exit(1); - - exit(0); + return 1; ; return 0; } _ACEOF -if ac_fn_c_try_run "$LINENO" -then : +if ac_fn_c_try_run "$LINENO"; then : user_path=`cat conftest.stdpath` -else $as_nop +else user_path="/usr/bin:/bin:/usr/sbin:/sbin" fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ @@ -22151,9 +20599,9 @@ if test $? -ne 0 ; then echo $user_path | grep "^$t_bindir" > /dev/null 2>&1 if test $? -ne 0 ; then - user_path=$user_path:$t_bindir - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: Adding $t_bindir to USER_PATH so scp will work" >&5 -printf "%s\n" "Adding $t_bindir to USER_PATH so scp will work" >&6; } + user_path=$t_bindir:$user_path + { $as_echo "$as_me:${as_lineno-$LINENO}: result: Prepend $t_bindir to USER_PATH so scp will work" >&5 +$as_echo "Prepend $t_bindir to USER_PATH so scp will work" >&6; } fi fi fi @@ -22162,7 +20610,9 @@ if test "x$external_path_file" != "x/etc/login.conf" ; then -printf "%s\n" "#define USER_PATH \"$user_path\"" >>confdefs.h +cat >>confdefs.h <<_ACEOF +#define USER_PATH "$user_path" +_ACEOF fi @@ -22170,13 +20620,14 @@ # Set superuser path separately to user path # Check whether --with-superuser-path was given. -if test ${with_superuser_path+y} -then : +if test "${with_superuser_path+set}" = set; then : withval=$with_superuser_path; if test -n "$withval" && test "x$withval" != "xno" && \ test "x${withval}" != "xyes"; then -printf "%s\n" "#define SUPERUSER_PATH \"$withval\"" >>confdefs.h +cat >>confdefs.h <<_ACEOF +#define SUPERUSER_PATH "$withval" +_ACEOF superuser_path=$withval fi @@ -22186,37 +20637,36 @@ -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if we need to convert IPv4 in IPv6-mapped addresses" >&5 -printf %s "checking if we need to convert IPv4 in IPv6-mapped addresses... " >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if we need to convert IPv4 in IPv6-mapped addresses" >&5 +$as_echo_n "checking if we need to convert IPv4 in IPv6-mapped addresses... " >&6; } IPV4_IN6_HACK_MSG="no" # Check whether --with-4in6 was given. -if test ${with_4in6+y} -then : +if test "${with_4in6+set}" = set; then : withval=$with_4in6; if test "x$withval" != "xno" ; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } -printf "%s\n" "#define IPV4_IN_IPV6 1" >>confdefs.h +$as_echo "#define IPV4_IN_IPV6 1" >>confdefs.h IPV4_IN6_HACK_MSG="yes" else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } fi -else $as_nop +else if test "x$inet6_default_4in6" = "xyes"; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes (default)" >&5 -printf "%s\n" "yes (default)" >&6; } - printf "%s\n" "#define IPV4_IN_IPV6 1" >>confdefs.h + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes (default)" >&5 +$as_echo "yes (default)" >&6; } + $as_echo "#define IPV4_IN_IPV6 1" >>confdefs.h IPV4_IN6_HACK_MSG="yes" else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no (default)" >&5 -printf "%s\n" "no (default)" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no (default)" >&5 +$as_echo "no (default)" >&6; } fi @@ -22227,12 +20677,11 @@ BSD_AUTH_MSG=no # Check whether --with-bsd-auth was given. -if test ${with_bsd_auth+y} -then : +if test "${with_bsd_auth+set}" = set; then : withval=$with_bsd_auth; if test "x$withval" != "xno" ; then -printf "%s\n" "#define BSD_AUTH 1" >>confdefs.h +$as_echo "#define BSD_AUTH 1" >>confdefs.h BSD_AUTH_MSG=yes fi @@ -22241,6 +20690,326 @@ fi + +# enable LDAP queries +LDAP_MSG=no + + +ac_ldap=none +# Check whether --enable-ldap was given. +if test "${enable_ldap+set}" = set; then : + enableval=$enable_ldap; ac_ldap=$enableval + +fi + + +if test "x$ac_ldap" = xyes; then + ac_ldap_prefix="" + +# Check whether --with-ldap-prefix was given. +if test "${with_ldap_prefix+set}" = set; then : + withval=$with_ldap_prefix; ac_ldap_prefix=$withval + +fi + + + +# Check whether --with-ldap-bindir was given. +if test "${with_ldap_bindir+set}" = set; then : + withval=$with_ldap_bindir; LDAP_BINDIR=$withval +else + + if test "x$ac_ldap_prefix" != "x"; then + LDAP_BINDIR="$ac_ldap_prefix/bin" + fi + + +fi + + + + +# Check whether --with-ldap-libexecdir was given. +if test "${with_ldap_libexecdir+set}" = set; then : + withval=$with_ldap_libexecdir; LDAP_LIBEXECDIR=$withval +else + + if test "x$ac_ldap_prefix" = "x"; then + LDAP_LIBEXECDIR="/usr/libexec" + else + LDAP_LIBEXECDIR="$ac_ldap_prefix/libexec" + fi + + +fi + + + + +# Check whether --with-ldap-sysconfdir was given. +if test "${with_ldap_sysconfdir+set}" = set; then : + withval=$with_ldap_sysconfdir; LDAP_SYSCONFDIR=$withval +else + LDAP_SYSCONFDIR="$ac_ldap_prefix/etc/openldap" + +fi + + + + + +# Check whether --with-ldap-libdir was given. +if test "${with_ldap_libdir+set}" = set; then : + withval=$with_ldap_libdir; LDAP_LDFLAGS="-L$withval" +else + + if test "x$ac_ldap_prefix" != "x"; then + LDAP_LDFLAGS="-L$ac_ldap_prefix/lib" + else + LDAP_LDFLAGS="" + fi + + +fi + + + + +# Check whether --with-ldap-includedir was given. +if test "${with_ldap_includedir+set}" = set; then : + withval=$with_ldap_includedir; LDAP_CPPFLAGS="-I$withval" +else + + if test "x$ac_ldap_prefix" != "x"; then + LDAP_CPPFLAGS="-I$ac_ldap_prefix/include" + else + LDAP_CPPFLAGS="" + fi + + +fi + + + + + ac_save_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS $LDAP_CPPFLAGS" + for ac_header in lber.h ldap.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +else + + as_fn_error $? "cannot found LDAP headers" "$LINENO" 5 + + +fi + +done + + CPPFLAGS="$ac_save_CPPFLAGS" + + ac_ldap_libs="" + +# Check whether --with-ldap-libs was given. +if test "${with_ldap_libs+set}" = set; then : + withval=$with_ldap_libs; ac_ldap_libs="$withval" + +fi + + +### Try to link with LDAP libs + ac_save_LDFLAGS="$LDFLAGS" + ac_save_LIBS="$LIBS" + + LDFLAGS="$LDAP_LDFLAGS $LDFLAGS" + ac_LDAP_LINK="" + if test "x$ac_ldap_libs" != "x"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking to link with specified LDAP libs" >&5 +$as_echo_n "checking to link with specified LDAP libs... " >&6; } + + LDAP_LIBS="$ac_ldap_libs" + LIBS="$LDAP_LIBS $ac_save_LIBS" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char ldap_init (); +int +main () +{ +return ldap_init (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_LDAP_LINK="yes" + +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + if test "x$ac_LDAP_LINK" != "xyes"; then + as_fn_error $? "cannot link with specified LDAP libs" "$LINENO" 5 + fi + else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to link LDAP libs" >&5 +$as_echo_n "checking how to link LDAP libs... " >&6; } + + LDAP_LIBS="-lldap" + for L in lber ssl crypto; do + LDAP_LIBS="$LDAP_LIBS -l$L" + LIBS="$LDAP_LIBS $ac_save_LIBS" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char ldap_init (); +int +main () +{ +return ldap_init (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_LDAP_LINK="yes" + +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + if test "x$ac_LDAP_LINK" = "xyes"; then + break + fi + done + if test "x$ac_LDAP_LINK" != "xyes"; then + as_fn_error $? "cannot link with default LDAP libs" "$LINENO" 5 + fi + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: done" >&5 +$as_echo "done" >&6; } + LIBS="$ac_save_LIBS" + LDFLAGS="$ac_save_LDFLAGS" + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: LDAP is disabled" >&5 +$as_echo "$as_me: LDAP is disabled" >&6;} +fi + +if test "x$ac_ldap" = "xyes"; then + +cat >>confdefs.h <<_ACEOF +#define LDAP_ENABLED 1 +_ACEOF + + LDAP_ON='' + LDAP_OFF='#' +else + LDAP_ON='#' + LDAP_OFF='' +fi + + + +if test "x$LDAP_ON" = "x"; then : + + LDAP_MSG=yes + for ac_prog in openldapadd ldapadd +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_LDAPADD+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$LDAPADD"; then + ac_cv_prog_LDAPADD="$LDAPADD" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +as_dummy="PATH="$LDAP_BINDIR:$PATH"" +for as_dir in $as_dummy +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_LDAPADD="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +LDAPADD=$ac_cv_prog_LDAPADD +if test -n "$LDAPADD"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LDAPADD" >&5 +$as_echo "$LDAPADD" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$LDAPADD" && break +done +test -n "$LDAPADD" || LDAPADD="false" + + +fi + + +if test "x$ac_ldap" = "xyes"; then + ac_save_CPPFLAGS="$CPPFLAGS" + ac_save_LDFLAGS="$LDFLAGS" + ac_save_LIBS="$LIBS" + CPPFLAGS="$CPPFLAGS $LDAP_CPPFLAGS" + LDFLAGS="$LDFLAGS $LDAP_LDFLAGS" + LIBS="$LDAP_LIBS $LIBS" + for ac_func in \ + ldap_initialize \ + ldap_parse_result \ + ldap_sasl_bind_s \ + ldap_search_ext_s \ + ldap_unbind_ext_s \ + +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + LIBS="$ac_save_LIBS" + LDFLAGS="$ac_save_LDFLAGS" + CPPFLAGS="$ac_save_CPPFLAGS" +fi + + + # Where to place sshd.pid piddir=/var/run # make sure the directory exists @@ -22253,15 +21022,14 @@ # Check whether --with-pid-dir was given. -if test ${with_pid_dir+y} -then : +if test "${with_pid_dir+set}" = set; then : withval=$with_pid_dir; if test -n "$withval" && test "x$withval" != "xno" && \ test "x${withval}" != "xyes"; then piddir=$withval if test ! -d $piddir ; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: ** no $piddir directory on this system **" >&5 -printf "%s\n" "$as_me: WARNING: ** no $piddir directory on this system **" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: ** no $piddir directory on this system **" >&5 +$as_echo "$as_me: WARNING: ** no $piddir directory on this system **" >&2;} fi fi @@ -22270,16 +21038,17 @@ -printf "%s\n" "#define _PATH_SSH_PIDDIR \"$piddir\"" >>confdefs.h +cat >>confdefs.h <<_ACEOF +#define _PATH_SSH_PIDDIR "$piddir" +_ACEOF # Check whether --enable-lastlog was given. -if test ${enable_lastlog+y} -then : +if test "${enable_lastlog+set}" = set; then : enableval=$enable_lastlog; if test "x$enableval" = "xno" ; then - printf "%s\n" "#define DISABLE_LASTLOG 1" >>confdefs.h + $as_echo "#define DISABLE_LASTLOG 1" >>confdefs.h fi @@ -22287,11 +21056,10 @@ fi # Check whether --enable-utmp was given. -if test ${enable_utmp+y} -then : +if test "${enable_utmp+set}" = set; then : enableval=$enable_utmp; if test "x$enableval" = "xno" ; then - printf "%s\n" "#define DISABLE_UTMP 1" >>confdefs.h + $as_echo "#define DISABLE_UTMP 1" >>confdefs.h fi @@ -22299,24 +21067,26 @@ fi # Check whether --enable-utmpx was given. -if test ${enable_utmpx+y} -then : +if test "${enable_utmpx+set}" = set; then : enableval=$enable_utmpx; - if test "x$enableval" = "xno" ; then + ssh_disable_utmpx=$enableval -printf "%s\n" "#define DISABLE_UTMPX 1" >>confdefs.h - - fi +fi +if test no = $ac_cv_header_utmpx_h; then + ssh_disable_utmpx=yes fi +if test yes = $ssh_disable_utmpx; then + +$as_echo "#define DISABLE_UTMPX 1" >>confdefs.h +fi # Check whether --enable-wtmp was given. -if test ${enable_wtmp+y} -then : +if test "${enable_wtmp+set}" = set; then : enableval=$enable_wtmp; if test "x$enableval" = "xno" ; then - printf "%s\n" "#define DISABLE_WTMP 1" >>confdefs.h + $as_echo "#define DISABLE_WTMP 1" >>confdefs.h fi @@ -22324,12 +21094,11 @@ fi # Check whether --enable-wtmpx was given. -if test ${enable_wtmpx+y} -then : +if test "${enable_wtmpx+set}" = set; then : enableval=$enable_wtmpx; if test "x$enableval" = "xno" ; then -printf "%s\n" "#define DISABLE_WTMPX 1" >>confdefs.h +$as_echo "#define DISABLE_WTMPX 1" >>confdefs.h fi @@ -22337,37 +21106,85 @@ fi # Check whether --enable-libutil was given. -if test ${enable_libutil+y} -then : +if test "${enable_libutil+set}" = set; then : enableval=$enable_libutil; if test "x$enableval" = "xno" ; then - printf "%s\n" "#define DISABLE_LOGIN 1" >>confdefs.h + $as_echo "#define DISABLE_LOGIN 1" >>confdefs.h fi fi + # Check whether --enable-pututline was given. -if test ${enable_pututline+y} -then : - enableval=$enable_pututline; - if test "x$enableval" = "xno" ; then +if test "${enable_pututline+set}" = set; then : + enableval=$enable_pututline; ssh_enable_pututline=$enableval +else + ssh_enable_pututline=yes -printf "%s\n" "#define DISABLE_PUTUTLINE 1" >>confdefs.h +fi - fi +if test $ssh_enable_pututline = no; then : + + +$as_echo "#define DISABLE_PUTUTLINE 1" >>confdefs.h + + +else + + for ac_func in endutent pututline setutent +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + ac_fn_c_check_decl "$LINENO" "endutent" "ac_cv_have_decl_endutent" " +#ifdef HAVE_UTMP_H +# include +#endif + +" +if test "x$ac_cv_have_decl_endutent" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_ENDUTENT $ac_have_decl +_ACEOF +ac_fn_c_check_decl "$LINENO" "pututline" "ac_cv_have_decl_pututline" " +#ifdef HAVE_UTMP_H +# include +#endif + +" +if test "x$ac_cv_have_decl_pututline" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_PUTUTLINE $ac_have_decl +_ACEOF fi # Check whether --enable-pututxline was given. -if test ${enable_pututxline+y} -then : +if test "${enable_pututxline+set}" = set; then : enableval=$enable_pututxline; if test "x$enableval" = "xno" ; then -printf "%s\n" "#define DISABLE_PUTUTXLINE 1" >>confdefs.h +$as_echo "#define DISABLE_PUTUTXLINE 1" >>confdefs.h fi @@ -22376,11 +21193,10 @@ # Check whether --with-lastlog was given. -if test ${with_lastlog+y} -then : +if test "${with_lastlog+set}" = set; then : withval=$with_lastlog; if test "x$withval" = "xno" ; then - printf "%s\n" "#define DISABLE_LASTLOG 1" >>confdefs.h + $as_echo "#define DISABLE_LASTLOG 1" >>confdefs.h elif test -n "$withval" && test "x${withval}" != "xyes"; then conf_lastlog_location=$withval @@ -22391,8 +21207,8 @@ -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if your system defines LASTLOG_FILE" >&5 -printf %s "checking if your system defines LASTLOG_FILE... " >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if your system defines LASTLOG_FILE" >&5 +$as_echo_n "checking if your system defines LASTLOG_FILE... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -22409,23 +21225,22 @@ #endif int -main (void) +main () { char *lastlog = LASTLOG_FILE; ; return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO" -then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } -else $as_nop - - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if your system defines _PATH_LASTLOG" >&5 -printf %s "checking if your system defines _PATH_LASTLOG... " >&6; } +if ac_fn_c_try_compile "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if your system defines _PATH_LASTLOG" >&5 +$as_echo_n "checking if your system defines _PATH_LASTLOG... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -22439,28 +21254,27 @@ #endif int -main (void) +main () { char *lastlog = _PATH_LASTLOG; ; return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO" -then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } -else $as_nop +if ac_fn_c_try_compile "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } system_lastlog_path=no fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext if test -z "$conf_lastlog_location"; then if test x"$system_lastlog_path" = x"no" ; then @@ -22470,20 +21284,22 @@ fi done if test -z "$conf_lastlog_location"; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: ** Cannot find lastlog **" >&5 -printf "%s\n" "$as_me: WARNING: ** Cannot find lastlog **" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: ** Cannot find lastlog **" >&5 +$as_echo "$as_me: WARNING: ** Cannot find lastlog **" >&2;} fi fi fi if test -n "$conf_lastlog_location"; then -printf "%s\n" "#define CONF_LASTLOG_FILE \"$conf_lastlog_location\"" >>confdefs.h +cat >>confdefs.h <<_ACEOF +#define CONF_LASTLOG_FILE "$conf_lastlog_location" +_ACEOF fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if your system defines UTMP_FILE" >&5 -printf %s "checking if your system defines UTMP_FILE... " >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if your system defines UTMP_FILE" >&5 +$as_echo_n "checking if your system defines UTMP_FILE... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -22492,26 +21308,29 @@ #ifdef HAVE_PATHS_H # include #endif +/* Compatibility names for the strings of the canonical file names */ +#ifndef UTMP_FILE +#define UTMP_FILE _PATH_UTMP +#endif int -main (void) +main () { char *utmp = UTMP_FILE; ; return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO" -then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } -else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } +if ac_fn_c_try_compile "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } system_utmp_path=no fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext if test -z "$conf_utmp_location"; then if test x"$system_utmp_path" = x"no" ; then for f in /etc/utmp /usr/adm/utmp /var/run/utmp; do @@ -22520,19 +21339,21 @@ fi done if test -z "$conf_utmp_location"; then - printf "%s\n" "#define DISABLE_UTMP 1" >>confdefs.h + $as_echo "#define DISABLE_UTMP 1" >>confdefs.h fi fi fi if test -n "$conf_utmp_location"; then -printf "%s\n" "#define CONF_UTMP_FILE \"$conf_utmp_location\"" >>confdefs.h +cat >>confdefs.h <<_ACEOF +#define CONF_UTMP_FILE "$conf_utmp_location" +_ACEOF fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if your system defines WTMP_FILE" >&5 -printf %s "checking if your system defines WTMP_FILE... " >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if your system defines WTMP_FILE" >&5 +$as_echo_n "checking if your system defines WTMP_FILE... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -22541,26 +21362,29 @@ #ifdef HAVE_PATHS_H # include #endif +/* Compatibility names for the strings of the canonical file names */ +#ifndef WTMP_FILE +#define WTMP_FILE _PATH_WTMP +#endif int -main (void) +main () { char *wtmp = WTMP_FILE; ; return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO" -then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } -else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } +if ac_fn_c_try_compile "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } system_wtmp_path=no fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext if test -z "$conf_wtmp_location"; then if test x"$system_wtmp_path" = x"no" ; then for f in /usr/adm/wtmp /var/log/wtmp; do @@ -22569,19 +21393,21 @@ fi done if test -z "$conf_wtmp_location"; then - printf "%s\n" "#define DISABLE_WTMP 1" >>confdefs.h + $as_echo "#define DISABLE_WTMP 1" >>confdefs.h fi fi fi if test -n "$conf_wtmp_location"; then -printf "%s\n" "#define CONF_WTMP_FILE \"$conf_wtmp_location\"" >>confdefs.h +cat >>confdefs.h <<_ACEOF +#define CONF_WTMP_FILE "$conf_wtmp_location" +_ACEOF fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if your system defines WTMPX_FILE" >&5 -printf %s "checking if your system defines WTMPX_FILE... " >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if your system defines WTMPX_FILE" >&5 +$as_echo_n "checking if your system defines WTMPX_FILE... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -22595,40 +21421,41 @@ #endif int -main (void) +main () { char *wtmpx = WTMPX_FILE; ; return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO" -then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } -else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } +if ac_fn_c_try_compile "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } system_wtmpx_path=no fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext if test -z "$conf_wtmpx_location"; then if test x"$system_wtmpx_path" = x"no" ; then - printf "%s\n" "#define DISABLE_WTMPX 1" >>confdefs.h + $as_echo "#define DISABLE_WTMPX 1" >>confdefs.h fi else -printf "%s\n" "#define CONF_WTMPX_FILE \"$conf_wtmpx_location\"" >>confdefs.h +cat >>confdefs.h <<_ACEOF +#define CONF_WTMPX_FILE "$conf_wtmpx_location" +_ACEOF fi if test ! -z "$blibpath" ; then LDFLAGS="$LDFLAGS $blibflags$blibpath" - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: Please check and edit blibpath in LDFLAGS in Makefile" >&5 -printf "%s\n" "$as_me: WARNING: Please check and edit blibpath in LDFLAGS in Makefile" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Please check and edit blibpath in LDFLAGS in Makefile" >&5 +$as_echo "$as_me: WARNING: Please check and edit blibpath in LDFLAGS in Makefile" >&2;} fi ac_fn_c_check_member "$LINENO" "struct lastlog" "ll_line" "ac_cv_member_struct_lastlog_ll_line" " @@ -22646,13 +21473,12 @@ #endif " -if test "x$ac_cv_member_struct_lastlog_ll_line" = xyes -then : +if test "x$ac_cv_member_struct_lastlog_ll_line" = xyes; then : -else $as_nop +else if test x$SKIP_DISABLE_LASTLOG_DEFINE != "xyes" ; then - printf "%s\n" "#define DISABLE_LASTLOG 1" >>confdefs.h + $as_echo "#define DISABLE_LASTLOG 1" >>confdefs.h fi @@ -22674,14 +21500,13 @@ #endif " -if test "x$ac_cv_member_struct_utmp_ut_line" = xyes -then : +if test "x$ac_cv_member_struct_utmp_ut_line" = xyes; then : -else $as_nop +else - printf "%s\n" "#define DISABLE_UTMP 1" >>confdefs.h + $as_echo "#define DISABLE_UTMP 1" >>confdefs.h - printf "%s\n" "#define DISABLE_WTMP 1" >>confdefs.h + $as_echo "#define DISABLE_WTMP 1" >>confdefs.h fi @@ -22694,11 +21519,11 @@ else TEST_SSH_IPV6=yes fi -ac_fn_check_decl "$LINENO" "BROKEN_GETADDRINFO" "ac_cv_have_decl_BROKEN_GETADDRINFO" "$ac_includes_default" "$ac_c_undeclared_builtin_options" "CFLAGS" -if test "x$ac_cv_have_decl_BROKEN_GETADDRINFO" = xyes -then : +ac_fn_c_check_decl "$LINENO" "BROKEN_GETADDRINFO" "ac_cv_have_decl_BROKEN_GETADDRINFO" "$ac_includes_default" +if test "x$ac_cv_have_decl_BROKEN_GETADDRINFO" = xyes; then : TEST_SSH_IPV6=no fi + TEST_SSH_IPV6=$TEST_SSH_IPV6 TEST_SSH_UTF8=$TEST_SSH_UTF8 @@ -22707,21 +21532,23 @@ UNSUPPORTED_ALGORITHMS=$unsupported_algorithms -DEPEND=$(cat $srcdir/.depend) - CFLAGS="${CFLAGS} ${CFLAGS_AFTER}" LDFLAGS="${LDFLAGS} ${LDFLAGS_AFTER}" -# Make a copy of CFLAGS/LDFLAGS without PIE options. -LDFLAGS_NOPIE=`echo "$LDFLAGS" | sed 's/ -pie//'` -CFLAGS_NOPIE=`echo "$CFLAGS" | sed 's/ -fPIE//'` +ac_config_files="$ac_config_files Makefile buildpkg.sh opensshd.init openssh.xml openbsd-compat/Makefile openbsd-compat/regress/Makefile tests/env tests/CA/Makefile survey.sh" + +if test "x$OPENSSL_FIPS_MODE" = "xyes"; then : + if test -n "$FIPSLD_CC"; then : + CC='FIPSLD_CC=$(FIPSLD_CC) '$CC + LD='FIPSLD_CC=$(FIPSLD_CC) '$LD -ac_config_files="$ac_config_files Makefile buildpkg.sh opensshd.init openssh.xml openbsd-compat/Makefile openbsd-compat/regress/Makefile survey.sh" +fi +fi cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure @@ -22749,8 +21576,8 @@ case $ac_val in #( *${as_nl}*) case $ac_var in #( - *_cv_*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 -printf "%s\n" "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( @@ -22780,15 +21607,15 @@ /^ac_cv_env_/b end t clear :clear - s/^\([^=]*\)=\(.*[{}].*\)$/test ${\1+y} || &/ + s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ t end s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ :end' >>confcache if diff "$cache_file" confcache >/dev/null 2>&1; then :; else if test -w "$cache_file"; then if test "x$cache_file" != "x/dev/null"; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 -printf "%s\n" "$as_me: updating cache $cache_file" >&6;} + { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 +$as_echo "$as_me: updating cache $cache_file" >&6;} if test ! -f "$cache_file" || test -h "$cache_file"; then cat confcache >"$cache_file" else @@ -22802,8 +21629,8 @@ fi fi else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 -printf "%s\n" "$as_me: not updating unwritable cache $cache_file" >&6;} + { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 +$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} fi fi rm -f confcache @@ -22820,7 +21647,7 @@ for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue # 1. Remove the extension, and $U if already installed. ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' - ac_i=`printf "%s\n" "$ac_i" | sed "$ac_script"` + ac_i=`$as_echo "$ac_i" | sed "$ac_script"` # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR # will be set to the directory where LIBOBJS objects are built. as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" @@ -22837,8 +21664,8 @@ ac_write_fail=0 ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files $CONFIG_STATUS" -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 -printf "%s\n" "$as_me: creating $CONFIG_STATUS" >&6;} +{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 +$as_echo "$as_me: creating $CONFIG_STATUS" >&6;} as_write_fail=0 cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 #! $SHELL @@ -22861,16 +21688,14 @@ # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh -as_nop=: -if test ${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1 -then : +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST -else $as_nop +else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( @@ -22880,46 +21705,46 @@ fi - -# Reset variables that may have inherited troublesome values from -# the environment. - -# IFS needs to be set, to space, tab, and newline, in precisely that order. -# (If _AS_PATH_WALK were called with IFS unset, it would have the -# side effect of setting IFS to empty, thus disabling word splitting.) -# Quoting is to prevent editors from complaining about space-tab. as_nl=' ' export as_nl -IFS=" "" $as_nl" - -PS1='$ ' -PS2='> ' -PS4='+ ' - -# Ensure predictable behavior from utilities with locale-dependent output. -LC_ALL=C -export LC_ALL -LANGUAGE=C -export LANGUAGE - -# We cannot yet rely on "unset" to work, but we need these variables -# to be unset--not just set to an empty or harmless value--now, to -# avoid bugs in old shells (e.g. pre-3.0 UWIN ksh). This construct -# also avoids known problems related to "unset" and subshell syntax -# in other old shells (e.g. bash 2.01 and pdksh 5.2.14). -for as_var in BASH_ENV ENV MAIL MAILPATH CDPATH -do eval test \${$as_var+y} \ - && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : -done - -# Ensure that fds 0, 1, and 2 are open. -if (exec 3>&0) 2>/dev/null; then :; else exec 0&1) 2>/dev/null; then :; else exec 1>/dev/null; fi -if (exec 3>&2) ; then :; else exec 2>/dev/null; fi +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi # The user is always right. -if ${PATH_SEPARATOR+false} :; then +if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || @@ -22928,6 +21753,13 @@ fi +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( @@ -22936,12 +21768,8 @@ for as_dir in $PATH do IFS=$as_save_IFS - case $as_dir in #((( - '') as_dir=./ ;; - */) ;; - *) as_dir=$as_dir/ ;; - esac - test -r "$as_dir$0" && as_myself=$as_dir$0 && break + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS @@ -22953,10 +21781,30 @@ as_myself=$0 fi if test ! -f "$as_myself"; then - printf "%s\n" "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH # as_fn_error STATUS ERROR [LINENO LOG_FD] @@ -22969,14 +21817,13 @@ as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi - printf "%s\n" "$as_me: error: $2" >&2 + $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error - # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. @@ -23003,20 +21850,18 @@ { eval $1=; unset $1;} } as_unset=as_fn_unset - # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. -if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null -then : +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' -else $as_nop +else as_fn_append () { eval $1=\$$1\$2 @@ -23028,13 +21873,12 @@ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. -if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null -then : +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' -else $as_nop +else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` @@ -23065,7 +21909,7 @@ $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || -printf "%s\n" X/"$0" | +$as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q @@ -23087,10 +21931,6 @@ as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits - -# Determine whether it's possible to make 'echo' print without a newline. -# These variables are no longer used directly by Autoconf, but are AC_SUBSTed -# for compatibility with existing Makefiles. ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) @@ -23104,12 +21944,6 @@ ECHO_N='-n';; esac -# For backward compatibility with old third-party macros, we provide -# the shell variables $as_echo and $as_echo_n. New code should use -# AS_ECHO(["message"]) and AS_ECHO_N(["message"]), respectively. -as_echo='printf %s\n' -as_echo_n='printf %s' - rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file @@ -23151,7 +21985,7 @@ as_dirs= while :; do case $as_dir in #( - *\'*) as_qdir=`printf "%s\n" "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" @@ -23160,7 +21994,7 @@ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || -printf "%s\n" X"$as_dir" | +$as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q @@ -23222,8 +22056,8 @@ # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by OpenSSH $as_me Portable, which was -generated by GNU Autoconf 2.71. Invocation command line was +This file was extended by PKIX-SSH $as_me 14.2.1, which was +generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS @@ -23278,26 +22112,24 @@ Configuration headers: $config_headers -Report bugs to ." +Report bugs to . +PKIX-SSH home page: ." _ACEOF -ac_cs_config=`printf "%s\n" "$ac_configure_args" | sed "$ac_safe_unquote"` -ac_cs_config_escaped=`printf "%s\n" "$ac_cs_config" | sed "s/^ //; s/'/'\\\\\\\\''/g"` cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 -ac_cs_config='$ac_cs_config_escaped' +ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -OpenSSH config.status Portable -configured by $0, generated by GNU Autoconf 2.71, +PKIX-SSH config.status 14.2.1 +configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" -Copyright (C) 2021 Free Software Foundation, Inc. +Copyright (C) 2012 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." ac_pwd='$ac_pwd' srcdir='$srcdir' INSTALL='$INSTALL' -MKDIR_P='$MKDIR_P' AWK='$AWK' test -n "\$AWK" || AWK=awk _ACEOF @@ -23330,15 +22162,15 @@ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) ac_cs_recheck=: ;; --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) - printf "%s\n" "$ac_cs_version"; exit ;; + $as_echo "$ac_cs_version"; exit ;; --config | --confi | --conf | --con | --co | --c ) - printf "%s\n" "$ac_cs_config"; exit ;; + $as_echo "$ac_cs_config"; exit ;; --debug | --debu | --deb | --de | --d | -d ) debug=: ;; --file | --fil | --fi | --f ) $ac_shift case $ac_optarg in - *\'*) ac_optarg=`printf "%s\n" "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; '') as_fn_error $? "missing file argument" ;; esac as_fn_append CONFIG_FILES " '$ac_optarg'" @@ -23346,7 +22178,7 @@ --header | --heade | --head | --hea ) $ac_shift case $ac_optarg in - *\'*) ac_optarg=`printf "%s\n" "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; esac as_fn_append CONFIG_HEADERS " '$ac_optarg'" ac_need_defaults=false;; @@ -23355,7 +22187,7 @@ as_fn_error $? "ambiguous option: \`$1' Try \`$0 --help' for more information.";; --help | --hel | -h ) - printf "%s\n" "$ac_cs_usage"; exit ;; + $as_echo "$ac_cs_usage"; exit ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil | --si | --s) ac_cs_silent=: ;; @@ -23383,7 +22215,7 @@ if \$ac_cs_recheck; then set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion shift - \printf "%s\n" "running CONFIG_SHELL=$SHELL \$*" >&6 + \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 CONFIG_SHELL='$SHELL' export CONFIG_SHELL exec "\$@" @@ -23397,7 +22229,7 @@ sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX ## Running $as_me. ## _ASBOX - printf "%s\n" "$ac_log" + $as_echo "$ac_log" } >&5 _ACEOF @@ -23417,6 +22249,8 @@ "openssh.xml") CONFIG_FILES="$CONFIG_FILES openssh.xml" ;; "openbsd-compat/Makefile") CONFIG_FILES="$CONFIG_FILES openbsd-compat/Makefile" ;; "openbsd-compat/regress/Makefile") CONFIG_FILES="$CONFIG_FILES openbsd-compat/regress/Makefile" ;; + "tests/env") CONFIG_FILES="$CONFIG_FILES tests/env" ;; + "tests/CA/Makefile") CONFIG_FILES="$CONFIG_FILES tests/CA/Makefile" ;; "survey.sh") CONFIG_FILES="$CONFIG_FILES survey.sh" ;; *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; @@ -23429,8 +22263,8 @@ # We use the long form for the default assignment because of an extremely # bizarre bug on SunOS 4.1.3. if $ac_need_defaults; then - test ${CONFIG_FILES+y} || CONFIG_FILES=$config_files - test ${CONFIG_HEADERS+y} || CONFIG_HEADERS=$config_headers + test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files + test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers fi # Have a temporary directory for convenience. Make it in the build tree @@ -23766,7 +22600,7 @@ esac || as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; esac - case $ac_f in *\'*) ac_f=`printf "%s\n" "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac + case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac as_fn_append ac_file_inputs " '$ac_f'" done @@ -23774,17 +22608,17 @@ # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ configure_input='Generated from '` - printf "%s\n" "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' + $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' `' by configure.' if test x"$ac_file" != x-; then configure_input="$ac_file. $configure_input" - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 -printf "%s\n" "$as_me: creating $ac_file" >&6;} + { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 +$as_echo "$as_me: creating $ac_file" >&6;} fi # Neutralize special characters interpreted by sed in replacement strings. case $configure_input in #( *\&* | *\|* | *\\* ) - ac_sed_conf_input=`printf "%s\n" "$configure_input" | + ac_sed_conf_input=`$as_echo "$configure_input" | sed 's/[\\\\&|]/\\\\&/g'`;; #( *) ac_sed_conf_input=$configure_input;; esac @@ -23801,7 +22635,7 @@ X"$ac_file" : 'X\(//\)[^/]' \| \ X"$ac_file" : 'X\(//\)$' \| \ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || -printf "%s\n" X"$ac_file" | +$as_echo X"$ac_file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q @@ -23825,9 +22659,9 @@ case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) - ac_dir_suffix=/`printf "%s\n" "$ac_dir" | sed 's|^\.[\\/]||'` + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. - ac_top_builddir_sub=`printf "%s\n" "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; @@ -23865,11 +22699,6 @@ [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; esac - ac_MKDIR_P=$MKDIR_P - case $MKDIR_P in - [\\/$]* | ?:[\\/]* ) ;; - */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;; - esac _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 @@ -23889,8 +22718,8 @@ case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in *datarootdir*) ac_datarootdir_seen=yes;; *@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 -printf "%s\n" "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 +$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_datarootdir_hack=' @@ -23924,7 +22753,6 @@ s&@abs_builddir@&$ac_abs_builddir&;t t s&@abs_top_builddir@&$ac_abs_top_builddir&;t t s&@INSTALL@&$ac_INSTALL&;t t -s&@MKDIR_P@&$ac_MKDIR_P&;t t $ac_datarootdir_hack " eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ @@ -23934,9 +22762,9 @@ { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ "$ac_tmp/out"`; test -z "$ac_out"; } && - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&5 -printf "%s\n" "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' +$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&2;} rm -f "$ac_tmp/stdin" @@ -23952,20 +22780,20 @@ # if test x"$ac_file" != x-; then { - printf "%s\n" "/* $configure_input */" >&1 \ + $as_echo "/* $configure_input */" \ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" } >"$ac_tmp/config.h" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 -printf "%s\n" "$as_me: $ac_file is unchanged" >&6;} + { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 +$as_echo "$as_me: $ac_file is unchanged" >&6;} else rm -f "$ac_file" mv "$ac_tmp/config.h" "$ac_file" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 fi else - printf "%s\n" "/* $configure_input */" >&1 \ + $as_echo "/* $configure_input */" \ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \ || as_fn_error $? "could not create -" "$LINENO" 5 fi @@ -24006,8 +22834,8 @@ $ac_cs_success || as_fn_exit 1 fi if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 -printf "%s\n" "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 +$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} fi @@ -24026,10 +22854,11 @@ J=`eval echo ${superuser_path}` ; J=`eval echo ${J}` echo "" -echo "OpenSSH has been configured with the following options:" +echo "$PACKAGE_NAME has been configured with the following options:" echo " User binaries: $B" echo " System binaries: $C" echo " Configuration files: $D" +echo " CA root: $sshcadir" echo " Askpass program: $E" echo " Manual pages: $F" echo " PID file: $G" @@ -24052,8 +22881,14 @@ echo " OSF SIA support: $SIA_MSG" echo " KerberosV support: $KRB5_MSG" echo " SELinux support: $SELINUX_MSG" +echo " PKCS#11 support: $PKCS11_MSG" +echo " TCP Wrappers support: $TCPW_MSG" +echo " MD5 password support: $MD5_MSG" +echo " OCSP support: $OCSP_MSG" +echo " LDAP queries: $LDAP_MSG" echo " libedit support: $LIBEDIT_MSG" echo " libldns support: $LDNS_MSG" +echo " Compression support: $ZLIB_MSG" echo " Solaris process contract support: $SPC_MSG" echo " Solaris project support: $SP_MSG" echo " Solaris privilege support: $SPP_MSG" @@ -24062,22 +22897,25 @@ echo " BSD Auth support: $BSD_AUTH_MSG" echo " Random number source: $RAND_MSG" echo " Privsep sandbox style: $SANDBOX_STYLE" -echo " PKCS#11 support: $enable_pkcs11" -echo " U2F/FIDO support: $enable_sk" +echo " FIPS capable build: $OPENSSL_FIPS_MODE" echo "" echo " Host: ${host}" +if test "x$OPENSSL_FIPS_MODE" = "xyes"; then : + +echo " Actual compiler: $FIPSLD_CC" + +fi echo " Compiler: ${CC}" echo " Compiler flags: ${CFLAGS}" echo "Preprocessor flags: ${CPPFLAGS}" echo " Linker flags: ${LDFLAGS}" echo " Libraries: ${LIBS}" -if test ! -z "${CHANNELLIBS}"; then -echo " +for channels: ${CHANNELLIBS}" -fi -if test ! -z "${LIBFIDO2}"; then -echo " +for FIDO2: ${LIBFIDO2}" +if $ssh_ocsp; then : + +echo " OCSP libraries: $LIBOCSP" + fi if test ! -z "${SSHDLIBS}"; then echo " +for sshd: ${SSHDLIBS}" @@ -24090,6 +22928,27 @@ echo "" fi +if test "x$LDAP_MSG" = "xyes" ; then +echo "Extra LDAP flags:" +echo " LDAP compiler flags: ${LDAP_CFLAGS}" +echo "LDAP preprocessor flags: ${LDAP_CPPFLAGS}" +echo " LDAP linker flags: ${LDAP_LDFLAGS}" +echo " LDAP libraries: ${LDAP_LIBS}" +echo "" +echo "LDAP paths(used only in tests):" +echo " LDAP sysconfig dir: ${LDAP_SYSCONFDIR}" +echo " LDAP libexec dir: ${LDAP_LIBEXECDIR}" +echo " LDAP bin dir: ${LDAP_BINDIR}" +echo "" +fi + +if test "x$OPENSSL_FIPS_MODE" = "xyes"; then : + +echo " FIPS libraries: $FIPS_LIBS" +echo "" + +fi + if test "x$PAM_MSG" = "xyes" ; then echo "PAM is enabled. You may need to install a PAM control file " echo "for sshd, otherwise password authentication may fail. " diff -ruN openssh-9.4p1/configure.ac openssh-9.4p1+x509-14.2.1/configure.ac --- openssh-9.4p1/configure.ac 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/configure.ac 2023-08-20 10:07:00.000000000 +0300 @@ -1,5 +1,6 @@ # # Copyright (c) 1999-2004 Damien Miller +# Copyright (c) 2002-2023 Roumen Petrov # # Permission to use, copy, modify, and distribute this software for any # purpose with or without fee is hereby granted, provided that the above @@ -13,33 +14,34 @@ # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -AC_INIT([OpenSSH], [Portable], [openssh-unix-dev@mindrot.org]) -AC_CONFIG_MACRO_DIR([m4]) +AC_PREREQ([2.59]) +m4_include([version.m4]) + +AC_INIT([SSH_PACKAGE], [SSH_VERSION], [SSH_BUGREPORT], [openssh], [SSH_URL]) AC_CONFIG_SRCDIR([ssh.c]) -# Check for stale configure as early as possible. -for i in $srcdir/configure.ac $srcdir/m4/*.m4; do - if test "$i" -nt "$srcdir/configure"; then - AC_MSG_ERROR([$i newer than configure, run autoreconf]) - fi +dnl check for stale configure as early as possible +for i in $srcdir/version.m4 $srcdir/m4/*.m4 $srcdir/configure.ac ; do + AS_IF([test "$i" -nt "$srcdir/configure"], [ + AC_MSG_ERROR([configure older than $i + +*** Please re-genenarate and configure *** + ]) + ]) done -AC_LANG([C]) +m4_include([m4/c.m4]) +m4_include([m4/local.m4]) +m4_include([m4/ldap.m4]) AC_CONFIG_HEADERS([config.h]) -AC_PROG_CC([cc gcc clang]) - -# XXX relax this after reimplementing logit() etc. -AC_MSG_CHECKING([if $CC supports C99-style variadic macros]) -AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ -int f(int a, int b, int c) { return a + b + c; } -#define F(a, ...) f(a, __VA_ARGS__) -]], [[return F(1, 2, -3);]])], - [ AC_MSG_RESULT([yes]) ], - [ AC_MSG_ERROR([*** OpenSSH requires support for C99-style variadic macros]) ] -) AC_CANONICAL_HOST + +SSH_AC_PROG_CC +AS_IF([test "x$ac_cv_prog_cc_c99" = "xno"], [ + AC_MSG_ERROR([*** $PACKAGE_NAME requires a C99 capable compiler ***]) +]) AC_C_BIGENDIAN # Checks for programs. @@ -48,24 +50,18 @@ AC_PROG_RANLIB AC_PROG_INSTALL AC_PROG_EGREP -AC_PROG_MKDIR_P AC_CHECK_TOOLS([AR], [ar]) AC_PATH_PROG([CAT], [cat]) AC_PATH_PROG([KILL], [kill]) AC_PATH_PROG([SED], [sed]) -AC_PATH_PROG([TEST_MINUS_S_SH], [bash]) -AC_PATH_PROG([TEST_MINUS_S_SH], [ksh]) -AC_PATH_PROG([TEST_MINUS_S_SH], [sh]) -AC_PATH_PROG([SH], [bash]) -AC_PATH_PROG([SH], [ksh]) AC_PATH_PROG([SH], [sh]) AC_PATH_PROG([GROFF], [groff]) AC_PATH_PROG([NROFF], [nroff awf]) AC_PATH_PROG([MANDOC], [mandoc]) AC_PATH_TOOL([PKGCONFIG], [pkg-config], [no]) -AC_SUBST([TEST_SHELL], [sh]) -dnl select manpage formatter to be used to build "cat" format pages. +AC_ARG_VAR([MANFMT],[manpage formatter]) +if test -z "$MANFMT" ; then if test "x$MANDOC" != "x" ; then MANFMT="$MANDOC" elif test "x$NROFF" != "x" ; then @@ -76,7 +72,7 @@ AC_MSG_WARN([no manpage formatter found]) MANFMT="false" fi -AC_SUBST([MANFMT]) +fi dnl for buildpkg.sh AC_PATH_PROG([PATH_GROUPADD_PROG], [groupadd], [groupadd], @@ -90,6 +86,9 @@ AC_SUBST([STARTUP_SCRIPT_SHELL], [/bin/sh]) fi +m4_include([m4/android.m4]) +SSH_ANDROID_PRECONF + # System features AC_SYS_LARGEFILE @@ -113,14 +112,14 @@ AC_C_INLINE AC_CHECK_DECL([LLONG_MAX], [have_llong_max=1], , [#include ]) -AC_CHECK_DECL([LONG_LONG_MAX], [have_long_long_max=1], , [#include ]) + AC_CHECK_DECL([SYSTR_POLICY_KILL], [have_systr_policy_kill=1], , [ #include #include #include ]) AC_CHECK_DECL([RLIMIT_NPROC], - [AC_DEFINE([HAVE_RLIMIT_NPROC], [], [sys/resource.h has RLIMIT_NPROC])], , [ + [AC_DEFINE([HAVE_RLIMIT_NPROC], [1], [sys/resource.h has RLIMIT_NPROC])], , [ #include #include ]) @@ -129,43 +128,49 @@ #include ]) -openssl=yes -openssl_bin=openssl +dnl compatibility argument AC_ARG_WITH([openssl], - [ --without-openssl Disable use of OpenSSL; use only limited internal crypto **EXPERIMENTAL** ], - [ if test "x$withval" = "xno" ; then - openssl=no - openssl_bin="" - fi - ] + [AS_HELP_STRING([--without-openssl], + [Disable use of OpenSSL; use only limited internal crypto **EXPERIMENTAL** ])], + [], + [with_openssl=yes] ) AC_MSG_CHECKING([whether OpenSSL will be used for cryptography]) -if test "x$openssl" = "xyes" ; then - AC_MSG_RESULT([yes]) - AC_DEFINE_UNQUOTED([WITH_OPENSSL], [1], [use libcrypto for cryptography]) -else - AC_MSG_RESULT([no]) +AC_MSG_RESULT([$with_openssl]) +if test "x$with_openssl" != "xyes"; then + AC_MSG_ERROR([build with OpenSSL is required]) fi -use_stack_protector=1 -use_toolchain_hardening=1 +openssl=yes +AC_DEFINE_UNQUOTED([WITH_OPENSSL], [1], [use libcrypto for cryptography]) + +use_stack_protector=: +use_toolchain_hardening=: AC_ARG_WITH([stackprotect], - [ --without-stackprotect Don't use compiler's stack protection], [ - if test "x$withval" = "xno"; then - use_stack_protector=0 - fi ]) + [AS_HELP_STRING([--without-stackprotect], + [Don't use compiler's stack protection])], + [ + if test "x$withval" = "xno"; then + use_stack_protector=false + fi + ] +) AC_ARG_WITH([hardening], - [ --without-hardening Don't use toolchain hardening flags], [ - if test "x$withval" = "xno"; then - use_toolchain_hardening=0 - fi ]) + [AS_HELP_STRING([--without-hardening], + [Don't use toolchain hardening flags])], + [ + if test "x$withval" = "xno"; then + use_toolchain_hardening=false + fi + ] +) # We use -Werror for the tests only so that we catch warnings like "this is # on by default" for things like -fPIE. AC_MSG_CHECKING([if $CC supports -Werror]) saved_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -Werror" -AC_COMPILE_IFELSE([AC_LANG_SOURCE([[int main(void) { return 0; }]])], +AC_COMPILE_IFELSE([AC_LANG_PROGRAM], [ AC_MSG_RESULT([yes]) WERROR="-Werror"], [ AC_MSG_RESULT([no]) @@ -193,7 +198,6 @@ OSSH_CHECK_CFLAG_COMPILE([-pipe]) OSSH_CHECK_CFLAG_COMPILE([-Wunknown-warning-option]) OSSH_CHECK_CFLAG_COMPILE([-Wno-error=format-truncation]) - OSSH_CHECK_CFLAG_COMPILE([-Qunused-arguments]) OSSH_CHECK_CFLAG_COMPILE([-Wall]) OSSH_CHECK_CFLAG_COMPILE([-Wextra]) OSSH_CHECK_CFLAG_COMPILE([-Wpointer-arith]) @@ -202,13 +206,14 @@ OSSH_CHECK_CFLAG_COMPILE([-Wformat-security]) OSSH_CHECK_CFLAG_COMPILE([-Wsizeof-pointer-memaccess]) OSSH_CHECK_CFLAG_COMPILE([-Wpointer-sign], [-Wno-pointer-sign]) - OSSH_CHECK_CFLAG_COMPILE([-Wunused-parameter], [-Wno-unused-parameter]) + #unused parameter must be marked explicitly + #OSSH_CHECK_CFLAG_COMPILE([-Wunused-parameter], [-Wno-unused-parameter]) + #OSSH_CHECK_CFLAG_COMPILE([-Qunused-arguments]) OSSH_CHECK_CFLAG_COMPILE([-Wunused-result], [-Wno-unused-result]) - OSSH_CHECK_CFLAG_COMPILE([-Wimplicit-fallthrough]) - OSSH_CHECK_CFLAG_COMPILE([-Wmisleading-indentation]) - OSSH_CHECK_CFLAG_COMPILE([-Wbitwise-instead-of-logical]) + #ignore bogus warnings on some compilers... + #OSSH_CHECK_CFLAG_COMPILE([-Wimplicit-fallthrough]) OSSH_CHECK_CFLAG_COMPILE([-fno-strict-aliasing]) - if test "x$use_toolchain_hardening" = "x1"; then + if $use_toolchain_hardening ; then OSSH_CHECK_CFLAG_COMPILE([-mretpoline]) # clang OSSH_CHECK_LDFLAG_LINK([-Wl,-z,retpolineplt]) OSSH_CHECK_CFLAG_COMPILE([-D_FORTIFY_SOURCE=2]) @@ -220,15 +225,22 @@ # that can overflow. We must check that the result of enabling it # actually links. The test program compiled/linked includes a number # of integer operations that should exercise this. - OSSH_CHECK_CFLAG_LINK([-ftrapv]) + # + # Remark: Option -ftrapv is not maintained and does not work on + # all platforms. Use -fsanitize=... instead. + #-#OSSH_CHECK_CFLAG_LINK([-ftrapv]) + + # TODO: wipe used registers # clang 15 seems to have a bug in -fzero-call-used-regs=all. See - # https://bugzilla.mindrot.org/show_bug.cgi?id=3475 and # https://github.com/llvm/llvm-project/issues/59242 - case "$CLANG_VER" in - 15.*) OSSH_CHECK_CFLAG_COMPILE([-fzero-call-used-regs=used]) ;; - *) OSSH_CHECK_CFLAG_COMPILE([-fzero-call-used-regs=all]) ;; - esac - OSSH_CHECK_CFLAG_COMPILE([-ftrivial-auto-var-init=zero]) + #case "$CLANG_VER" in + #15.*) OSSH_CHECK_CFLAG_COMPILE([-fzero-call-used-regs=used]) ;; + #*) OSSH_CHECK_CFLAG_COMPILE([-fzero-call-used-regs=all]) ;; + #esac + + # TODO: stack variables auto-initialization + # (see -Wuninitialized) + #-#OSSH_CHECK_CFLAG_COMPILE([-ftrivial-auto-var-init=zero]) fi AC_MSG_CHECKING([if $CC accepts -fno-builtin-memset]) @@ -244,7 +256,7 @@ # -fstack-protector-all doesn't always work for some GCC versions # and/or platforms, so we test if we can. If it's not supported # on a given platform gcc will emit a warning so we use -Werror. - if test "x$use_stack_protector" = "x1"; then + if $use_stack_protector ; then for t in -fstack-protector-strong -fstack-protector-all \ -fstack-protector; do AC_MSG_CHECKING([if $CC supports $t]) @@ -254,10 +266,11 @@ LDFLAGS="$LDFLAGS $t -Werror" AC_LINK_IFELSE( [AC_LANG_PROGRAM([[ - #include - int func (int t) {char b[100]; snprintf(b,sizeof b,"%d",t); return t;} - ]], - [[ +#include + +int func (int t); +int func (int t) {char b[100]; snprintf(b,sizeof b,"%d",t); return t;} + ]],[[ char x[256]; snprintf(x, sizeof(x), "XXX%d", func(1)); ]])], @@ -267,10 +280,11 @@ AC_MSG_CHECKING([if $t works]) AC_RUN_IFELSE( [AC_LANG_PROGRAM([[ - #include - int func (int t) {char b[100]; snprintf(b,sizeof b,"%d",t); return t;} - ]], - [[ +#include + +int func (int t); +int func (int t) {char b[100]; snprintf(b,sizeof b,"%d",t); return t;} + ]],[[ char x[256]; snprintf(x, sizeof(x), "XXX%d", func(1)); ]])], @@ -288,6 +302,7 @@ done fi + # keep check as C99 is not strictly required if test -z "$have_llong_max"; then # retry LLONG_MAX with -std=gnu99, needed on some Linuxes unset ac_cv_have_decl_LLONG_MAX @@ -301,12 +316,20 @@ fi fi +if test -z "$have_llong_max" ; then + dnl LONGLONG_{MIN|MAX} is defined on AIX + AC_CHECK_DECL([LONGLONG_MAX], [have_llong_max=1], , [#include ]) +fi +if test -z "$have_llong_max" ; then + dnl LONG_LONG_{MIN|MAX} is defined on HP-UX + AC_CHECK_DECL([LONG_LONG_MAX], [have_llong_max=1], , [#include ]) +fi + AC_MSG_CHECKING([if compiler allows __attribute__ on return types]) AC_COMPILE_IFELSE( [AC_LANG_PROGRAM([[ -#include __attribute__((__unused__)) static void foo(void){return;}]], - [[ exit(0); ]])], + [[]])], [ AC_MSG_RESULT([yes]) ], [ AC_MSG_RESULT([no]) AC_DEFINE(NO_ATTRIBUTE_ON_RETURN_TYPE, 1, @@ -316,32 +339,23 @@ AC_MSG_CHECKING([if compiler allows __attribute__ prototype args]) AC_COMPILE_IFELSE( [AC_LANG_PROGRAM([[ -#include typedef void foo(const char *, ...) __attribute__((format(printf, 1, 2)));]], - [[ exit(0); ]])], + [[]])], [ AC_MSG_RESULT([yes]) ], [ AC_MSG_RESULT([no]) AC_DEFINE(NO_ATTRIBUTE_ON_PROTOTYPE_ARGS, 1, [compiler does not accept __attribute__ on prototype args]) ] ) -AC_MSG_CHECKING([if compiler supports variable length arrays]) +AC_MSG_CHECKING([if compiler allows __attribute__ to warn if last parameter is not NULL]) AC_COMPILE_IFELSE( - [AC_LANG_PROGRAM([[#include ]], - [[ int i; for (i=0; i<3; i++){int a[i]; a[i-1]=0;} exit(0); ]])], - [ AC_MSG_RESULT([yes]) - AC_DEFINE(VARIABLE_LENGTH_ARRAYS, [1], - [compiler supports variable length arrays]) ], - [ AC_MSG_RESULT([no]) ] -) - -AC_MSG_CHECKING([if compiler accepts variable declarations after code]) -AC_COMPILE_IFELSE( - [AC_LANG_PROGRAM([[#include ]], - [[ int a; a = 1; int b = 1; exit(a-b); ]])], + [AC_LANG_PROGRAM([[ +extern void foo(const char *, ...) __attribute__((__sentinel__));]], + [[]])], [ AC_MSG_RESULT([yes]) - AC_DEFINE(VARIABLE_DECLARATION_AFTER_CODE, [1], - [compiler variable declarations after code]) ], + AC_DEFINE([HAVE_ATTRIBUTE__SENTINEL__], [1], + [Define to 1 if compiler accept __attribute__ that warn if last parameter is not NULL]) + ], [ AC_MSG_RESULT([no]) ] ) @@ -349,14 +363,14 @@ AC_DEFINE([HAVE_ATTRIBUTE__NONNULL__], [1], [Have attribute nonnull]) fi +rpath_opt= AC_ARG_WITH([rpath], - [ --without-rpath Disable auto-added -R linker paths], + [AS_HELP_STRING([--with-rpath=FLAG], + [Use runtime library search path (by default -R flag)])], [ - if test "x$withval" = "xno" ; then - rpath_opt="" - elif test "x$withval" = "xyes" ; then + if test "x$withval" = "xyes" ; then rpath_opt="-R" - else + elif test "x$withval" != "xno" ; then rpath_opt="$withval" fi ] @@ -430,19 +444,10 @@ ] ) -dnl On some old platforms, sys/stat.h requires sys/types.h, but autoconf-2.71's -dnl AC_CHECK_INCLUDES_DEFAULT checks for them in the opposite order. If we -dnl haven't detected it, recheck. -if test "x$ac_cv_header_sys_stat_h" != "xyes"; then - unset ac_cv_header_sys_stat_h - AC_CHECK_HEADERS([sys/stat.h]) -fi - AC_CHECK_HEADERS([ \ blf.h \ bstring.h \ crypt.h \ - crypto/sha2.h \ dirent.h \ endian.h \ elf.h \ @@ -456,7 +461,6 @@ ia.h \ iaf.h \ ifaddrs.h \ - inttypes.h \ langinfo.h \ limits.h \ locale.h \ @@ -476,9 +480,6 @@ sha2.h \ shadow.h \ stddef.h \ - stdint.h \ - string.h \ - strings.h \ sys/bitypes.h \ sys/byteorder.h \ sys/bsdtty.h \ @@ -488,7 +489,6 @@ sys/mman.h \ sys/label.h \ sys/ndir.h \ - sys/param.h \ sys/poll.h \ sys/prctl.h \ sys/procctl.h \ @@ -499,6 +499,7 @@ sys/stream.h \ sys/stropts.h \ sys/strtio.h \ + sys/statfs.h \ sys/statvfs.h \ sys/sysmacros.h \ sys/time.h \ @@ -508,7 +509,6 @@ tmpdir.h \ ttyent.h \ ucred.h \ - unistd.h \ usersec.h \ util.h \ utime.h \ @@ -539,14 +539,14 @@ #endif ]) +# caph_cache_tzdata() is defined as inline in capsicum_helpers.h AC_MSG_CHECKING([for caph_cache_tzdata]) AC_LINK_IFELSE( [AC_LANG_PROGRAM([[ #include ]], [[caph_cache_tzdata();]])], - [ - AC_MSG_RESULT([yes]) - AC_DEFINE([HAVE_CAPH_CACHE_TZDATA], [1], - [Define if you have caph_cache_tzdata]) + [ AC_MSG_RESULT([yes]) + AC_DEFINE([HAVE_CAPH_CACHE_TZDATA], [1], + [Define to 1 if you have the `caph_cache_tzdata' function.]) ], [ AC_MSG_RESULT([no]) ] ) @@ -591,6 +591,26 @@ #include ]) + +# templates for target-specific defines +AH_TEMPLATE([BROKEN_TCGETATTR_ICANON], [Define to 1 if tcgetattr with ICANON may hang]) +AH_TEMPLATE([BROKEN_GETADDRINFO], [Define to 1 if system getaddrinfo(3) is broken]) +AH_TEMPLATE([BROKEN_SETREUID], [Define to 1 if system setreuid(2) is broken]) +AH_TEMPLATE([BROKEN_SETREGID], [Define to 1 if system setregid(2) is broken]) +# For instance inet_ntoa(3) Irix gcc issue: +AH_TEMPLATE([BROKEN_INET_NTOA], [Define to 1 if system inet_ntoa(3) is broken]) +AH_TEMPLATE([BROKEN_UPDWTMPX], [Define to 1 if system updwtmpx(3) is broken]) +AH_TEMPLATE([BROKEN_POLL], [Define to 1 if system poll(2) implementation is broken]) +AH_TEMPLATE([NEED_SETPGRP], [Need setpgrp to acquire controlling tty]) +AH_TEMPLATE([DISABLE_FD_PASSING], [Define if your platform needs to skip post auth file descriptor passing]) +AH_TEMPLATE([BROKEN_ONE_BYTE_DIRENT_D_NAME], + [Define to 1 if system struct dirent expects program to allocate extra space for d_name]) +# For instance unexpected glob(3) functionality on FreeBSD and OS X +AH_TEMPLATE([BROKEN_GLOB], [Define to 1 if system glob(3) does not do what we expect]) +AH_TEMPLATE([SSHD_ACQUIRES_CTTY], + [Define to 1 if sshd somehow reacquires a controlling TTY after setsid()]) +AH_TEMPLATE([GSSAPI], [Define this if you want GSSAPI support]) + # Messages for features tested for in target-specific section SIA_MSG="no" SPC_MSG="no" @@ -602,6 +622,9 @@ SOLARIS_PRIVS="no" # Check for some target-specific stuff +AC_SUBST([XLDFLAGS]) +AC_SUBST([XDEPLIBS]) +ssh_disable_utmpx=no case "$host" in *-*-aix*) # Some versions of VAC won't allow macro redefinitions at @@ -613,8 +636,9 @@ AC_COMPILE_IFELSE( [AC_LANG_PROGRAM([[ #define testmacro foo -#define testmacro bar]], - [[ exit(0); ]])], +#define testmacro bar + ]], [[ + ]])], [ AC_MSG_RESULT([yes]) ], [ AC_MSG_RESULT([no]) CC="`echo $CC | sed 's/-qlanglvl\=ansi//g'`" @@ -681,8 +705,8 @@ check_for_aix_broken_getaddrinfo=1 AC_DEFINE([SETEUID_BREAKS_SETUID], [1], [Define if your platform breaks doing a seteuid before a setuid]) - AC_DEFINE([BROKEN_SETREUID], [1], [Define if your setreuid() is broken]) - AC_DEFINE([BROKEN_SETREGID], [1], [Define if your setregid() is broken]) + AC_DEFINE([BROKEN_SETREUID], [1]) + AC_DEFINE([BROKEN_SETREGID], [1]) dnl AIX handles lastlog as part of its login message AC_DEFINE([DISABLE_LASTLOG], [1], [Define if you don't want to use lastlog]) AC_DEFINE([LOGIN_NEEDS_UTMPX], [1], @@ -697,10 +721,6 @@ AC_DEFINE([BROKEN_STRNDUP], 1, [strndup broken, see APAR IY61211]) AC_DEFINE([BROKEN_STRNLEN], 1, [strnlen broken, see APAR IY62551]) ;; -*-*-android*) - AC_DEFINE([DISABLE_UTMP], [1], [Define if you don't want to use utmp]) - AC_DEFINE([DISABLE_WTMP], [1], [Define if you don't want to use wtmp]) - ;; *-*-cygwin*) LIBS="$LIBS /usr/lib/textreadmode.o" AC_DEFINE([HAVE_CYGWIN], [1], [Define if you are on Cygwin]) @@ -711,10 +731,7 @@ [Define if you want to disable shadow passwords]) AC_DEFINE([NO_X11_UNIX_SOCKETS], [1], [Define if X11 doesn't support AF_UNIX sockets on that system]) - AC_DEFINE([DISABLE_FD_PASSING], [1], - [Define if your platform needs to skip post auth - file descriptor passing]) - AC_DEFINE([SSH_IOBUFSZ], [65535], [Windows is sensitive to read buffer size]) + AC_DEFINE([DISABLE_FD_PASSING]) AC_DEFINE([FILESYSTEM_NO_BACKSLASH], [1], [File names may not contain backslash characters]) # Cygwin defines optargs, optargs as declspec(dllimport) for historical # reasons which cause compile warnings, so we disable those warnings. @@ -724,38 +741,41 @@ AC_DEFINE([IP_TOS_IS_BROKEN], [1], [Define if your system choked on IP TOS setting]) AC_DEFINE([SETEUID_BREAKS_SETUID]) - AC_DEFINE([BROKEN_SETREUID]) - AC_DEFINE([BROKEN_SETREGID]) + AC_DEFINE([BROKEN_SETREUID], [1]) + AC_DEFINE([BROKEN_SETREGID], [1]) ;; *-*-darwin*) use_pie=auto AC_MSG_CHECKING([if we have working getaddrinfo]) - AC_RUN_IFELSE([AC_LANG_SOURCE([[ + AC_RUN_IFELSE([AC_LANG_PROGRAM([[ #include -#include -int main(void) { if (NSVersionOfRunTimeLibrary("System") >= (60 << 16)) - exit(0); - else - exit(1); -} + ]],[[ + if (NSVersionOfRunTimeLibrary("System") < (60 << 16)) + return 1; ]])], [AC_MSG_RESULT([working])], [AC_MSG_RESULT([buggy]) - AC_DEFINE([BROKEN_GETADDRINFO], [1], - [getaddrinfo is broken (if present)]) + AC_DEFINE([BROKEN_GETADDRINFO], [1]) ], [AC_MSG_RESULT([assume it is working])]) AC_DEFINE([SETEUID_BREAKS_SETUID]) - AC_DEFINE([BROKEN_SETREUID]) - AC_DEFINE([BROKEN_SETREGID]) - AC_DEFINE([BROKEN_GLOB], [1], [OS X glob does not do what we expect]) + AC_DEFINE([BROKEN_SETREUID], [1]) + AC_DEFINE([BROKEN_SETREGID], [1]) + AC_DEFINE([BROKEN_GLOB], [1]) AC_DEFINE_UNQUOTED([BIND_8_COMPAT], [1], [Define if your resolver libs need this for getrrsetbyname]) - AC_DEFINE([SSH_TUN_FREEBSD], [1], [Open tunnel devices the FreeBSD way]) - AC_DEFINE([SSH_TUN_COMPAT_AF], [1], - [Use tunnel device compatibility to OpenBSD]) - AC_DEFINE([SSH_TUN_PREPEND_AF], [1], - [Prepend the address family to IP tunnel traffic]) + AC_CHECK_HEADERS([net/if_utun.h]) + if test "x$ac_cv_header_net_if_utun_h" = "xyes" ; then + AC_DEFINE([SSH_TUN_DARWIN], [1], + [Open tunnel devices the Darwin way]) + else + AC_DEFINE([SSH_TUN_FREEBSD], [1], + [Open tunnel devices the FreeBSD way]) + AC_DEFINE([SSH_TUN_PREPEND_AF], [1], + [Prepend the address family to IP tunnel traffic]) + AC_DEFINE([SSH_TUN_COMPAT_AF], [1], + [Use tunnel device compatibility to OpenBSD]) + fi m4_pattern_allow([AU_IPv]) AC_CHECK_DECL([AU_IPv4], [], AC_DEFINE([AU_IPv4], [0], [System only supports IPv4 audit records]) @@ -776,11 +796,9 @@ AC_CHECK_FUNCS([proc_pidinfo]) # poll(2) is broken for character-special devices (at least). # cf. Apple bug 3710161 (not public, but searchable) - AC_DEFINE([BROKEN_POLL], [1], - [System poll(2) implementation is broken]) + AC_DEFINE([BROKEN_POLL], [1]) ;; *-*-dragonfly*) - SSHDLIBS="$SSHDLIBS" TEST_MALLOC_OPTIONS="AFGJPRX" ;; *-*-haiku*) @@ -788,7 +806,7 @@ CFLAGS="$CFLAGS -D_BSD_SOURCE" AC_CHECK_LIB([network], [socket]) AC_DEFINE([HAVE_U_INT64_T]) - AC_DEFINE([DISABLE_UTMPX], [1], [no utmpx]) + ssh_disable_utmpx=yes MANTYPE=man ;; *-*-hpux*) @@ -833,19 +851,17 @@ AC_DEFINE([HAVE_SECUREWARE], [1], [Define if you have SecureWare-based protected password database]) - disable_ptmx_check=yes + ac_cv_file__dev_ptmx=disable LIBS="$LIBS -lsecpw" ;; esac ;; *-*-irix5*) PATH="$PATH:/usr/etc" - AC_DEFINE([BROKEN_INET_NTOA], [1], - [Define if you system's inet_ntoa is busted - (e.g. Irix gcc issue)]) + AC_DEFINE([BROKEN_INET_NTOA], [1]) AC_DEFINE([SETEUID_BREAKS_SETUID]) - AC_DEFINE([BROKEN_SETREUID]) - AC_DEFINE([BROKEN_SETREGID]) + AC_DEFINE([BROKEN_SETREUID], [1]) + AC_DEFINE([BROKEN_SETREGID], [1]) AC_DEFINE([WITH_ABBREV_NO_TTY], [1], [Define if you shouldn't strip 'tty' from your ttyname in [uw]tmp]) @@ -862,11 +878,11 @@ [Define if you want IRIX audit trails]) AC_CHECK_FUNC([jlimit_startjob], [AC_DEFINE([WITH_IRIX_JOBS], [1], [Define if you want IRIX kernel jobs])]) - AC_DEFINE([BROKEN_INET_NTOA]) + AC_DEFINE([BROKEN_INET_NTOA], [1]) AC_DEFINE([SETEUID_BREAKS_SETUID]) - AC_DEFINE([BROKEN_SETREUID]) - AC_DEFINE([BROKEN_SETREGID]) - AC_DEFINE([BROKEN_UPDWTMPX], [1], [updwtmpx is broken (if present)]) + AC_DEFINE([BROKEN_SETREUID], [1]) + AC_DEFINE([BROKEN_SETREGID], [1]) + AC_DEFINE([BROKEN_UPDWTMPX], [1]) AC_DEFINE([WITH_ABBREV_NO_TTY]) AC_DEFINE([LOCKED_PASSWD_STRING], ["*LK*"]) ;; @@ -878,14 +894,16 @@ AC_DEFINE([USE_BTMP], [1], [Use btmp to log bad logins]) ;; *-*-linux*) - no_dev_ptmx=1 + case "$host" in + *-*-linux-android*) ;; + *) + ac_cv_file__dev_ptmx=ignore;; + esac use_pie=auto check_for_openpty_ctty_bug=1 dnl Target SUSv3/POSIX.1-2001 plus BSD specifics. dnl _DEFAULT_SOURCE is the new name for _BSD_SOURCE - dnl _GNU_SOURCE is needed for setres*id prototypes. - CPPFLAGS="$CPPFLAGS -D_XOPEN_SOURCE=600 -D_BSD_SOURCE -D_DEFAULT_SOURCE -D_GNU_SOURCE" - AC_DEFINE([BROKEN_CLOSEFROM], [1], [broken in chroots on older kernels]) + CPPFLAGS="$CPPFLAGS -D_XOPEN_SOURCE=600 -D_BSD_SOURCE -D_DEFAULT_SOURCE" AC_DEFINE([PAM_TTY_KLUDGE], [1], [Work around problematic Linux PAM modules handling of PAM_TTY]) AC_DEFINE([LOCKED_PASSWD_PREFIX], ["!"], @@ -894,9 +912,26 @@ AC_DEFINE([LINK_OPNOTSUPP_ERRNO], [EPERM], [Define to whatever link() returns for "not supported" if it doesn't return EOPNOTSUPP.]) + case "$host" in + *-*-linux-android*) ;; + *) AC_DEFINE([_PATH_BTMP], ["/var/log/btmp"], [log for bad login attempts]) AC_DEFINE([USE_BTMP]) + ;; + esac AC_DEFINE([LINUX_OOM_ADJUST], [1], [Adjust Linux out-of-memory killer]) + + case "$host" in + *-*-linux-android*) + LIBS="$LIBS -llog" + XLDFLAGS="$XLDFLAGS -Wl,--wrap=open -Wl,--wrap=fopen" + XLDFLAGS="$XLDFLAGS -Wl,--wrap=rename" + dnl app library stub + XLDFLAGS="$XLDFLAGS -L. -lappinfo" + XDEPLIBS="$XDEPLIBS libappinfo.so" + ;; + esac + inet6_default_4in6=yes case `uname -r` in 1.*|2.0.*) @@ -917,29 +952,25 @@ AC_CHECK_HEADER([linux/if.h], AC_DEFINE([SYS_RDOMAIN_LINUX], [1], [Support routing domains using Linux VRF]), [], [ -#ifdef HAVE_SYS_TYPES_H -# include -#endif + #ifdef HAVE_SYS_TYPES_H + # include + #endif + #include ]) AC_CHECK_HEADERS([linux/seccomp.h linux/filter.h linux/audit.h], [], [], [#include ]) # Obtain MIPS ABI case "$host" in - mips*) - AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ -#if _MIPS_SIM != _ABIO32 -#error -#endif - ]])],[mips_abi="o32"],[AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ + mips64*) + AC_COMPILE_IFELSE([AC_LANG_SOURCE([[ #if _MIPS_SIM != _ABIN32 #error -#endif - ]])],[mips_abi="n32"],[AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ +#endif]]) ], [mips64_abi="n32"], [ + AC_COMPILE_IFELSE([AC_LANG_SOURCE([[ #if _MIPS_SIM != _ABI64 #error -#endif - ]])],[mips_abi="n64"],[AC_MSG_ERROR([unknown MIPS ABI]) - ]) +#endif]]) ], [mips64_abi="n64"], [ + AC_MSG_ERROR([unknown MIPS ABI]) ]) ]) ;; @@ -981,7 +1012,7 @@ seccomp_audit_arch=AUDIT_ARCH_MIPSEL ;; mips64-*) - case "$mips_abi" in + case "$mips64_abi" in "n32") seccomp_audit_arch=AUDIT_ARCH_MIPS64N32 ;; @@ -991,7 +1022,7 @@ esac ;; mips64el-*) - case "$mips_abi" in + case "$mips64_abi" in "n32") seccomp_audit_arch=AUDIT_ARCH_MIPSEL64N32 ;; @@ -1015,17 +1046,13 @@ *-*-minix) AC_DEFINE([SETEUID_BREAKS_SETUID]) # poll(2) seems to choke on /dev/null; "Bad file descriptor" - AC_DEFINE([BROKEN_POLL], [1], - [System poll(2) implementation is broken]) + AC_DEFINE([BROKEN_POLL], [1]) ;; mips-sony-bsd|mips-sony-newsos4) - AC_DEFINE([NEED_SETPGRP], [1], [Need setpgrp to acquire controlling tty]) + AC_DEFINE([NEED_SETPGRP]) SONY=1 ;; *-*-netbsd*) - if test "x$withval" != "xno" ; then - rpath_opt="-R" - fi CPPFLAGS="$CPPFLAGS -D_OPENBSD_SOURCE" AC_DEFINE([SSH_TUN_FREEBSD], [1], [Open tunnel devices the FreeBSD way]) AC_CHECK_HEADER([net/if_tap.h], , @@ -1041,12 +1068,8 @@ AC_DEFINE([SSH_TUN_FREEBSD], [1], [Open tunnel devices the FreeBSD way]) AC_CHECK_HEADER([net/if_tap.h], , AC_DEFINE([SSH_TUN_NO_L2], [1], [No layer 2 tunnel support])) - AC_DEFINE([BROKEN_GLOB], [1], [FreeBSD glob does not do what we need]) + AC_DEFINE([BROKEN_GLOB], [1]) TEST_MALLOC_OPTIONS="AJRX" - # Preauth crypto occasionally uses file descriptors for crypto offload - # and will crash if they cannot be opened. - AC_DEFINE([SANDBOX_SKIP_RLIMIT_NOFILE], [1], - [define if setrlimit RLIMIT_NOFILE breaks things]) case "$host" in *-*-freebsd9.*|*-*-freebsd10.*) # Capsicum on 9 and 10 do not allow ppoll() so don't auto-enable. @@ -1055,8 +1078,8 @@ ;; *-*-bsdi*) AC_DEFINE([SETEUID_BREAKS_SETUID]) - AC_DEFINE([BROKEN_SETREUID]) - AC_DEFINE([BROKEN_SETREGID]) + AC_DEFINE([BROKEN_SETREUID], [1]) + AC_DEFINE([BROKEN_SETREGID], [1]) ;; *-next-*) conf_lastlog_location="/usr/adm/lastlog" @@ -1069,7 +1092,7 @@ ;; *-*-openbsd*) use_pie=auto - AC_DEFINE([HAVE_ATTRIBUTE__SENTINEL__], [1], [OpenBSD's gcc has sentinel]) + dnl AC_DEFINE([HAVE_ATTRIBUTE__SENTINEL__], [1], [OpenBSD's gcc has sentinel]) AC_DEFINE([HAVE_ATTRIBUTE__BOUNDED__], [1], [OpenBSD's gcc has bounded]) AC_DEFINE([SSH_TUN_OPENBSD], [1], [Open tunnel devices the OpenBSD way]) AC_DEFINE([SYSLOG_R_SAFE_IN_SIGHAND], [1], @@ -1077,9 +1100,6 @@ TEST_MALLOC_OPTIONS="AFGJPRX" ;; *-*-solaris*) - if test "x$withval" != "xno" ; then - rpath_opt="-R" - fi AC_DEFINE([PAM_SUN_CODEBASE]) AC_DEFINE([LOGIN_NEEDS_UTMPX]) AC_DEFINE([PAM_TTY_KLUDGE]) @@ -1088,12 +1108,10 @@ to the unpriv'ed user]) AC_DEFINE([LOCKED_PASSWD_STRING], ["*LK*"]) # Pushing STREAMS modules will cause sshd to acquire a controlling tty. - AC_DEFINE([SSHD_ACQUIRES_CTTY], [1], - [Define if sshd somehow reacquires a controlling TTY - after setsid()]) + AC_DEFINE([SSHD_ACQUIRES_CTTY], [1]) AC_DEFINE([PASSWD_NEEDS_USERNAME], [1], [must supply username to passwd in case the name is longer than 8 chars]) - AC_DEFINE([BROKEN_TCGETATTR_ICANON], [1], [tcgetattr with ICANON may hang]) + AC_DEFINE([BROKEN_TCGETATTR_ICANON], [1]) external_path_file=/etc/default/login # hardwire lastlog location (can't detect it on some versions) conf_lastlog_location="/var/adm/lastlog" @@ -1150,7 +1168,6 @@ fi ], ) - TEST_SHELL=$SHELL # let configure find us a capable shell ;; *-*-sunos4*) CPPFLAGS="$CPPFLAGS -DSUNOS4" @@ -1160,15 +1177,15 @@ conf_wtmp_location=/var/adm/wtmp conf_lastlog_location=/var/adm/lastlog AC_DEFINE([USE_PIPES]) - AC_DEFINE([DISABLE_UTMPX], [1], [no utmpx]) + ssh_disable_utmpx=yes ;; *-ncr-sysv*) LIBS="$LIBS -lc89" AC_DEFINE([USE_PIPES]) - AC_DEFINE([SSHD_ACQUIRES_CTTY]) + AC_DEFINE([SSHD_ACQUIRES_CTTY], [1]) AC_DEFINE([SETEUID_BREAKS_SETUID]) - AC_DEFINE([BROKEN_SETREUID]) - AC_DEFINE([BROKEN_SETREGID]) + AC_DEFINE([BROKEN_SETREUID], [1]) + AC_DEFINE([BROKEN_SETREGID], [1]) ;; *-sni-sysv*) # /usr/ucblib MUST NOT be searched on ReliantUNIX @@ -1179,9 +1196,9 @@ AC_DEFINE([USE_PIPES]) AC_DEFINE([IP_TOS_IS_BROKEN]) AC_DEFINE([SETEUID_BREAKS_SETUID]) - AC_DEFINE([BROKEN_SETREUID]) - AC_DEFINE([BROKEN_SETREGID]) - AC_DEFINE([SSHD_ACQUIRES_CTTY]) + AC_DEFINE([BROKEN_SETREUID], [1]) + AC_DEFINE([BROKEN_SETREGID], [1]) + AC_DEFINE([SSHD_ACQUIRES_CTTY], [1]) external_path_file=/etc/default/login # /usr/ucblib/libucb.a no longer needed on ReliantUNIX # Attention: always take care to bind libsocket and libnsl before libc, @@ -1191,11 +1208,10 @@ *-*-sysv4.2*) AC_DEFINE([USE_PIPES]) AC_DEFINE([SETEUID_BREAKS_SETUID]) - AC_DEFINE([BROKEN_SETREUID]) - AC_DEFINE([BROKEN_SETREGID]) + AC_DEFINE([BROKEN_SETREUID], [1]) + AC_DEFINE([BROKEN_SETREGID], [1]) AC_DEFINE([PASSWD_NEEDS_USERNAME], [1], [must supply username to passwd]) AC_DEFINE([LOCKED_PASSWD_STRING], ["*LK*"]) - TEST_SHELL=$SHELL # let configure find us a capable shell ;; # UnixWare 7.x, OpenUNIX 8 *-*-sysv5*) @@ -1203,16 +1219,15 @@ AC_DEFINE([UNIXWARE_LONG_PASSWORDS], [1], [Support passwords > 8 chars]) AC_DEFINE([USE_PIPES]) AC_DEFINE([SETEUID_BREAKS_SETUID]) - AC_DEFINE([BROKEN_GETADDRINFO]) - AC_DEFINE([BROKEN_SETREUID]) - AC_DEFINE([BROKEN_SETREGID]) + AC_DEFINE([BROKEN_GETADDRINFO], [1]) + AC_DEFINE([BROKEN_SETREUID], [1]) + AC_DEFINE([BROKEN_SETREGID], [1]) AC_DEFINE([PASSWD_NEEDS_USERNAME]) - AC_DEFINE([BROKEN_TCGETATTR_ICANON]) - TEST_SHELL=$SHELL # let configure find us a capable shell + AC_DEFINE([BROKEN_TCGETATTR_ICANON], [1]) case "$host" in *-*-sysv5SCO_SV*) # SCO OpenServer 6.x maildir=/var/spool/mail - AC_DEFINE([BROKEN_UPDWTMPX]) + AC_DEFINE([BROKEN_UPDWTMPX], [1]) AC_CHECK_LIB([prot], [getluid], [ LIBS="$LIBS -lprot" AC_CHECK_FUNCS([getluid setluid], , , [-lprot]) ], , ) @@ -1229,25 +1244,24 @@ ;; # SCO OpenServer 5.x *-*-sco3.2v5*) + ac_cv_file__dev_ptmx=ignore if test -z "$GCC"; then CFLAGS="$CFLAGS -belf" fi LIBS="$LIBS -lprot -lx -ltinfo -lm" - no_dev_ptmx=1 AC_DEFINE([USE_PIPES]) AC_DEFINE([HAVE_SECUREWARE]) AC_DEFINE([DISABLE_SHADOW]) AC_DEFINE([DISABLE_FD_PASSING]) AC_DEFINE([SETEUID_BREAKS_SETUID]) - AC_DEFINE([BROKEN_GETADDRINFO]) - AC_DEFINE([BROKEN_SETREUID]) - AC_DEFINE([BROKEN_SETREGID]) + AC_DEFINE([BROKEN_GETADDRINFO], [1]) + AC_DEFINE([BROKEN_SETREUID], [1]) + AC_DEFINE([BROKEN_SETREGID], [1]) AC_DEFINE([WITH_ABBREV_NO_TTY]) - AC_DEFINE([BROKEN_UPDWTMPX]) + AC_DEFINE([BROKEN_UPDWTMPX], [1]) AC_DEFINE([PASSWD_NEEDS_USERNAME]) AC_CHECK_FUNCS([getluid setluid]) MANTYPE=man - TEST_SHELL=$SHELL # let configure find us a capable shell SKIP_DISABLE_LASTLOG_DEFINE=yes ;; *-dec-osf*) @@ -1280,10 +1294,10 @@ [String used in /etc/passwd to denote locked account]) fi fi - AC_DEFINE([BROKEN_GETADDRINFO]) + AC_DEFINE([BROKEN_GETADDRINFO], [1]) AC_DEFINE([SETEUID_BREAKS_SETUID]) - AC_DEFINE([BROKEN_SETREUID]) - AC_DEFINE([BROKEN_SETREGID]) + AC_DEFINE([BROKEN_SETREUID], [1]) + AC_DEFINE([BROKEN_SETREGID], [1]) AC_DEFINE([BROKEN_READV_COMPARISON], [1], [Can't do comparisons on readv]) ;; @@ -1291,7 +1305,7 @@ AC_DEFINE([USE_PIPES]) AC_DEFINE([NO_X11_UNIX_SOCKETS]) AC_DEFINE([DISABLE_LASTLOG]) - AC_DEFINE([SSHD_ACQUIRES_CTTY]) + AC_DEFINE([SSHD_ACQUIRES_CTTY], [1]) AC_DEFINE([BROKEN_SHADOW_EXPIRE], [1], [QNX shadow support is broken]) enable_etc_default_login=no # has incompatible /etc/default/login case "$host" in @@ -1303,12 +1317,10 @@ *-*-ultrix*) AC_DEFINE([BROKEN_GETGROUPS], [1], [getgroups(0,NULL) will return -1]) - AC_DEFINE([NEED_SETPGRP], [1], [Need setpgrp to for controlling tty]) + AC_DEFINE([NEED_SETPGRP]) AC_DEFINE([HAVE_SYS_SYSLOG_H], [1], [Force use of sys/syslog.h on Ultrix]) - AC_DEFINE([DISABLE_UTMPX], [1], [Disable utmpx]) - # DISABLE_FD_PASSING so that we call setpgrp as root, otherwise we - # don't get a controlling tty. - AC_DEFINE([DISABLE_FD_PASSING], [1], [Need to call setpgrp as root]) + ssh_disable_utmpx=yes + AC_DEFINE([DISABLE_FD_PASSING]) # On Ultrix some headers are not protected against multiple includes, # so we create wrappers and put it where the compiler will find it. AC_MSG_WARN([creating compat wrappers for headers]) @@ -1331,8 +1343,12 @@ ;; esac +# let configure find us a capable shell +AC_SUBST([TEST_SHELL], [$SHELL]) + + AC_MSG_CHECKING([compiler and flags for sanity]) -AC_RUN_IFELSE([AC_LANG_PROGRAM([[ #include ]], [[ exit(0); ]])], +AC_RUN_IFELSE([AC_LANG_PROGRAM([[]], [[]])], [ AC_MSG_RESULT([yes]) ], [ AC_MSG_RESULT([no]) @@ -1353,22 +1369,16 @@ save_LIBS="$LIBS" LIBS="$LIBS -lgen" AC_RUN_IFELSE( - [AC_LANG_SOURCE([[ + [AC_LANG_PROGRAM([[ #include #include -#include - -int main(int argc, char **argv) { + ]], [[ char *s, buf[32]; strncpy(buf,"/etc", 32); s = dirname(buf); - if (!s || strncmp(s, "/", 32) != 0) { - exit(1); - } else { - exit(0); - } -} + if (s == NULL || strncmp(s, "/", 32) != 0) + return 1; ]])], [ ac_cv_have_broken_dirname="no" ], [ ac_cv_have_broken_dirname="yes" ], @@ -1390,11 +1400,12 @@ [Define if you have the basename function.])]) dnl zlib defaults to enabled -zlib=yes +ZLIB_MSG=yes AC_ARG_WITH([zlib], - [ --with-zlib=PATH Use zlib in PATH], + [AS_HELP_STRING([--with-zlib@<:@=PATH@:>@], + [Use zlib for compression(optionally in PATH)])], [ if test "x$withval" = "xno" ; then - zlib=no + ZLIB_MSG=no elif test "x$withval" != "xyes"; then if test -d "$withval/lib"; then if test -n "${rpath_opt}"; then @@ -1417,21 +1428,18 @@ fi ] ) -# These libraries are needed for anything that links in the channel code. -CHANNELLIBS="" AC_MSG_CHECKING([for zlib]) -if test "x${zlib}" = "xno"; then +if test "x$ZLIB_MSG" = "xno"; then AC_MSG_RESULT([no]) else - saved_LIBS="$LIBS" - CHANNELLIBS="$CHANNELLIBS -lz" - AC_MSG_RESULT([yes]) - AC_DEFINE([WITH_ZLIB], [1], [Enable zlib]) + AC_MSG_RESULT([yes]) + AC_DEFINE([WITH_ZLIB], [1], [Enable zlib]) AC_CHECK_HEADER([zlib.h], ,[AC_MSG_ERROR([*** zlib.h missing - please install first or check config.log ***])]) - AC_CHECK_LIB([z], [deflate], [], + AC_CHECK_LIB([z], [deflate], , [ saved_CPPFLAGS="$CPPFLAGS" saved_LDFLAGS="$LDFLAGS" + save_LIBS="$LIBS" dnl Check default zlib install dir if test -n "${rpath_opt}"; then LDFLAGS="-L/usr/local/lib ${rpath_opt}/usr/local/lib ${saved_LDFLAGS}" @@ -1439,6 +1447,7 @@ LDFLAGS="-L/usr/local/lib ${saved_LDFLAGS}" fi CPPFLAGS="-I/usr/local/include ${saved_CPPFLAGS}" + LIBS="$LIBS -lz" AC_TRY_LINK_FUNC([deflate], [AC_DEFINE([HAVE_LIBZ])], [ AC_MSG_ERROR([*** zlib missing - please install first or check config.log ***]) @@ -1458,26 +1467,23 @@ AC_MSG_CHECKING([for possibly buggy zlib]) AC_RUN_IFELSE([AC_LANG_PROGRAM([[ #include -#include #include ]], [[ int a=0, b=0, c=0, d=0, n, v; n = sscanf(ZLIB_VERSION, "%d.%d.%d.%d", &a, &b, &c, &d); - if (n != 3 && n != 4) - exit(1); + if (n < 1) + return 1; v = a*1000000 + b*10000 + c*100 + d; fprintf(stderr, "found zlib version %s (%d)\n", ZLIB_VERSION, v); /* 1.1.4 is OK */ if (a == 1 && b == 1 && c >= 4) - exit(0); + return 0; /* 1.2.3 and up are OK */ - if (v >= 1020300) - exit(0); - - exit(2); + if (v < 1020300) + return 2; ]])], AC_MSG_RESULT([no]), [ AC_MSG_RESULT([yes]) @@ -1488,14 +1494,13 @@ are sure this is the case, you can disable the check by running "./configure --without-zlib-version-check". If you are in doubt, upgrade zlib to version 1.2.3 or greater. -See http://www.gzip.org/zlib/ for details.]) +See https://zlib.net/ for details.]) else AC_MSG_WARN([zlib version may have security problems]) fi ], [ AC_MSG_WARN([cross compiling: not checking zlib version]) ] ) - LIBS="$saved_LIBS" fi dnl UnixWare 2.x @@ -1518,41 +1523,76 @@ AC_SEARCH_LIBS([updwtmp], [util bsd]) AC_CHECK_FUNCS([fmt_scaled scan_scaled login logout openpty updwtmp logwtmp]) +dnl check for constant openpty arguments +ssh_openpty_args=const +AS_IF([test $ac_cv_func_openpty != no], [ + AC_MSG_CHECKING([whether openpty declare const arguments]) + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ +#include +#include +#ifdef HAVE_PTY_H +# include +#endif +#ifdef HAVE_STDDEF_H +# include +#endif +int openpty( + int *amaster, int *aslave, char *name, + const struct termios *termp, const struct winsize *winp +) { +(void)amaster; (void)aslave; (void)name; +(void)termp; (void)winp; +return 0; } + ]], [[ +int ptyfd = 1, ttyfd = 2; +(void)openpty(&ptyfd, &ttyfd, NULL, NULL, NULL); + ]])], + [ AC_MSG_RESULT([yes]) ], + [ AC_MSG_RESULT([no]) + ssh_openpty_args= ] + ) +]) +AC_DEFINE_UNQUOTED([OPENPTY_CONST_ARG], [$ssh_openpty_args], + [Define as const if openpty declare const arguments]) + # On some platforms, inet_ntop and gethostbyname may be found in libresolv # or libnsl. AC_SEARCH_LIBS([inet_ntop], [resolv nsl]) AC_SEARCH_LIBS([gethostbyname], [resolv nsl]) -# Some Linux distribtions ship the BSD libc hashing functions in -# separate libraries. -AC_SEARCH_LIBS([SHA256Update], [md bsd]) - # "Particular Function Checks" # see https://www.gnu.org/software/autoconf/manual/autoconf-2.69/html_node/Particular-Functions.html AC_FUNC_STRFTIME AC_FUNC_MALLOC AC_FUNC_REALLOC # autoconf doesn't have AC_FUNC_CALLOC so fake it if malloc returns NULL; -AC_MSG_CHECKING([if calloc(0, N) returns non-null]) +AC_CACHE_CHECK([if calloc(0, N) returns non-null], + [ssh_cv_func_calloc_0_nonnull], AC_RUN_IFELSE( - [AC_LANG_PROGRAM( - [[ #include ]], - [[ void *p = calloc(0, 1); exit(p == NULL); ]] - )], - [ func_calloc_0_nonnull=yes ], - [ func_calloc_0_nonnull=no ], - [ AC_MSG_WARN([cross compiling: assuming same as malloc]) - func_calloc_0_nonnull="$ac_cv_func_malloc_0_nonnull"] + [AC_LANG_PROGRAM([[ +#include + ]], [[ + void *p = calloc(0, 1); + if (p == NULL) return 1; + ]])], + [ ssh_cv_func_calloc_0_nonnull=yes ], + [ ssh_cv_func_calloc_0_nonnull=no ], + [ ssh_cv_func_calloc_0_nonnull=cross ] ) -AC_MSG_RESULT([$func_calloc_0_nonnull]) - -if test "x$func_calloc_0_nonnull" = "xyes"; then - AC_DEFINE(HAVE_CALLOC, 1, [calloc(0, x) returns non-null]) -else - AC_DEFINE(HAVE_CALLOC, 0, [calloc(0, x) returns NULL]) +) +if test $ssh_cv_func_calloc_0_nonnull = cross ; then + AC_MSG_WARN([cross compiling: assuming calloc(0, N) returns non-null same as malloc]) + ssh_cv_func_calloc_0_nonnull=$ac_cv_func_malloc_0_nonnull +fi +AS_IF([test $ssh_cv_func_calloc_0_nonnull = yes], [ + AC_DEFINE([HAVE_CALLOC], 1, + [Define to 1 if your system function calloc(0, x) + returns non-null, and to 0 otherwise.]) +], [ + AC_DEFINE([HAVE_CALLOC], 0) AC_DEFINE(calloc, rpl_calloc, [Define to rpl_calloc if the replacement function should be used.]) -fi +]) # Check for ALTDIRFUNC glob() extension AC_MSG_CHECKING([for GLOB_ALTDIRFUNC support]) @@ -1589,13 +1629,16 @@ # Check for g.gl_statv glob() extension AC_MSG_CHECKING([for gl_statv and GLOB_KEEPSTAT extensions for glob]) -AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include ]], [[ +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ +#include +#include + ]], [[ #ifndef GLOB_KEEPSTAT #error "glob does not support GLOB_KEEPSTAT extension" #endif glob_t g; g.gl_statv = NULL; -]])], + ]])], [ AC_DEFINE([GLOB_HAS_GL_STATV], [1], [Define if your system glob() function has @@ -1611,29 +1654,31 @@ AC_CHECK_DECL([VIS_ALL], , AC_DEFINE(BROKEN_STRNVIS, 1, [missing VIS_ALL]), [#include ]) -AC_MSG_CHECKING([whether struct dirent allocates space for d_name]) +AC_CACHE_CHECK([whether struct dirent allocates space for d_name], + [ssh_cv_dirent_allocates_space_for_d_name],[ AC_RUN_IFELSE( [AC_LANG_PROGRAM([[ #include -#include -#include - ]], +#include ]], [[ struct dirent d; - exit(sizeof(d.d_name)<=sizeof(char)); + if (sizeof(d.d_name) <= sizeof(char)) + return 1; ]])], - [AC_MSG_RESULT([yes])], - [ - AC_MSG_RESULT([no]) - AC_DEFINE([BROKEN_ONE_BYTE_DIRENT_D_NAME], [1], - [Define if your struct dirent expects you to - allocate extra space for d_name]) - ], - [ - AC_MSG_WARN([cross compiling: assuming BROKEN_ONE_BYTE_DIRENT_D_NAME]) - AC_DEFINE([BROKEN_ONE_BYTE_DIRENT_D_NAME]) - ] + [ssh_cv_dirent_allocates_space_for_d_name=yes], + [ssh_cv_dirent_allocates_space_for_d_name=no], + [ssh_cv_dirent_allocates_space_for_d_name=cross] ) +]) +case $ssh_cv_dirent_allocates_space_for_d_name in + no) + AC_DEFINE([BROKEN_ONE_BYTE_DIRENT_D_NAME], [1]) + ;; + cross) + AC_MSG_WARN([cross compiling: assuming BROKEN_ONE_BYTE_DIRENT_D_NAME]) + AC_DEFINE([BROKEN_ONE_BYTE_DIRENT_D_NAME], [1]) + ;; +esac AC_MSG_CHECKING([for /proc/pid/fd directory]) if test -d "/proc/$$/fd" ; then @@ -1643,52 +1688,99 @@ AC_MSG_RESULT([no]) fi +# Check whether user wants TCP wrappers support +TCPW_MSG="no" +AC_ARG_WITH([tcp-wrappers], + [AS_HELP_STRING([--with-tcp-wrappers@<:@=PATH@:>@], + [Enable tcpwrappers support (optionally in PATH)])], + [AS_IF([test "x$withval" != "xno"],[ + saved_LIBS="$LIBS" + saved_LDFLAGS="$LDFLAGS" + saved_CPPFLAGS="$CPPFLAGS" + + AS_IF([test -n "${withval}" && \ + test "x${withval}" != "xyes"], [ + AS_IF([test -d "${withval}/lib"], [ + if test -n "${need_dash_r}"; then + LDFLAGS="-L${withval}/lib -R${withval}/lib ${LDFLAGS}" + else + LDFLAGS="-L${withval}/lib ${LDFLAGS}" + fi + ], [ + if test -n "${need_dash_r}"; then + LDFLAGS="-L${withval} -R${withval} ${LDFLAGS}" + else + LDFLAGS="-L${withval} ${LDFLAGS}" + fi + ]) + AS_IF([test -d "${withval}/include"], [ + CPPFLAGS="-I${withval}/include ${CPPFLAGS}" + ], [ + CPPFLAGS="-I${withval} ${CPPFLAGS}" + ]) + ]) + + AC_MSG_CHECKING([how to link with wrap library]) + # libwrap may require libnsl + for WRAPLIBS in "-lwrap" "-lwrap -lnsl"; do + LIBS="$WRAPLIBS $saved_LIBS" + AC_LINK_IFELSE([AC_LANG_PROGRAM([[ +#include +#include +#include +#include +int deny_severity = 0, allow_severity = 0;]], [[ + hosts_access(0);]] + )], [ + TCPW_MSG=yes + ]) + test $TCPW_MSG = yes && break + done + + if test $TCPW_MSG = yes; then + AC_MSG_RESULT([$WRAPLIBS]) + AC_DEFINE([LIBWRAP], [1], + [Define if you want TCP Wrappers support]) + SSHDLIBS="$SSHDLIBS $WRAPLIBS" + else + AC_MSG_ERROR([cannot link]) + fi + + LIBS="$saved_LIBS" + ])] +) + # Check whether user wants to use ldns LDNS_MSG="no" AC_ARG_WITH(ldns, - [ --with-ldns[[=PATH]] Use ldns for DNSSEC support (optionally in PATH)], - [ - ldns="" - if test "x$withval" = "xyes" ; then - AC_PATH_TOOL([LDNSCONFIG], [ldns-config], [no]) - if test "x$LDNSCONFIG" = "xno"; then - LIBS="-lldns $LIBS" - ldns=yes - else - LIBS="$LIBS `$LDNSCONFIG --libs`" - CPPFLAGS="$CPPFLAGS `$LDNSCONFIG --cflags`" - ldns=yes + [AS_HELP_STRING([--with-ldns@<:@=PATH@:>@], + [Use ldns for DNSSEC support (optionally in PATH)])], +[ + if test "x$withval" != "xno" ; then + if test "x$withval" != "xyes" ; then + CPPFLAGS="$CPPFLAGS -I$withval/include" + LDFLAGS="$LDFLAGS -L$withval/lib" fi - elif test "x$withval" != "xno" ; then - CPPFLAGS="$CPPFLAGS -I${withval}/include" - LDFLAGS="$LDFLAGS -L${withval}/lib" - LIBS="-lldns $LIBS" - ldns=yes - fi - - # Verify that it works. - if test "x$ldns" = "xyes" ; then - AC_DEFINE(HAVE_LDNS, 1, [Define if you want ldns support]) + LIBS="-lldns $LIBS" LDNS_MSG="yes" - AC_MSG_CHECKING([for ldns support]) - AC_LINK_IFELSE( - [AC_LANG_SOURCE([[ -#include -#include -#ifdef HAVE_STDINT_H -# include -#endif -#include -int main(void) { ldns_status status = ldns_verify_trusted(NULL, NULL, NULL, NULL); status=LDNS_STATUS_OK; exit(0); } - ]]) - ], - [AC_MSG_RESULT(yes)], - [ - AC_MSG_RESULT(no) - AC_MSG_ERROR([** Incomplete or missing ldns libraries.]) - ]) fi ]) +# Verify that ldns works. +if test "x$LDNS_MSG" = "xyes" ; then + AC_MSG_CHECKING([for ldns support]) + AC_LINK_IFELSE([AC_LANG_PROGRAM([[ +#include + ]],[[ + ldns_status status = ldns_verify_trusted(NULL, NULL, NULL, NULL); + status = LDNS_STATUS_OK; + ]])], + [AC_MSG_RESULT(yes)], + [ + AC_MSG_RESULT(no) + AC_MSG_ERROR([** Incomplete or missing ldns libraries.]) + ]) + AC_DEFINE(HAVE_LDNS, 1, [Define if you want ldns support]) +fi # Check whether user wants libedit support LIBEDIT_MSG="no" @@ -1732,12 +1824,9 @@ AC_COMPILE_IFELSE( [AC_LANG_PROGRAM([[ #include -#include - ]], - [[ + ]], [[ int i = H_SETSIZE; el_init("", NULL, NULL, NULL); - exit(0); ]])], [ AC_MSG_RESULT([yes]) ], [ AC_MSG_RESULT([no]) @@ -1812,7 +1901,7 @@ if test "x$use_pie" = "x"; then use_pie=no fi -if test "x$use_toolchain_hardening" != "x1" && test "x$use_pie" = "xauto"; then +if $use_toolchain_hardening && test "x$use_pie" = "xauto"; then # Turn off automatic PIE when toolchain hardening is off. use_pie=no fi @@ -1846,18 +1935,6 @@ fi fi -AC_MSG_CHECKING([whether -fPIC is accepted]) -SAVED_CFLAGS="$CFLAGS" -CFLAGS="$CFLAGS -fPIC" -AC_COMPILE_IFELSE( - [AC_LANG_PROGRAM( [[ #include ]], [[ exit(0); ]] )], - [AC_MSG_RESULT([yes]) - PICFLAG="-fPIC"; ], - [AC_MSG_RESULT([no]) - PICFLAG=""; ]) -CFLAGS="$SAVED_CFLAGS" -AC_SUBST([PICFLAG]) - dnl Checks for library functions. Please keep in alphabetical order AC_CHECK_FUNCS([ \ Blowfish_initstate \ @@ -1872,11 +1949,9 @@ __b64_ntop \ b64_pton \ __b64_pton \ - bcopy \ bcrypt_pbkdf \ bindresvport_sa \ blf_enc \ - bzero \ cap_rights_limit \ clock \ closefrom \ @@ -1902,6 +1977,7 @@ getcwd \ getentropy \ getgrouplist \ + getifaddrs \ getline \ getnameinfo \ getopt \ @@ -1921,10 +1997,10 @@ inet_ntop \ innetgr \ killpg \ - llabs \ localtime_r \ login_getcapbool \ login_getpwclass \ + md5_crypt \ memmem \ memmove \ memset_s \ @@ -1943,7 +2019,6 @@ raise \ readpassphrase \ reallocarray \ - realpath \ recvmsg \ recallocarray \ rresvport_af \ @@ -2002,7 +2077,26 @@ warn \ ]) -AC_CHECK_DECLS([bzero, memmem]) +dnl Note in GNU C-library memmem requires definition of _GNU_SOURCE. +dnl It is not defined yet by configuration, but is defined in common +dnl header "includes.h". +saved_CPPFLAGS="$CPPFLAGS" +CPPFLAGS="$CPPFLAGS -D_GNU_SOURCE" +AC_CHECK_DECLS([memmem]) +dnl Function memmem_s, if defined, conforms to c11 and could be +dnl declared under some conditions. +AC_CHECK_DECLS([memset_s]) +AS_IF([test $ac_cv_func_endgrent != no], [ + AC_CHECK_DECLS([endgrent], [], [], [ +#include +#include + ]) +]) +AC_CHECK_DECLS([endpwent], [], [], [ +#include +#include +]) +CPPFLAGS="$saved_CPPFLAGS" dnl Wide character support. AC_CHECK_FUNCS([mblen mbtowc nl_langinfo wcwidth]) @@ -2012,12 +2106,9 @@ AC_RUN_IFELSE( [AC_LANG_PROGRAM([[ #include -#include ]], [[ char *loc = setlocale(LC_CTYPE, "en_US.UTF-8"); - if (loc != NULL) - exit(0); - exit(1); + if (loc == NULL) return 1; ]])], AC_MSG_RESULT(yes), [AC_MSG_RESULT(no) @@ -2032,34 +2123,15 @@ [AC_DEFINE([HAVE_ISBLANK], [1], [Define if you have isblank(3C).]) ]) -disable_pkcs11= +PKCS11_MSG=yes AC_ARG_ENABLE([pkcs11], - [ --disable-pkcs11 disable PKCS#11 support code [no]], - [ - if test "x$enableval" = "xno" ; then - disable_pkcs11=1 - fi - ] -) - -disable_sk= -AC_ARG_ENABLE([security-key], - [ --disable-security-key disable U2F/FIDO support code [no]], + [AS_HELP_STRING([--disable-pkcs11], [disable PKCS#11 support code @<:@=no@:>@])], [ if test "x$enableval" = "xno" ; then - disable_sk=1 + PKCS11_MSG=no fi ] ) -enable_sk_internal= -AC_ARG_WITH([security-key-builtin], - [ --with-security-key-builtin include builtin U2F/FIDO support], - [ enable_sk_internal=$withval ] -) - -AC_SEARCH_LIBS([dlopen], [dl]) -AC_CHECK_FUNCS([dlopen]) -AC_CHECK_DECL([RTLD_NOW], [], [], [#include ]) # IRIX has a const char return value for gai_strerror() AC_CHECK_FUNCS([gai_strerror], [ @@ -2133,7 +2205,7 @@ #endif ]) -AC_CHECK_DECLS([ftruncate, getentropy], , , +AC_CHECK_DECLS([ftruncate], , , [ #include #include @@ -2166,9 +2238,7 @@ #ifdef HAVE_SYS_TIME_H #include #endif -#ifdef HAVE_UNISTD_H #include -#endif ]]) AC_CHECK_TYPES([fd_mask], [], [], [[ #include @@ -2179,78 +2249,83 @@ #ifdef HAVE_SYS_TIME_H #include #endif -#ifdef HAVE_UNISTD_H #include -#endif ]]) AC_CHECK_FUNCS([setresuid], [ dnl Some platorms have setresuid that isn't implemented, test for this - AC_MSG_CHECKING([if setresuid seems to work]) - AC_RUN_IFELSE( - [AC_LANG_PROGRAM([[ -#include -#include +AC_CACHE_CHECK( + [if setresuid seems to work], + [ssh_cv_func_setresuid_work], + [AC_RUN_IFELSE([AC_LANG_PROGRAM([[ +#define _GNU_SOURCE #include - ]], [[ - errno=0; - setresuid(0,0,0); - if (errno==ENOSYS) - exit(1); - else - exit(0); - ]])], - [AC_MSG_RESULT([yes])], - [AC_DEFINE([BROKEN_SETRESUID], [1], - [Define if your setresuid() is broken]) - AC_MSG_RESULT([not implemented])], - [AC_MSG_WARN([cross compiling: not checking setresuid])] - ) +#include + ]], [[ +errno=0; +setresuid(0,0,0); +if (errno==ENOSYS) return 1; + ]])], + [ssh_cv_func_setresuid_work=yes], + [ssh_cv_func_setresuid_work=no], + [ssh_cv_func_setresuid_work=cross] +)]) +AS_IF([test $ssh_cv_func_setresuid_work = cross], [ + AC_MSG_WARN([cross compiling: assuming working setresuid]) + ssh_cv_func_setresuid_work=yes +]) +AS_IF([test $ssh_cv_func_setresuid_work != yes], [ + AC_DEFINE([BROKEN_SETRESUID], [1], + [Define if your setresuid() is broken]) +]) ]) AC_CHECK_FUNCS([setresgid], [ dnl Some platorms have setresgid that isn't implemented, test for this - AC_MSG_CHECKING([if setresgid seems to work]) - AC_RUN_IFELSE( - [AC_LANG_PROGRAM([[ -#include -#include +AC_CACHE_CHECK( + [if setresgid seems to work], + [ssh_cv_func_setresgid_work], + [AC_RUN_IFELSE([AC_LANG_PROGRAM([[ +#define _GNU_SOURCE #include - ]], [[ - errno=0; - setresgid(0,0,0); - if (errno==ENOSYS) - exit(1); - else - exit(0); - ]])], - [AC_MSG_RESULT([yes])], - [AC_DEFINE([BROKEN_SETRESGID], [1], - [Define if your setresgid() is broken]) - AC_MSG_RESULT([not implemented])], - [AC_MSG_WARN([cross compiling: not checking setresuid])] - ) +#include + ]], [[ +errno=0; +setresgid(0,0,0); +if (errno==ENOSYS) return 1; + ]])], + [ssh_cv_func_setresgid_work=yes], + [ssh_cv_func_setresgid_work=no], + [ssh_cv_func_setresgid_work=cross] +)]) +AS_IF([test $ssh_cv_func_setresgid_work = cross], [ + AC_MSG_WARN([cross compiling: assuming working setresgid]) + ssh_cv_func_setresgid_work=yes +]) +AS_IF([test $ssh_cv_func_setresgid_work != yes], [ + AC_DEFINE([BROKEN_SETRESGID], [1], + [Define if your setresgid() is broken]) +]) ]) -AC_MSG_CHECKING([for working fflush(NULL)]) +AC_CACHE_CHECK([for working fflush(NULL)], [ssh_cv_func_fflush_null], [ AC_RUN_IFELSE( - [AC_LANG_PROGRAM([[ -#include -#include - ]], - [[fflush(NULL); exit(0);]])], - AC_MSG_RESULT([yes]), - [AC_MSG_RESULT([no]) + [AC_LANG_PROGRAM([[#include ]], [[fflush(NULL);]])], + [ ssh_cv_func_fflush_null=yes ], + [ ssh_cv_func_fflush_null=no ], + [ ssh_cv_func_fflush_null=cross ] +)]) +if test $ssh_cv_func_fflush_null = cross ; then + AC_MSG_WARN([cross compiling: assuming working fflush(NULL)]) + ssh_cv_func_fflush_null=yes +fi +if test $ssh_cv_func_fflush_null != yes ; then AC_DEFINE([FFLUSH_NULL_BUG], [1], [define if fflush(NULL) does not work])], - AC_MSG_WARN([cross compiling: assuming working]) -) +fi dnl Checks for time functions AC_CHECK_FUNCS([gettimeofday time]) -dnl Checks for utmp functions -AC_CHECK_FUNCS([endutent getutent getutid getutline pututline setutent]) -AC_CHECK_FUNCS([utmpname]) dnl Checks for utmpx functions AC_CHECK_FUNCS([endutxent getutxent getutxid getutxline getutxuser pututxline]) AC_CHECK_FUNCS([setutxdb setutxent utmpxname]) @@ -2270,110 +2345,6 @@ [LIBS="$LIBS -lucb"; AC_DEFINE([HAVE_GETPAGESIZE])])] ) -# Check for broken snprintf -if test "x$ac_cv_func_snprintf" = "xyes" ; then - AC_MSG_CHECKING([whether snprintf correctly terminates long strings]) - AC_RUN_IFELSE( - [AC_LANG_PROGRAM([[ -#include -#include - ]], - [[ - char b[5]; - snprintf(b,5,"123456789"); - exit(b[4]!='\0'); - ]])], - [AC_MSG_RESULT([yes])], - [ - AC_MSG_RESULT([no]) - AC_DEFINE([BROKEN_SNPRINTF], [1], - [Define if your snprintf is busted]) - AC_MSG_WARN([****** Your snprintf() function is broken, complain to your vendor]) - ], - [ AC_MSG_WARN([cross compiling: Assuming working snprintf()]) ] - ) -fi - -if test "x$ac_cv_func_snprintf" = "xyes" ; then - AC_MSG_CHECKING([whether snprintf understands %zu]) - AC_RUN_IFELSE( - [AC_LANG_PROGRAM([[ -#include -#include -#include -#include - ]], - [[ - size_t a = 1, b = 2; - char z[128]; - snprintf(z, sizeof z, "%zu%zu", a, b); - exit(strcmp(z, "12")); - ]])], - [AC_MSG_RESULT([yes])], - [ - AC_MSG_RESULT([no]) - AC_DEFINE([BROKEN_SNPRINTF], [1], - [snprintf does not understand %zu]) - ], - [ AC_MSG_WARN([cross compiling: Assuming working snprintf()]) ] - ) -fi - -# We depend on vsnprintf returning the right thing on overflow: the -# number of characters it tried to create (as per SUSv3) -if test "x$ac_cv_func_vsnprintf" = "xyes" ; then - AC_MSG_CHECKING([whether vsnprintf returns correct values on overflow]) - AC_RUN_IFELSE( - [AC_LANG_PROGRAM([[ -#include -#include -#include - -int x_snprintf(char *str, size_t count, const char *fmt, ...) -{ - size_t ret; - va_list ap; - - va_start(ap, fmt); - ret = vsnprintf(str, count, fmt, ap); - va_end(ap); - return ret; -} - ]], [[ -char x[1]; -if (x_snprintf(x, 1, "%s %d", "hello", 12345) != 11) - return 1; -if (x_snprintf(NULL, 0, "%s %d", "hello", 12345) != 11) - return 1; -return 0; - ]])], - [AC_MSG_RESULT([yes])], - [ - AC_MSG_RESULT([no]) - AC_DEFINE([BROKEN_SNPRINTF], [1], - [Define if your snprintf is busted]) - AC_MSG_WARN([****** Your vsnprintf() function is broken, complain to your vendor]) - ], - [ AC_MSG_WARN([cross compiling: Assuming working vsnprintf()]) ] - ) -fi - -# On systems where [v]snprintf is broken, but is declared in stdio, -# check that the fmt argument is const char * or just char *. -# This is only useful for when BROKEN_SNPRINTF -AC_MSG_CHECKING([whether snprintf can declare const char *fmt]) -AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ -#include -int snprintf(char *a, size_t b, const char *c, ...) { return 0; } - ]], [[ - snprintf(0, 0, 0); - ]])], - [AC_MSG_RESULT([yes]) - AC_DEFINE([SNPRINTF_CONST], [const], - [Define as const if snprintf() can declare const char *fmt])], - [AC_MSG_RESULT([no]) - AC_DEFINE([SNPRINTF_CONST], [/* not const */])]) - # Check for missing getpeereid (or equiv) support NO_PEERCHECK="" if test "x$ac_cv_func_getpeereid" != "xyes" -a "x$ac_cv_func_getpeerucred" != "xyes"; then @@ -2394,36 +2365,34 @@ AC_RUN_IFELSE( [AC_LANG_PROGRAM([[ #include -#include +#include +#include +#include #include #ifdef HAVE_PTY_H # include #endif -#include -#include -#include ]], [[ pid_t pid; int fd, ptyfd, ttyfd, status; pid = fork(); - if (pid < 0) { /* failed */ - exit(1); + if (pid == -1) { /* failed */ + return 1; } else if (pid > 0) { /* parent */ waitpid(pid, &status, 0); if (WIFEXITED(status)) - exit(WEXITSTATUS(status)); + return WEXITSTATUS(status); else - exit(2); + return 2; } else { /* child */ close(0); close(1); close(2); setsid(); openpty(&ptyfd, &ttyfd, NULL, NULL, NULL); fd = open("/dev/tty", O_RDWR | O_NOCTTY); - if (fd >= 0) - exit(3); /* Acquired ctty: broken */ - else - exit(0); /* Did not acquire ctty: OK */ + if (fd != -1) + return 3; /* Acquired ctty: broken */ + /*else Did not acquire ctty: OK */ } ]])], [ @@ -2431,7 +2400,7 @@ ], [ AC_MSG_RESULT([no]) - AC_DEFINE([SSHD_ACQUIRES_CTTY]) + AC_DEFINE([SSHD_ACQUIRES_CTTY], [1]) ], [ AC_MSG_RESULT([cross-compiling, assuming yes]) @@ -2445,7 +2414,6 @@ AC_RUN_IFELSE( [AC_LANG_PROGRAM([[ #include -#include #include #include #include @@ -2465,7 +2433,7 @@ err = getaddrinfo(name, TEST_PORT, &hints, &gai_ai); if (err != 0) { fprintf(stderr, "getaddrinfo failed (%s)", gai_strerror(err)); - exit(1); + return 1; } for (ai = gai_ai; ai != NULL; ai = ai->ai_next) { @@ -2482,25 +2450,24 @@ else fprintf(stderr, "getnameinfo failed: %s\n", gai_strerror(err)); - exit(2); + return 2; } sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); - if (sock < 0) + if (sock == -1) perror("socket"); - if (bind(sock, ai->ai_addr, ai->ai_addrlen) < 0) { + if (bind(sock, ai->ai_addr, ai->ai_addrlen) == -1) { if (errno == EBADF) - exit(3); + return 3; } } - exit(0); ]])], [ AC_MSG_RESULT([yes]) ], [ AC_MSG_RESULT([no]) - AC_DEFINE([BROKEN_GETADDRINFO]) + AC_DEFINE([BROKEN_GETADDRINFO], [1]) ], [ AC_MSG_RESULT([cross-compiling, assuming yes]) @@ -2514,7 +2481,6 @@ AC_RUN_IFELSE( [AC_LANG_PROGRAM([[ #include -#include #include #include #include @@ -2534,7 +2500,7 @@ err = getaddrinfo(name, TEST_PORT, &hints, &gai_ai); if (err != 0) { fprintf(stderr, "getaddrinfo failed (%s)", gai_strerror(err)); - exit(1); + return 1; } for (ai = gai_ai; ai != NULL; ai = ai->ai_next) { @@ -2547,10 +2513,9 @@ if (ai->ai_family == AF_INET && err != 0) { perror("getnameinfo"); - exit(2); + return 2; } } - exit(0); ]])], [ AC_MSG_RESULT([yes]) @@ -2560,7 +2525,7 @@ ], [ AC_MSG_RESULT([no]) - AC_DEFINE([BROKEN_GETADDRINFO]) + AC_DEFINE([BROKEN_GETADDRINFO], [1]) ], [ AC_MSG_RESULT([cross-compiling, assuming no]) @@ -2579,9 +2544,8 @@ AC_MSG_CHECKING([for conflicting getspnam in shadow.h]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include -#include - ]], - [[ exit(0); ]])], + ]], [[ + ]])], [ AC_MSG_RESULT([no]) ], @@ -2608,7 +2572,6 @@ AC_RUN_IFELSE( [AC_LANG_PROGRAM([[ #include -#include #include #include #include @@ -2617,9 +2580,8 @@ char dst[16]; signal(SIGSEGV, sighandler); - if (strnvis(dst, "src", 4, 0) && strcmp(dst, "src") == 0) - exit(0); - exit(1) + if (strnvis(dst, "src", 4, 0) != 4 || strcmp(dst, "src") != 0) + return 1; ]])], [AC_MSG_RESULT([yes])], [AC_MSG_RESULT([no]) @@ -2629,20 +2591,21 @@ ) fi -AC_MSG_CHECKING([if SA_RESTARTed signals interrupt select()]) -AC_RUN_IFELSE( - [AC_LANG_PROGRAM([[ +AC_CACHE_CHECK( + [if restarted signals interrupt select()], + [ssh_cv_sa_restart_work], + [AC_RUN_IFELSE([AC_LANG_PROGRAM([[ #ifdef HAVE_SYS_SELECT # include #endif #include -#include -#include +#ifdef HAVE_SYS_TIME_H +# include +#endif #include #include static void sighandler(int sig) { } ]], [[ - int r; pid_t pid; struct sigaction sa; @@ -2656,18 +2619,23 @@ sleep(1); if (getppid() == pid) /* if parent did not exit, shoot it */ kill(pid, SIGKILL); - exit(0); } else { /* parent */ - r = select(0, NULL, NULL, NULL, NULL); + int r = select(0, NULL, NULL, NULL, NULL); + if (r != -1) return 1; } - exit(r == -1 ? 0 : 1); ]])], - [AC_MSG_RESULT([yes])], - [AC_MSG_RESULT([no]) - AC_DEFINE([NO_SA_RESTART], [1], - [SA_RESTARTed signals do no interrupt select])], - [AC_MSG_WARN([cross compiling: assuming yes])] -) + [ssh_cv_sa_restart_work=yes], + [ssh_cv_sa_restart_work=no], + [ssh_cv_sa_restart_work=cross] +)]) +AS_IF([test $ssh_cv_sa_restart_work = cross], [ + AC_MSG_WARN([cross compiling: assuming working restarted signals]) + ssh_cv_sa_restart_work=yes +]) +AS_IF([test $ssh_cv_sa_restart_work != yes], [ + AC_DEFINE([BROKEN_SA_RESTART], [1], + [Define if restarted signals do not interrupt select]) +]) AC_CHECK_FUNCS([getpgrp],[ AC_MSG_CHECKING([if getpgrp accepts zero args]) @@ -2683,7 +2651,6 @@ # Search for OpenSSL saved_CPPFLAGS="$CPPFLAGS" saved_LDFLAGS="$LDFLAGS" -openssl_bin_PATH="$PATH" AC_ARG_WITH([ssl-dir], [ --with-ssl-dir=PATH Specify path to OpenSSL installation ], [ @@ -2695,30 +2662,39 @@ # Relative paths ./*|../*) withval="`pwd`/$withval" esac - if test -d "$withval/lib"; then - libcrypto_path="${withval}/lib" - elif test -d "$withval/lib64"; then + if test -d "$withval/lib64"; then libcrypto_path="$withval/lib64" + elif test -d "$withval/lib"; then + libcrypto_path="$withval/lib" else - # Built but not installed - libcrypto_path="${withval}" + libcrypto_path="$withval" fi - if test -n "${rpath_opt}"; then - LDFLAGS="-L${libcrypto_path} ${rpath_opt}${libcrypto_path} ${LDFLAGS}" + if test -n "$rpath_opt"; then + LDFLAGS="-L$libcrypto_path $rpath_opt$libcrypto_path $LDFLAGS" else - LDFLAGS="-L${libcrypto_path} ${LDFLAGS}" + LDFLAGS="-L$libcrypto_path $LDFLAGS" fi if test -d "$withval/include"; then CPPFLAGS="-I${withval}/include ${CPPFLAGS}" else CPPFLAGS="-I${withval} ${CPPFLAGS}" fi - openssl_bin_PATH="${PATH}${PATH_SEPARATOR}${withval}/bin${PATH_SEPARATOR}${withval}/apps" + fi + ], + [ + dnl Check default openssl install dir + if test -d /usr/local/ssl/lib ; then + if test -n "${need_dash_r}"; then + LDFLAGS="-L/usr/local/ssl/lib -R/usr/local/ssl/lib $LDFLAGS" + else + LDFLAGS="-L/usr/local/ssl/lib $LDFLAGS" + fi + fi + if test -d /usr/local/ssl/include ; then + CPPFLAGS="-I/usr/local/ssl/include $CPPFLAGS" fi ] ) -AC_PATH_PROGS([openssl_bin], openssl, [], [$openssl_bin_PATH]) -AC_SUBST(OPENSSL_BIN, [${openssl_bin}]) AC_ARG_WITH([openssl-header-check], [ --without-openssl-header-check Disable OpenSSL version consistency check], @@ -2729,51 +2705,134 @@ ] ) -openssl_engine=no AC_ARG_WITH([ssl-engine], - [ --with-ssl-engine Enable OpenSSL (hardware) ENGINE support ], + [AS_HELP_STRING([--with-ssl-engine], + [Enable OpenSSL (hardware) ENGINE support])], + [], + [with_ssl_engine=check] +) + +# enable/disable OCSP requests +ssh_ocsp=: +AC_ARG_ENABLE([ocsp], + [AS_HELP_STRING([--disable-ocsp], [Disable OCSP validation])], + [AS_IF([test "x$enableval" = "xno"], [ssh_ocsp=false])]) + +# Where to place ssh CA root +sshcadir='${sysconfdir}/ca' +sshcadir=`eval echo ${sshcadir}` +sshcadir=`eval echo ${sshcadir}` +case $sshcadir in + NONE/*) sshcadir=`echo $sshcadir | sed "s~NONE~$ac_default_prefix~"` ;; +esac + +AC_ARG_WITH([sshca-dir], + [AS_HELP_STRING([--with-sshca-dir=DIR], [Specify location of ssh CA root])], [ - if test "x$withval" != "xno" ; then - if test "x$openssl" = "xno" ; then - AC_MSG_ERROR([cannot use --with-ssl-engine when OpenSSL disabled]) - fi - openssl_engine=yes - fi + AS_IF([test "x$withval" != "xno"], [ + sshcadir=$withval + ]) ] ) -nocrypto_saved_LIBS="$LIBS" +AC_DEFINE_UNQUOTED([SSHCADIR], ["$sshcadir"], [Specify location of ssh CA root]) +AC_SUBST([sshcadir]) + +# reserved for future removal +COMMENT_OUT_DSA= +AC_SUBST([COMMENT_OUT_DSA]) + +COMMENT_OUT_ECC="#no ecc#" +COMMENT_OUT_ECC256="#no ecc256#" +COMMENT_OUT_ECC384="#no ecc384#" +COMMENT_OUT_ECC521="#no ecc521#" +AC_SUBST([COMMENT_OUT_ECC]) +AC_SUBST([COMMENT_OUT_ECC256]) +AC_SUBST([COMMENT_OUT_ECC384]) +AC_SUBST([COMMENT_OUT_ECC521]) + +# OpenSSL >= 1.1.1 +COMMENT_OUT_ED25519="#no ed25519#" +AC_SUBST([COMMENT_OUT_ED25519]) + if test "x$openssl" = "xyes" ; then - LIBS="-lcrypto $LIBS" - CHANNELLIBS="-lcrypto $CHANNELLIBS" - AC_TRY_LINK_FUNC([RAND_add], , - [AC_MSG_ERROR([*** working libcrypto not found, check config.log])]) - AC_CHECK_HEADER([openssl/opensslv.h], , - [AC_MSG_ERROR([*** OpenSSL headers missing - please install first or check config.log ***])]) + + save_LIBS="$LIBS" + AC_MSG_CHECKING([how to link programs using OpenSSL functions]) + ac_CRYPTO_LINK=false + for L in "" "-ldl" "-lpthread" "-lpthread -ldl" ; do + LIBS="-lcrypto $L $save_LIBS" + AC_LINK_IFELSE( + [AC_LANG_PROGRAM([[ +#include +]], [[ +/* "OpenSSL_add_all_algorithms" is macro existing in 1.1.0 + * only for backward compatibility, i.e. some builds could + * deprecate it. + OpenSSL_add_all_algorithms(); */ + EVP_add_cipher(NULL); +]])], + [ac_CRYPTO_LINK=:]) + $ac_CRYPTO_LINK && break + done + if $ac_CRYPTO_LINK ; then + CRYPTO_LIBS="-lcrypto $L" + AC_MSG_RESULT([$CRYPTO_LIBS]) + else + AC_MSG_RESULT([fail]) + AC_MSG_ERROR([cannot link with OpenSSL crypto library]) + fi + LIBS="$CRYPTO_LIBS $save_LIBS" + + AC_TRY_LINK_FUNC([RAND_add], [AC_DEFINE([HAVE_OPENSSL], [1], + [Define if your ssl headers are included + with #include ])], + [ + AC_CHECK_HEADER([openssl/opensslv.h], , + [AC_MSG_ERROR([*** OpenSSL headers missing - please install first or check config.log ***])]) + AC_TRY_LINK_FUNC([RAND_add], [AC_DEFINE([HAVE_OPENSSL])], + [ + AC_MSG_ERROR([*** Can't find recent OpenSSL libcrypto (see config.log for details) ***]) + ] + ) + ] + ) + + # check for OpenSSL 1.1 API + AC_CHECK_FUNCS([OPENSSL_init_crypto]) + + # check for new OpenSSL version scheme (3.0 API) + AC_CHECK_FUNCS([OPENSSL_version_major]) # Determine OpenSSL header version AC_MSG_CHECKING([OpenSSL header version]) AC_RUN_IFELSE( [AC_LANG_PROGRAM([[ - #include #include #include - #include + #include #define DATA "conftest.sslincver" ]], [[ FILE *fd; int rc; + const char *ver_s = OPENSSL_VERSION_TEXT; fd = fopen(DATA,"w"); - if(fd == NULL) - exit(1); - - if ((rc = fprintf(fd, "%08lx (%s)\n", - (unsigned long)OPENSSL_VERSION_NUMBER, - OPENSSL_VERSION_TEXT)) < 0) - exit(1); - - exit(0); + if (fd == NULL) return 1; + #ifdef HAVE_OPENSSL_VERSION_MAJOR + rc = fprintf(fd, "%u.%u.%u (%s)\n", + (unsigned)OPENSSL_VERSION_MAJOR, + (unsigned)OPENSSL_VERSION_MINOR, + (unsigned)OPENSSL_VERSION_PATCH, + ver_s); + #else + { + unsigned long ver_num = OPENSSL_VERSION_NUMBER; + rc = fprintf(fd, "%08lx (%s)\n", ver_num, ver_s); + } + #endif + fclose(fd); + if (rc < 0) return 1; ]])], [ ssl_header_ver=`cat conftest.sslincver` @@ -2788,76 +2847,48 @@ ] ) - # Determining OpenSSL library version is version dependent. - AC_CHECK_FUNCS([OpenSSL_version OpenSSL_version_num]) - # Determine OpenSSL library version AC_MSG_CHECKING([OpenSSL library version]) AC_RUN_IFELSE( [AC_LANG_PROGRAM([[ #include - #include - #include - #include #include #define DATA "conftest.ssllibver" ]], [[ - FILE *f; - /* We need these legacy bits to warn for old libcrypto */ - #ifndef OPENSSL_VERSION - # define OPENSSL_VERSION SSLEAY_VERSION - #endif - #ifndef HAVE_OPENSSL_VERSION - # define OpenSSL_version SSLeay_version - #endif - #ifndef HAVE_OPENSSL_VERSION_NUM - # define OpenSSL_version_num SSLeay - #endif - if ((f = fopen(DATA, "w")) == NULL) - exit(1); - if (fprintf(f, "%08lx (%s)", - (unsigned long)OpenSSL_version_num(), - OpenSSL_version(OPENSSL_VERSION)) < 0) - exit(1); -#ifdef LIBRESSL_VERSION_NUMBER - if (fprintf(f, " libressl-%08lx", LIBRESSL_VERSION_NUMBER) < 0) - exit(1); -#endif - if (fputc('\n', f) == EOF || fclose(f) == EOF) - exit(1); - exit(0); + FILE *fd; + int rc; + const char *ver_s; + #ifdef HAVE_OPENSSL_INIT_CRYPTO + ver_s = OpenSSL_version(OPENSSL_VERSION); + #else + ver_s = SSLeay_version(SSLEAY_VERSION); + #endif + + fd = fopen(DATA,"w"); + if (fd == NULL) return 1; + #ifdef HAVE_OPENSSL_VERSION_MAJOR + rc = fprintf(fd, "%u.%u.%u (%s)\n", + OPENSSL_version_major(), + OPENSSL_version_minor(), + OPENSSL_version_patch(), + ver_s); + #else + { + unsigned long ver_num; + #ifdef HAVE_OPENSSL_INIT_CRYPTO + ver_num = OpenSSL_version_num(); + #else + ver_num = SSLeay(); + #endif + rc = fprintf(fd, "%08lx (%s)\n", ver_num, ver_s); + } + #endif + fclose(fd); + if (rc < 0) return 1; ]])], [ - sslver=`cat conftest.ssllibver` - ssl_showver=`echo "$sslver" | sed 's/ libressl-.*//'` - # Check version is supported. - case "$sslver" in - 100*|10100*) # 1.0.x, 1.1.0x - AC_MSG_ERROR([OpenSSL >= 1.1.1 required (have "$ssl_showver")]) - ;; - 101*) ;; # 1.1.x - 200*) # LibreSSL - lver=`echo "$sslver" | sed 's/.*libressl-//'` - case "$lver" in - 2*|300*) # 2.x, 3.0.0 - AC_MSG_ERROR([LibreSSL >= 3.1.0 required (have "$ssl_showver")]) - ;; - *) ;; # Assume all other versions are good. - esac - ;; - 300*) - # OpenSSL 3; we use the 1.1x API - CPPFLAGS="$CPPFLAGS -DOPENSSL_API_COMPAT=0x10100000L" - ;; - 301*|302*) - # OpenSSL development branch; request 1.1x API - CPPFLAGS="$CPPFLAGS -DOPENSSL_API_COMPAT=0x10100000L" - ;; - *) - AC_MSG_ERROR([Unknown/unsupported OpenSSL version ("$ssl_showver")]) - ;; - esac - AC_MSG_RESULT([$ssl_showver]) + ssl_library_ver=`cat conftest.ssllibver` + AC_MSG_RESULT([$ssl_library_ver]) ], [ AC_MSG_RESULT([not found]) @@ -2868,25 +2899,27 @@ ] ) - case "$host" in - x86_64-*) - case "$sslver" in - 3000004*) - AC_MSG_ERROR([OpenSSL 3.0.4 has a potential RCE in its RSA implementation (CVE-2022-2274)]) - ;; - esac - esac - # Sanity check OpenSSL headers AC_MSG_CHECKING([whether OpenSSL's headers match the library]) AC_RUN_IFELSE( [AC_LANG_PROGRAM([[ - #include - #include - #include #include ]], [[ - exit(OpenSSL_version_num() == OPENSSL_VERSION_NUMBER ? 0 : 1); + #ifdef HAVE_OPENSSL_VERSION_MAJOR + if (OPENSSL_version_major() != OPENSSL_VERSION_MAJOR) return 1; + if (OPENSSL_version_minor() != OPENSSL_VERSION_MINOR) return 1; + if (OPENSSL_version_patch() != OPENSSL_VERSION_PATCH) return 1; + #else + { + unsigned long ver_num; + #ifdef HAVE_OPENSSL_INIT_CRYPTO + ver_num = OpenSSL_version_num(); + #else + ver_num = SSLeay(); + #endif + if (ver_num != OPENSSL_VERSION_NUMBER) return 1; + } + #endif ]])], [ AC_MSG_RESULT([yes]) @@ -2898,12 +2931,10 @@ library. Check config.log for details. If you are sure your installation is consistent, you can disable the check by running "./configure --without-openssl-header-check". - Also see contrib/findssl.sh for help identifying header/library mismatches. ]) else AC_MSG_WARN([Your OpenSSL headers do not match your - library. Check config.log for details. - Also see contrib/findssl.sh for help identifying header/library mismatches.]) + library. Check config.log for details.]) fi ], [ @@ -2911,64 +2942,8 @@ ] ) - AC_MSG_CHECKING([if programs using OpenSSL functions will link]) - AC_LINK_IFELSE( - [AC_LANG_PROGRAM([[ #include ]], - [[ ERR_load_crypto_strings(); ]])], - [ - AC_MSG_RESULT([yes]) - ], - [ - AC_MSG_RESULT([no]) - LIBS="$LIBS -ldl" - AC_MSG_CHECKING([if programs using OpenSSL need -ldl]) - AC_LINK_IFELSE( - [AC_LANG_PROGRAM([[ #include ]], - [[ ERR_load_crypto_strings(); ]])], - [ - AC_MSG_RESULT([yes]) - CHANNELLIBS="$CHANNELLIBS -ldl" - ], - [ - AC_MSG_RESULT([no]) - ] - ) - ] - ) - - AC_CHECK_FUNCS([ \ - BN_is_prime_ex \ - DES_crypt \ - DSA_generate_parameters_ex \ - EVP_DigestFinal_ex \ - EVP_DigestInit_ex \ - EVP_MD_CTX_cleanup \ - EVP_MD_CTX_copy_ex \ - EVP_MD_CTX_init \ - HMAC_CTX_init \ - RSA_generate_key_ex \ - RSA_get_default_method \ - ]) - - # OpenSSL_add_all_algorithms may be a macro. - AC_CHECK_FUNC(OpenSSL_add_all_algorithms, - AC_DEFINE(HAVE_OPENSSL_ADD_ALL_ALGORITHMS, 1, [as a function]), - AC_CHECK_DECL(OpenSSL_add_all_algorithms, - AC_DEFINE(HAVE_OPENSSL_ADD_ALL_ALGORITHMS, 1, [as a macro]), , - [[#include ]] - ) - ) - - # LibreSSL/OpenSSL API differences - AC_CHECK_FUNCS([ \ - EVP_CIPHER_CTX_iv \ - EVP_CIPHER_CTX_iv_noconst \ - EVP_CIPHER_CTX_get_iv \ - EVP_CIPHER_CTX_get_updated_iv \ - EVP_CIPHER_CTX_set_iv \ - ]) - - if test "x$openssl_engine" = "xyes" ; then + if test "x$with_ssl_engine" != "xno" ; then + AC_CHECK_HEADERS([openssl/engine.h]) AC_MSG_CHECKING([for OpenSSL ENGINE support]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include @@ -2987,11 +2962,11 @@ AC_MSG_CHECKING([whether OpenSSL has crippled AES support]) AC_LINK_IFELSE( [AC_LANG_PROGRAM([[ - #include - #include #include ]], [[ - exit(EVP_aes_192_cbc() == NULL || EVP_aes_256_cbc() == NULL); + if (EVP_aes_192_cbc() == NULL || + EVP_aes_256_cbc() == NULL) + return 1; ]])], [ AC_MSG_RESULT([no]) @@ -3003,28 +2978,68 @@ ] ) - AC_MSG_CHECKING([if EVP_DigestUpdate returns an int]) + # Check for OpenSSL with EVP_aes_*ctr + AC_MSG_CHECKING([whether OpenSSL has AES CTR via EVP]) AC_LINK_IFELSE( [AC_LANG_PROGRAM([[ - #include - #include #include ]], [[ - if(EVP_DigestUpdate(NULL, NULL,0)) - exit(0); + if (EVP_aes_128_ctr() == NULL || + EVP_aes_192_ctr() == NULL || + EVP_aes_256_ctr() == NULL) + return 1; ]])], [ AC_MSG_RESULT([yes]) + AC_DEFINE([OPENSSL_HAVE_EVPCTR], [1], + [libcrypto has EVP AES CTR]) ], [ AC_MSG_RESULT([no]) - AC_DEFINE([OPENSSL_EVP_DIGESTUPDATE_VOID], [1], - [Define if EVP_DigestUpdate returns void]) ] ) - # Check for various EVP support in OpenSSL - AC_CHECK_FUNCS([EVP_sha256 EVP_sha384 EVP_sha512 EVP_chacha20]) + # Check for OpenSSL with EVP_aes_*gcm + AC_MSG_CHECKING([whether OpenSSL has AES GCM via EVP]) + AC_LINK_IFELSE( + [AC_LANG_PROGRAM([[ + #include + ]], [[ + if (EVP_aes_128_gcm() == NULL || + EVP_aes_256_gcm() == NULL || + EVP_CTRL_GCM_SET_IV_FIXED == 0 || + EVP_CTRL_GCM_IV_GEN == 0 || + EVP_CTRL_GCM_SET_TAG == 0 || + EVP_CTRL_GCM_GET_TAG == 0 || + EVP_CIPHER_CTX_ctrl(NULL, 0, 0, NULL) == 0) + return 1; + ]])], + [ + AC_MSG_RESULT([yes]) + AC_DEFINE([OPENSSL_HAVE_EVPGCM], [1], + [libcrypto has EVP AES GCM]) + ], + [ + AC_MSG_RESULT([no]) + unsupported_algorithms="$unsupported_cipers \ + aes128-gcm@openssh.com \ + aes256-gcm@openssh.com" + ] + ) + + # Check for SHA256, SHA384 and SHA512 support in OpenSSL + AC_CHECK_FUNCS([EVP_sha256 EVP_sha384 EVP_sha512], , + [unsupported_algorithms="$unsupported_algorithms \ + hmac-sha2-256 \ + hmac-sha2-512 \ + diffie-hellman-group14-sha256 \ + diffie-hellman-group16-sha512 \ + diffie-hellman-group18-sha512 \ + diffie-hellman-group-exchange-sha256 \ + hmac-sha2-256-etm@openssh.com \ + hmac-sha2-512-etm@openssh.com" + ] + ) # Check complete ECC support in OpenSSL AC_MSG_CHECKING([whether OpenSSL has NID_X9_62_prime256v1]) @@ -3036,6 +3051,16 @@ #include #include #include + #ifndef HAVE_OPENSSL_INIT_CRYPTO /* < 1.1.0 */ + #if OPENSSL_VERSION_NUMBER < 0x0090807f /* 0.9.8g */ + # error "OpenSSL < 0.9.8g has unreliable ECC code" + #endif + #ifdef OPENSSL_FIPS + # if OPENSSL_VERSION_NUMBER < 0x00908fff /* 0.9.8* */ + # error "OpenSSL <= 0.9.8* has unreliable ECC code in FIPS build" + # endif + #endif + #endif ]], [[ EC_KEY *e = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); const EVP_MD *m = EVP_sha256(); /* We need this too */ @@ -3054,6 +3079,16 @@ #include #include #include + #ifndef HAVE_OPENSSL_INIT_CRYPTO /* < 1.1.0 */ + #if OPENSSL_VERSION_NUMBER < 0x0090807f /* 0.9.8g */ + # error "OpenSSL < 0.9.8g has unreliable ECC code" + #endif + #ifdef OPENSSL_FIPS + # if OPENSSL_VERSION_NUMBER < 0x00908fff /* 0.9.8* */ + # error "OpenSSL <= 0.9.8* has unreliable ECC code in FIPS build" + # endif + #endif + #endif ]], [[ EC_KEY *e = EC_KEY_new_by_curve_name(NID_secp384r1); const EVP_MD *m = EVP_sha384(); /* We need this too */ @@ -3072,15 +3107,24 @@ #include #include #include + #ifndef HAVE_OPENSSL_INIT_CRYPTO /* < 1.1.0 */ + #if OPENSSL_VERSION_NUMBER < 0x0090807f /* 0.9.8g */ + # error "OpenSSL < 0.9.8g has unreliable ECC code" + #endif + #ifdef OPENSSL_FIPS + # if OPENSSL_VERSION_NUMBER < 0x00908fff /* 0.9.8* */ + # error "OpenSSL <= 0.9.8* has unreliable ECC code in FIPS build" + # endif + #endif + #endif ]], [[ EC_KEY *e = EC_KEY_new_by_curve_name(NID_secp521r1); const EVP_MD *m = EVP_sha512(); /* We need this too */ ]])], [ AC_MSG_RESULT([yes]) - AC_MSG_CHECKING([if OpenSSL's NID_secp521r1 is functional]) + AC_CACHE_CHECK([if OpenSSL's curve secp521r1 is functional],[ssh_cv_working_secp521r1],[ AC_RUN_IFELSE( [AC_LANG_PROGRAM([[ - #include #include #include #include @@ -3088,30 +3132,38 @@ #include #include ]],[[ + int ret = 0; EC_KEY *e = EC_KEY_new_by_curve_name(NID_secp521r1); const EVP_MD *m = EVP_sha512(); /* We need this too */ - exit(e == NULL || m == NULL); + if (e == NULL || m == NULL) + ret = 1; + EC_KEY_free(e); + return ret; ]])], - [ AC_MSG_RESULT([yes]) - enable_nistp521=1 ], - [ AC_MSG_RESULT([no]) ], - [ AC_MSG_WARN([cross-compiling: assuming yes]) - enable_nistp521=1 ] - )], + [ssh_cv_working_secp521r1=yes], + [ssh_cv_working_secp521r1=no], + [ssh_cv_working_secp521r1=cross] + )]) + if test "x$ssh_cv_working_secp521r1" = xcross ; then + AC_MSG_WARN([cross compiling: assuming functional secp521r1 curve]) + ssh_cv_working_secp521r1=yes + fi + if test "x$ssh_cv_working_secp521r1" = xyes ; then + enable_nistp521=1 + fi + ], AC_MSG_RESULT([no]) ) if test x$enable_nistp256 = x1 || test x$enable_nistp384 = x1 || \ test x$enable_nistp521 = x1; then AC_DEFINE(OPENSSL_HAS_ECC, [1], [OpenSSL has ECC]) - AC_CHECK_FUNCS([EC_KEY_METHOD_new]) - openssl_ecc=yes - else - openssl_ecc=no fi if test x$enable_nistp256 = x1; then AC_DEFINE([OPENSSL_HAS_NISTP256], [1], [libcrypto has NID_X9_62_prime256v1]) + COMMENT_OUT_ECC= + COMMENT_OUT_ECC256= else unsupported_algorithms="$unsupported_algorithms \ ecdsa-sha2-nistp256 \ @@ -3120,6 +3172,8 @@ fi if test x$enable_nistp384 = x1; then AC_DEFINE([OPENSSL_HAS_NISTP384], [1], [libcrypto has NID_secp384r1]) + COMMENT_OUT_ECC= + COMMENT_OUT_ECC384= else unsupported_algorithms="$unsupported_algorithms \ ecdsa-sha2-nistp384 \ @@ -3128,144 +3182,378 @@ fi if test x$enable_nistp521 = x1; then AC_DEFINE([OPENSSL_HAS_NISTP521], [1], [libcrypto has NID_secp521r1]) + COMMENT_OUT_ECC= + COMMENT_OUT_ECC521= else unsupported_algorithms="$unsupported_algorithms \ ecdh-sha2-nistp521 \ ecdsa-sha2-nistp521 \ ecdsa-sha2-nistp521-cert-v01@openssh.com" fi -fi -# PKCS11/U2F depend on OpenSSL and dlopen(). -enable_pkcs11=yes -enable_sk=yes -if test "x$openssl" != "xyes" ; then - enable_pkcs11="disabled; missing libcrypto" -fi -if test "x$ac_cv_func_dlopen" != "xyes" ; then - enable_pkcs11="disabled; missing dlopen(3)" - enable_sk="disabled; missing dlopen(3)" -fi -if test "x$ac_cv_have_decl_RTLD_NOW" != "xyes" ; then - enable_pkcs11="disabled; missing RTLD_NOW" - enable_sk="disabled; missing RTLD_NOW" -fi -if test ! -z "$disable_pkcs11" ; then - enable_pkcs11="disabled by user" -fi -if test ! -z "$disable_sk" ; then - enable_sk="disabled by user" + # Check for OpenSSL with ED25519 + AC_MSG_CHECKING([whether OpenSSL has ED25519 support]) + AC_LINK_IFELSE( + [AC_LANG_PROGRAM([[ + #include + ]], [[ + unsigned char buf[64]; + if (EVP_PKEY_new_raw_private_key( + EVP_PKEY_ED25519, NULL, + buf, sizeof(buf)) == NULL) + return 1; + ]])], + [ + AC_MSG_RESULT([yes]) + AC_DEFINE([OPENSSL_HAS_ED25519], [1], + [libcrypto has ed25519 support]) + COMMENT_OUT_ED25519= + ], + [ + AC_MSG_RESULT([no]) + ] + ) fi -AC_MSG_CHECKING([whether to enable PKCS11]) -if test "x$enable_pkcs11" = "xyes" ; then - AC_DEFINE([ENABLE_PKCS11], [], [Enable for PKCS#11 support]) + +# check for openssl 0.9.7+ functions ... +AC_CHECK_FUNCS([ \ + DES_crypt \ + EVP_MD_CTX_init \ +]) + +# check for openssl 0.9.8+ headers ... +AC_CHECK_HEADERS([ \ + openssl/ec.h \ +]) + +# check for openssl 0.9.8+ functions ... +dnl BN_is_negative is macro in 0.9.8*-1.0.2* +AC_CHECK_FUNCS([ \ + BN_is_prime_ex \ + DSA_generate_parameters_ex \ + EVP_CIPHER_CTX_new \ + EVP_PKEY_cmp \ + RSA_generate_key_ex \ +]) + +# Check for the existence of "X509_VERIFY_PARAM *param" (OpenSSL 0.9.8+) +# Instead check for X509_STORE_CTX.param we check for get functions +AC_CHECK_FUNCS([X509_STORE_CTX_get0_param]) + +# check for openssl 1.0.0+ functions ... +AC_CHECK_FUNCS([ \ + ERR_remove_thread_state \ + EVP_DigestSignInit \ + EVP_MD_flags \ + EVP_PKEY_base_id \ + EVP_PKEY_print_params \ + X509_STORE_set_verify_cb \ +]) + +# check for some structures +AC_CHECK_MEMBERS([ECDSA_METHOD.name], [], [], +[[#include ]] +) + +# check for openssl 1.0.2+ functions ... +AC_CHECK_FUNCS([ \ + ECDSA_METHOD_new \ +]) + +# check for openssl 1.1+ functions ... +AC_CHECK_FUNCS([ \ + ASN1_STRING_get0_data \ + BN_is_negative \ + DH_get0_key \ + DSA_SIG_get0 \ + DSA_SIG_set0 \ + EC_KEY_METHOD_new \ + ECDSA_SIG_get0 \ + ECDSA_SIG_set0 \ + EVP_chacha20 \ + EVP_CIPHER_CTX_iv \ + EVP_MD_CTX_new \ + RSA_meth_new \ + RSA_PKCS1_OpenSSL \ + X509_CRL_get0_lastUpdate \ + X509_get0_tbs_sigalg \ + X509_get_extension_flags \ + X509_get_key_usage \ + X509_OBJECT_new \ + X509_STORE_CTX_get_by_subject \ + X509_STORE_get0_objects \ + X509_STORE_lock \ +]) +dnl OpenSSL 1.1 changes X509_STORE_CTX and X509_VERIFY_PARAM to opaque structure. +dnl Until OpenSSL 1.1.0d+ there is no function to get "check" time. +AC_CHECK_FUNCS([X509_VERIFY_PARAM_get_time]) + +# check for functions randomly implemented for compatibility with openssl 1.1+ +AC_CHECK_FUNCS([ \ + DSA_get0_key \ + OPENSSL_cleanup \ + RSA_meth_get_pub_enc \ + RSA_meth_set1_name \ + RSA_meth_set_priv_enc \ + RSA_get0_key \ + X509_OBJECT_get0_X509 \ +]) +# check for removed in openssl 1.1+ functions ... +AC_CHECK_FUNCS([ \ + EVP_dss1 \ +]) +# check for openssl 1.1.+ declarations ... +AC_CHECK_DECLS([DEFINE_STACK_OF],,,[ +#include +#include +]) +# check for openssl 1.1+ opaque structures ... +AC_CHECK_TYPES([struct x509_lookup_method_st], [], [], [ +#include +]) + +# check for openssl 1.1.1+ functions ... +AC_CHECK_FUNCS([ \ + EC_POINT_get_affine_coordinates \ + EVP_DigestSign \ + RAND_keep_random_devices_open \ +]) + +# activate openssl(1.1.1+) store functionality +USE_OPENSSL_STORE2=false +AC_CHECK_FUNC([OSSL_STORE_open]) +if test "x$ac_cv_func_OSSL_STORE_open" = xyes ; then + AC_DEFINE( + [USE_OPENSSL_STORE2], + [1], [Use OpenSSL STORE functionality]) + USE_OPENSSL_STORE2=: fi -AC_MSG_RESULT([$enable_pkcs11]) +AC_SUBST([USE_OPENSSL_STORE2]) -AC_MSG_CHECKING([whether to enable U2F]) -if test "x$enable_sk" = "xyes" ; then - AC_DEFINE([ENABLE_SK], [], [Enable for U2F/FIDO support]) - AC_SUBST(SK_DUMMY_LIBRARY, [regress/misc/sk-dummy/sk-dummy.so]) -else - # Do not try to build sk-dummy library. - AC_SUBST(SK_DUMMY_LIBRARY, [""]) +# check for openssl 3.0+ functions ... +AC_CHECK_FUNCS([ \ + BN_check_prime \ + EC_GROUP_get_field_type \ + ERR_get_error_all \ + EVP_KEYMGMT_get0_provider \ + EVP_MD_get_flags \ + EVP_PKEY_eq \ + EVP_PKEY_get_base_id \ + X509_LOOKUP_store \ +]) + +# check for deprecated 3.0+ functions ... +AC_CHECK_FUNCS([ \ + AES_encrypt \ +]) + +# functions in openssl compatible libraries +AC_CHECK_DECLS([UTF8_getc],,,[ +#include +]) +AC_CHECK_FUNCS([ \ + EVP_CIPHER_CTX_get_iv \ + UTF8_getc \ +]) + +# ASN1_STRING_length const argument >= 1.0 +AC_MSG_CHECKING([whether ASN1_STRING_length declare const argument]) +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ +#include +int ASN1_STRING_length(const ASN1_STRING *x) { + (void) x; return 0; +} +]], [[ + ASN1_STRING_length(NULL); +]])], +[ AC_MSG_RESULT([yes]) + asn1_string_length_const="const" +], +[ AC_MSG_RESULT([no]) + asn1_string_length_const="/* not const */" +] +) +AC_DEFINE_UNQUOTED([ASN1_STRING_LENGTH_CONST], [$asn1_string_length_const], + [Define as const if ASN1_STRING_CONST() declare const argument] +) + +# check for function sk_OPENSSL_STRING_new_null inlined in openssl 1.1+ ... +AC_CACHE_CHECK( + [for sk_OPENSSL_STRING_new_null], + [ac_cv_func_sk_OPENSSL_STRING_new_null], + AC_LINK_IFELSE( + [AC_LANG_PROGRAM( + [[ + #include + ]],[[ + void *q; + q = sk_OPENSSL_STRING_new_null(); + ]]) + ], + [ ac_cv_func_sk_OPENSSL_STRING_new_null=yes ], + [ ac_cv_func_sk_OPENSSL_STRING_new_null=no ] + ) +) +if test "x$ac_cv_func_sk_OPENSSL_STRING_new_null" = xyes; then + AC_DEFINE( + [HAVE_SK_OPENSSL_STRING_NEW_NULL], + [1], [Define to 1 if you have the 'sk_OPENSSL_STRING_new_null' function.]) fi -AC_MSG_RESULT([$enable_sk]) -# Now check for built-in security key support. -if test "x$enable_sk" = "xyes" -a "x$enable_sk_internal" != "xno" ; then - use_pkgconfig_for_libfido2= - if test "x$PKGCONFIG" != "xno"; then - AC_MSG_CHECKING([if $PKGCONFIG knows about libfido2]) - if "$PKGCONFIG" libfido2; then - AC_MSG_RESULT([yes]) - use_pkgconfig_for_libfido2=yes - else - AC_MSG_RESULT([no]) - fi - fi - if test "x$use_pkgconfig_for_libfido2" = "xyes"; then - LIBFIDO2=`$PKGCONFIG --libs libfido2` - CPPFLAGS="$CPPFLAGS `$PKGCONFIG --cflags libfido2`" - else - LIBFIDO2="-lfido2 -lcbor" +AC_MSG_CHECKING([whether store find method uses const criteria]) +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ +#include +typedef int (*OSSL_STORE_find_fn)(OSSL_STORE_LOADER_CTX *ctx, + const OSSL_STORE_SEARCH *criteria); +]],[[ +]])], +[ AC_MSG_RESULT([yes]) + store_find_criterion_const="const" +], +[ AC_MSG_RESULT([no]) + store_find_criterion_const="/* not const */" +] +) +AC_DEFINE_UNQUOTED([STORE_FIND_CRITERION_CONST], [$store_find_criterion_const], + [Define as const if store find method uses const criteria] +) + + +# FIPS enabled OpenSSL +AC_ARG_VAR([FIPSLD_CC],[actual compiler to be used by openssl fips compiler]) + +OPENSSL_FIPS_MODE=no +AC_ARG_ENABLE([openssl-fips], + [AS_HELP_STRING([--enable-openssl-fips], [Enable build with FIPS-enabled openssl])], + [ac_openssl_fips=$enableval], + [ac_openssl_fips=none] +) + +AS_IF([test "x$ac_openssl_fips" = "xyes"], [ + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ +#include + ]],[[ +#ifndef OPENSSL_FIPS +error OPENSSL_FIPS is not defined +#endif + ]])], + [], + [AC_MSG_ERROR([cannot found fips capable openssl header])] + ) + AC_CHECK_FUNC( + [FIPS_mode], + [], + [AC_MSG_ERROR([cannot found fips capable openssl library])] + ) + OPENSSL_FIPS_MODE=yes +]) +AC_SUBST([OPENSSL_FIPS_MODE]) + +FIPS_LIBS= +FIPSHMAC=: +AS_IF([test "x$OPENSSL_FIPS_MODE" = "xyes"], [ + # some system distribute openssl/fips.h + AC_CHECK_HEADERS([openssl/fips.h], [], [], [ +/* Header in fips module 2.0* refer to elementary keys like RSA, + DSA, EVP* structures, and etc. i.e. unusable without OpenSSL + types declarations. Also header uses size_t. + */ +#include +#include + ]) + + # on some systems FIPS error string are not loaded with other errors!? + AC_CHECK_DECLS([ERR_load_FIPS_strings], [],[], [ +#include +#include +#ifdef HAVE_OPENSSL_FIPS_H +# include +#endif + ]) + AC_CHECK_FUNCS([ \ + ERR_load_FIPS_strings \ + ]) + + # check for Red Hat specific fips library + AC_CHECK_LIB([fipscheck], [FIPSCHECK_verify], + [ + FIPS_LIBS="-lfipscheck" + AC_CHECK_HEADERS([fipscheck.h]) + FIPSHMAC=fipshmac + ]) +]) +AC_SUBST([FIPS_LIBS]) +AC_SUBST([FIPSHMAC]) + + +use_dl=false +# PKCS#11 depends on OpenSSL and requires dlopen() and co. +if test $PKCS11_MSG = yes ; then +dnl build with OpenSSL is required - no check +dnl if test "x$openssl" = "xyes" ; then +dnl .... +dnl fi + use_dl=: +fi +if $use_dl ; then + AC_SEARCH_LIBS([dlopen], [dl], [], [use_dl=false]) +fi +if $use_dl ; then + # LAZY mode is preferred + AC_CHECK_DECL([RTLD_LAZY], [], [ + AC_CHECK_DECL([RTLD_NOW], [], [use_dl=false], + [#include ]) + ], [#include ]) +fi +if $use_dl ; then + if test $PKCS11_MSG = yes; then + AC_DEFINE([ENABLE_PKCS11], [1], + [Define if you want to enable PKCS#11 support]) fi - OTHERLIBS=`echo $LIBFIDO2 | sed 's/-lfido2//'` - fido2_error= - AC_CHECK_LIB([fido2], [fido_init], - [ ], - [ fido2_error="missing/unusable libfido2" ], - [ $OTHERLIBS ] - ) - AC_CHECK_HEADER([fido.h], [], - [ fido2_error="missing fido.h from libfido2" ]) - AC_CHECK_HEADER([fido/credman.h], [], - [ fido2_error="missing fido/credman.h from libfido2" ], - [ #include ] - ) - AC_MSG_CHECKING([for usable libfido2 installation]) - if test ! -z "$fido2_error" ; then - AC_MSG_RESULT([$fido2_error]) - if test "x$enable_sk_internal" = "xyes" ; then - AC_MSG_ERROR([No usable libfido2 library/headers found]) - fi - LIBFIDO2="" - else - AC_MSG_RESULT([yes]) - AC_SUBST([LIBFIDO2]) - AC_DEFINE([ENABLE_SK_INTERNAL], [], - [Enable for built-in U2F/FIDO support]) - enable_sk="built-in" - saved_LIBS="$LIBS" - LIBS="$LIBFIDO2 $LIBS" - AC_CHECK_FUNCS([ \ - fido_assert_set_clientdata \ - fido_cred_prot \ - fido_cred_set_prot \ - fido_cred_set_clientdata \ - fido_dev_get_touch_begin \ - fido_dev_get_touch_status \ - fido_dev_supports_cred_prot \ - fido_dev_is_winhello \ - ]) - LIBS="$saved_LIBS" +else + if test $PKCS11_MSG = yes; then + AC_MSG_ERROR([ + PKCS#11 support was requested, but dynamic loading is not detected! +]) fi fi +AC_CHECK_DECLS([arc4random]) +AC_CHECK_DECLS([arc4random_buf]) +AC_CHECK_DECLS([arc4random_stir]) +AC_CHECK_DECLS([arc4random_uniform]) AC_CHECK_FUNCS([ \ arc4random \ arc4random_buf \ arc4random_stir \ arc4random_uniform \ ]) + ### Configure cryptographic random number support # Check whether OpenSSL seeds itself if test "x$openssl" = "xyes" ; then - AC_MSG_CHECKING([whether OpenSSL's PRNG is internally seeded]) + AC_CACHE_CHECK([whether OpenSSL's PRNG is internally seeded], + [ssh_cv_openssl_seeds_itself], [ AC_RUN_IFELSE( [AC_LANG_PROGRAM([[ - #include - #include #include ]], [[ - exit(RAND_status() == 1 ? 0 : 1); + if (RAND_status() != 1) + return 1; ]])], - [ - OPENSSL_SEEDS_ITSELF=yes - AC_MSG_RESULT([yes]) - ], - [ - AC_MSG_RESULT([no]) - ], - [ - AC_MSG_WARN([cross compiling: assuming yes]) - # This is safe, since we will fatal() at runtime if - # OpenSSL is not seeded correctly. - OPENSSL_SEEDS_ITSELF=yes - ] + [ssh_cv_openssl_seeds_itself=yes], + [ssh_cv_openssl_seeds_itself=no], + [ssh_cv_openssl_seeds_itself=cross] ) + ]) + AS_IF([test "x$ssh_cv_openssl_seeds_itself" = "xcross"], [ + AC_MSG_WARN([cross compiling: assuming internally seeded]) + # This is safe, since program call fatal() at runtime if + # OpenSSL is not seeded correctly. + ssh_cv_openssl_seeds_itself=yes + ]) fi # PRNGD TCP socket @@ -3322,11 +3610,11 @@ ], [ # Check for existing socket only if we don't have a random device already - if test "x$OPENSSL_SEEDS_ITSELF" != "xyes" ; then + if test "x$ssh_cv_openssl_seeds_itself" != "xyes" ; then AC_MSG_CHECKING([for PRNGD/EGD socket]) # Insert other locations here for sock in /var/run/egd-pool /dev/egd-pool /etc/entropy; do - if test -r $sock && $TEST_MINUS_S_SH -c "test -S $sock -o -p $sock" ; then + if test -r $sock && $SHELL -c "test -S $sock -o -p $sock" ; then PRNGD_SOCKET="$sock" AC_DEFINE_UNQUOTED([PRNGD_SOCKET], ["$PRNGD_SOCKET"]) break; @@ -3346,16 +3634,15 @@ RAND_MSG="PRNGd port $PRNGD_PORT" elif test ! -z "$PRNGD_SOCKET" ; then RAND_MSG="PRNGd socket $PRNGD_SOCKET" -elif test ! -z "$OPENSSL_SEEDS_ITSELF" ; then +elif test "x$ssh_cv_openssl_seeds_itself" = "xyes" ; then AC_DEFINE([OPENSSL_PRNG_ONLY], [1], [Define if you want the OpenSSL internally seeded PRNG only]) RAND_MSG="OpenSSL internal ONLY" elif test "x$openssl" = "xno" ; then - AC_MSG_WARN([OpenSSH will use /dev/urandom as a source of random numbers. It will fail if this device is not supported or accessible]) + AC_MSG_WARN([$PACKAGE_NAME will use /dev/urandom as a source of random numbers. It will fail if this device is not supported or accessible]) else - AC_MSG_ERROR([OpenSSH has no source of random numbers. Please configure OpenSSL with an entropy source or re-run configure using one of the --with-prngd-port or --with-prngd-socket options]) + AC_MSG_ERROR([$PACKAGE_NAME has no source of random numbers. Please configure OpenSSL with an entropy source or re-run configure using one of the --with-prngd-port or --with-prngd-socket options]) fi -LIBS="$nocrypto_saved_LIBS" saved_LIBS="$LIBS" AC_CHECK_LIB([iaf], [ia_openinfo], [ @@ -3489,11 +3776,12 @@ #include #include #include - ]], - [[ int i = $seccomp_audit_arch; + ]], [[ + int i = $seccomp_audit_arch; errno = 0; prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, NULL, 0, 0); - exit(errno == EFAULT ? 0 : 1); ]])], + if (errno != EFAULT) return 1; + ]])], [ AC_MSG_RESULT([yes]) ], [ AC_MSG_RESULT([no]) # Disable seccomp filter as a target @@ -3505,20 +3793,22 @@ AC_CHECK_MEMBERS([struct pollfd.fd], [], [], [[ #include #ifdef HAVE_POLL_H -#include -#endif -#ifdef HAVE_SYS_POLL_H -#include +# include +#else +# ifdef HAVE_SYS_POLL_H +# include +# endif #endif ]]) AC_CHECK_TYPES([nfds_t], , , [ #include #ifdef HAVE_POLL_H -#include -#endif -#ifdef HAVE_SYS_POLL_H -#include +# include +#else +# ifdef HAVE_SYS_POLL_H +# include +# endif #endif ]) @@ -3535,112 +3825,37 @@ ] ) -if test "x$sandbox_arg" != "xno"; then -# POSIX specifies that poll() "shall fail with EINVAL if the nfds argument -# is greater than OPEN_MAX". On some platforms that includes implementions -# of select in userspace on top of poll() so check both work with rlimit -# NOFILES so check that both work before enabling the rlimit sandbox. - AC_MSG_CHECKING([if select and/or poll works with descriptor rlimit]) - AC_RUN_IFELSE( - [AC_LANG_PROGRAM([[ -#include -#ifdef HAVE_SYS_TIME_H -# include -#endif -#include -#ifdef HAVE_SYS_SELECT_H -# include -#endif -#ifdef HAVE_POLL_H -# include -#elif HAVE_SYS_POLL_H -# include -#endif -#include -#include -#include - ]],[[ - struct rlimit rl_zero; - int fd, r; - fd_set fds; - struct timeval tv; -#ifdef HAVE_POLL - struct pollfd pfd; -#endif - - fd = open("/dev/null", O_RDONLY); - FD_ZERO(&fds); - FD_SET(fd, &fds); - rl_zero.rlim_cur = rl_zero.rlim_max = 0; - setrlimit(RLIMIT_FSIZE, &rl_zero); - setrlimit(RLIMIT_NOFILE, &rl_zero); - tv.tv_sec = 1; - tv.tv_usec = 0; - r = select(fd+1, &fds, NULL, NULL, &tv); - if (r == -1) - exit(1); -#ifdef HAVE_POLL - pfd.fd = fd; - pfd.events = POLLIN; - r = poll(&pfd, 1, 1); - if (r == -1) - exit(2); -#endif - exit(0); - ]])], - [AC_MSG_RESULT([yes]) - select_works_with_rlimit=yes], - [AC_MSG_RESULT([no]) - select_works_with_rlimit=no], - [AC_MSG_WARN([cross compiling: assuming no]) - select_works_with_rlimit=no] - ) - - AC_MSG_CHECKING([if setrlimit(RLIMIT_NOFILE,{0,0}) works]) - AC_RUN_IFELSE( +AC_CACHE_CHECK( + [if setrlimit RLIMIT_FSIZE works], + [ssh_cv_rlimit_fsize_work], [ +AC_RUN_IFELSE( [AC_LANG_PROGRAM([[ #include #ifdef HAVE_SYS_TIME_H # include #endif #include -#include -#include ]],[[ struct rlimit rl_zero; int r; rl_zero.rlim_cur = rl_zero.rlim_max = 0; - r = setrlimit(RLIMIT_NOFILE, &rl_zero); - exit (r == -1 ? 1 : 0); - ]])], - [AC_MSG_RESULT([yes]) - rlimit_nofile_zero_works=yes], - [AC_MSG_RESULT([no]) - rlimit_nofile_zero_works=no], - [AC_MSG_WARN([cross compiling: assuming yes]) - rlimit_nofile_zero_works=yes] - ) - - AC_MSG_CHECKING([if setrlimit RLIMIT_FSIZE works]) - AC_RUN_IFELSE( - [AC_LANG_PROGRAM([[ -#include -#include -#include - ]],[[ - struct rlimit rl_zero; - - rl_zero.rlim_cur = rl_zero.rlim_max = 0; - exit(setrlimit(RLIMIT_FSIZE, &rl_zero) != 0); + r = setrlimit(RLIMIT_FSIZE, &rl_zero); + if (r == -1) return 1; ]])], - [AC_MSG_RESULT([yes])], - [AC_MSG_RESULT([no]) - AC_DEFINE(SANDBOX_SKIP_RLIMIT_FSIZE, 1, - [setrlimit RLIMIT_FSIZE works])], - [AC_MSG_WARN([cross compiling: assuming yes])] - ) -fi + [ssh_cv_rlimit_fsize_work=yes], + [ssh_cv_rlimit_fsize_work=no], + [ssh_cv_rlimit_fsize_work=cross] +) +]) +AS_IF([test $ssh_cv_rlimit_fsize_work = cross], [ + AC_MSG_WARN([cross compiling: assuming working setrlimit RLIMIT_FSIZE]) + ssh_cv_rlimit_fsize_work=yes +]) +AS_IF([test $ssh_cv_rlimit_fsize_work != yes], [ + AC_DEFINE([SANDBOX_SKIP_RLIMIT_FSIZE], [1], + [setrlimit RLIMIT_FSIZE works]) +]) if test "x$sandbox_arg" = "xpledge" || \ ( test -z "$sandbox_arg" && test "x$ac_cv_func_pledge" = "xyes" ) ; then @@ -3692,20 +3907,16 @@ AC_MSG_ERROR([capsicum sandbox requires cap_rights_limit function]) SANDBOX_STYLE="capsicum" AC_DEFINE([SANDBOX_CAPSICUM], [1], [Sandbox using capsicum]) +elif test "x$sandbox_arg" = "xsolaris" || \ + ( test -z "$sandbox_arg" && test "x$SOLARIS_PRIVS" = "xyes" ) ; then + SANDBOX_STYLE="solaris" + AC_DEFINE([SANDBOX_SOLARIS], [1], [Sandbox using Solaris/Illumos privileges]) elif test "x$sandbox_arg" = "xrlimit" || \ - ( test -z "$sandbox_arg" && test "x$ac_cv_func_setrlimit" = "xyes" && \ - test "x$select_works_with_rlimit" = "xyes" && \ - test "x$rlimit_nofile_zero_works" = "xyes" ) ; then + test -z "$sandbox_arg" && test "x$ac_cv_func_setrlimit" = "xyes" ; then test "x$ac_cv_func_setrlimit" != "xyes" && \ AC_MSG_ERROR([rlimit sandbox requires setrlimit function]) - test "x$select_works_with_rlimit" != "xyes" && \ - AC_MSG_ERROR([rlimit sandbox requires select to work with rlimit]) SANDBOX_STYLE="rlimit" AC_DEFINE([SANDBOX_RLIMIT], [1], [Sandbox using setrlimit(2)]) -elif test "x$sandbox_arg" = "xsolaris" || \ - ( test -z "$sandbox_arg" && test "x$SOLARIS_PRIVS" = "xyes" ) ; then - SANDBOX_STYLE="solaris" - AC_DEFINE([SANDBOX_SOLARIS], [1], [Sandbox using Solaris/Illumos privileges]) elif test -z "$sandbox_arg" || test "x$sandbox_arg" = "xno" || \ test "x$sandbox_arg" = "xnone" || test "x$sandbox_arg" = "xnull" ; then SANDBOX_STYLE="none" @@ -3719,7 +3930,7 @@ LIBS="$LIBS -liberty"; fi -# Check for long long datatypes +# Check for long long datatypes AC_CHECK_TYPES([long long, unsigned long long, long double]) # Check datatype sizes @@ -3727,29 +3938,28 @@ AC_CHECK_SIZEOF([int]) AC_CHECK_SIZEOF([long int]) AC_CHECK_SIZEOF([long long int]) +dnl Note AC_HEADER_TIME - outdated AC_CHECK_SIZEOF([time_t], [], [[ - #include - #ifdef HAVE_SYS_TIME_H - # include - #endif - #ifdef HAVE_TIME_H - # include - #endif - ]] -) +#ifdef HAVE_SYS_TIME_H +# include +#endif +#ifdef HAVE_TIME_H +# include +#endif +]]) # Sanity check long long for some platforms (AIX) if test "x$ac_cv_sizeof_long_long_int" = "x4" ; then ac_cv_sizeof_long_long_int=0 fi +# TODO: remove computation as C99 is required # compute LLONG_MIN and LLONG_MAX if we don't know them. -if test -z "$have_llong_max" && test -z "$have_long_long_max"; then +if test -z "$have_llong_max"; then AC_MSG_CHECKING([for max value of long long]) AC_RUN_IFELSE( [AC_LANG_PROGRAM([[ #include -#include /* Why is this so damn hard? */ #ifdef __GNUC__ # undef __GNUC__ @@ -3789,7 +3999,7 @@ long long i, llmin, llmax = 0; if((f = fopen(DATA,"w")) == NULL) - exit(1); + return 1; #if defined(LLONG_MIN) && defined(LLONG_MAX) fprintf(stderr, "Using system header for LLONG_MIN and LLONG_MAX\n"); @@ -3808,16 +4018,15 @@ || llmax - 1 > llmax || llmin == llmax || llmin == 0 || llmax == 0 || llmax < LONG_MAX || llmin > LONG_MIN) { fprintf(f, "unknown unknown\n"); - exit(2); + return 2; } if (fprint_ll(f, llmin) < 0) - exit(3); + return 3; if (fprint_ll(f, llmax) < 0) - exit(4); + return 4; if (fclose(f) < 0) - exit(5); - exit(0); + return 5; ]])], [ llong_min=`$AWK '{print $1}' conftest.llminmax` @@ -4038,7 +4247,7 @@ TYPE_SOCKLEN_T -AC_CHECK_TYPES([sig_atomic_t, sighandler_t], , , [#include ]) +AC_CHECK_TYPES([sig_atomic_t], , , [#include ]) AC_CHECK_TYPES([fsblkcnt_t, fsfilcnt_t], , , [ #include #ifdef HAVE_SYS_BITYPES_H @@ -4052,7 +4261,7 @@ #endif ]) -AC_CHECK_MEMBERS([struct statfs.f_files, struct statfs.f_flags], [], [], [[ +m4_define(statfs_includes,[[ #include #include #ifdef HAVE_SYS_BITYPES_H @@ -4071,10 +4280,21 @@ #include #endif ]]) +AC_CHECK_MEMBER([struct statfs.f_files], [], [], [statfs_includes]) +if test "x$ac_cv_member_struct_statfs_f_files" = "xyes" ; then + AC_DEFINE([USE_STRUCT_STATFS], [1], + [Define to 1 if you have the `statfs' structure]) +fi +AC_CHECK_MEMBERS([struct statfs.f_flags], [], [], [statfs_includes]) +dnl on Android netinet/in.h define __in_addr_t and arpa/inet.h define in_addr_t +AC_CHECK_HEADERS([arpa/inet.h]) AC_CHECK_TYPES([in_addr_t, in_port_t], , , [#include +#ifdef HAVE_ARPA_INET_H +#include +#endif #include ]) AC_CACHE_CHECK([for size_t], ac_cv_have_size_t, [ @@ -4191,13 +4411,12 @@ [define if you have struct in6_addr data type]) dnl Now check for sin6_scope_id - AC_CHECK_MEMBERS([struct sockaddr_in6.sin6_scope_id], , , - [ + AC_CHECK_MEMBERS([struct sockaddr_in6.sin6_scope_id], [], [], [[ #ifdef HAVE_SYS_TYPES_H #include #endif #include - ]) +]]) fi AC_CACHE_CHECK([for struct addrinfo], ac_cv_have_struct_addrinfo, [ @@ -4215,76 +4434,186 @@ [define if you have struct addrinfo data type]) fi -AC_CACHE_CHECK([for struct timeval], ac_cv_have_struct_timeval, [ - AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include ]], - [[ struct timeval tv; tv.tv_sec = 1;]])], - [ ac_cv_have_struct_timeval="yes" ], - [ ac_cv_have_struct_timeval="no" - ]) -]) -if test "x$ac_cv_have_struct_timeval" = "xyes" ; then - AC_DEFINE([HAVE_STRUCT_TIMEVAL], [1], [define if you have struct timeval]) - have_struct_timeval=1 -fi - -AC_CACHE_CHECK([for struct timespec], ac_cv_have_struct_timespec, [ - AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ - #ifdef HAVE_SYS_TIME_H - # include - #endif - #ifdef HAVE_TIME_H - # include - #endif - ]], - [[ struct timespec ts; ts.tv_sec = 1;]])], - [ ac_cv_have_struct_timespec="yes" ], - [ ac_cv_have_struct_timespec="no" - ]) -]) -if test "x$ac_cv_have_struct_timespec" = "xyes" ; then - AC_DEFINE([HAVE_STRUCT_TIMESPEC], [1], [define if you have struct timespec]) - have_struct_timespec=1 -fi +# useless checks as progmam code uses time* structures unconditionally +AC_CHECK_TYPES([struct timeval], [], [], [[ +#ifdef HAVE_SYS_TIME_H +# include +#endif +]]) +AC_CHECK_TYPES([struct timespec]) # We need int64_t or else certain parts of the compile will fail. if test "x$ac_cv_have_int64_t" = "xno" && \ test "x$ac_cv_sizeof_long_int" != "x8" && \ test "x$ac_cv_sizeof_long_long_int" = "x0" ; then - echo "OpenSSH requires int64_t support. Contact your vendor or install" - echo "an alternative compiler (I.E., GCC) before continuing." - echo "" - exit 1; -else -dnl test snprintf (broken on SCO w/gcc) - AC_RUN_IFELSE( - [AC_LANG_SOURCE([[ + AC_MSG_ERROR([*** $PACKAGE_NAME requires int64_t support. + Contact your vendor or install an alternative compiler (I.E., GCC) before continuing. + ]) +fi + + +dnl checks for working *snprintf ... +if test "x$ac_cv_func_snprintf" = "xyes" ; then +AC_CACHE_CHECK( + [whether snprintf correctly terminates long strings], + [ssh_cv_func_snprintf_long_string], + [AC_RUN_IFELSE([AC_LANG_PROGRAM([[ +#include + ]], [[ +char b[5]; +snprintf(b,5,"123456789"); +if (b[4] != '\0') + return 1; + ]])], + [ssh_cv_func_snprintf_long_string=yes], + [ssh_cv_func_snprintf_long_string=no], + [ssh_cv_func_snprintf_long_string=cross] +)]) +if test $ssh_cv_func_snprintf_long_string = cross ; then + AC_MSG_WARN([cross compiling: assuming snprintf correctly terminates long strings]) + ssh_cv_func_snprintf_long_string=yes +fi +if test $ssh_cv_func_snprintf_long_string != yes ; then + ssh_snprintf_broken=yes + AC_MSG_WARN([*** Broken function snprintf() - does not correctly terminates long strings]) +fi +fi + +dnl package depend on vsnprintf returning the right thing on overflow: +dnl the number of characters it tried to create (as per SUSv3) +if test "x$ac_cv_func_vsnprintf" = "xyes" && test "x$ssh_snprintf_broken" != xyes ; then +AC_CACHE_CHECK( + [whether vsnprintf returns correct values on overflow], + [ssh_cv_func_vsnprintf_overflow], + [AC_RUN_IFELSE([AC_LANG_PROGRAM([[ +#include +#include +#include + +int +x_snprintf(char *str, size_t count, const char *fmt, ...) { + size_t ret; + va_list ap; + + va_start(ap, fmt); + ret = vsnprintf(str, count, fmt, ap); + va_end(ap); + + return ret; +} + ]], [[ +char x[1]; +if (x_snprintf(x, 1, "%s %d", "hello", 12345) != 11) + return 1; +if (x_snprintf(NULL, 0, "%s %d", "hello", 12345) != 11) + return 1; + ]])], + [ssh_cv_func_vsnprintf_overflow=yes], + [ssh_cv_func_vsnprintf_overflow=no], + [ssh_cv_func_vsnprintf_overflow=cross] +)]) +if test $ssh_cv_func_vsnprintf_overflow = cross ; then + AC_MSG_WARN([cross compiling: assuming vsnprintf() returns correct values on overflow]) + ssh_cv_func_vsnprintf_overflow=yes +fi +if test $ssh_cv_func_vsnprintf_overflow != yes ; then + ssh_snprintf_broken=yes + AC_MSG_WARN([*** Broken function vsnprintf() - does not returns correct values on overflow]) +fi +fi + +dnl test snprintf format %ldd (broken on SCO w/gcc) +if test "x$ac_cv_func_snprintf" = "xyes" && test "x$ssh_snprintf_broken" != xyes ; then +AC_CACHE_CHECK( + [whether snprintf understands %lld format], + [ssh_cv_func_snprintf_fmt_lld], + [AC_RUN_IFELSE([AC_LANG_PROGRAM([[ #include -#include #include -#ifdef HAVE_SNPRINTF -int main(void) -{ - char buf[50]; - char expected_out[50]; - int mazsize = 50 ; + ]], [[ +char buf[50]; +char expected_out[50]; +int mazsize = 50 ; #if (SIZEOF_LONG_INT == 8) - long int num = 0x7fffffffffffffff; +long int num = 0x7fffffffffffffff; #else - long long num = 0x7fffffffffffffffll; +long long num = 0x7fffffffffffffffll; #endif - strcpy(expected_out, "9223372036854775807"); - snprintf(buf, mazsize, "%lld", num); - if(strcmp(buf, expected_out) != 0) - exit(1); - exit(0); -} -#else -int main(void) { exit(0); } +strcpy(expected_out, "9223372036854775807"); +snprintf(buf, mazsize, "%lld", num); +if (strcmp(buf, expected_out) != 0) + return 1; + ]])], + [ssh_cv_func_snprintf_fmt_lld=yes], + [ssh_cv_func_snprintf_fmt_lld=no], + [ssh_cv_func_snprintf_fmt_lld=cross] +)]) +if test $ssh_cv_func_snprintf_fmt_lld = cross ; then + AC_MSG_WARN([cross compiling: assuming snprintf() understands %lld format]) + ssh_cv_func_snprintf_fmt_lld=yes +fi +if test $ssh_cv_func_snprintf_fmt_lld != yes ; then + ssh_snprintf_broken=yes + AC_MSG_WARN([*** Outdated function snprintf() - does not understand %lld format]) +fi +fi + +if test "x$ac_cv_func_snprintf" = "xyes" && test "x$ssh_snprintf_broken" != xyes ; then +AC_CACHE_CHECK( + [whether snprintf understands %zu format], + [ssh_cv_func_snprintf_fmt_zu], + [AC_RUN_IFELSE([AC_LANG_PROGRAM([[ +#include +#include +#include + ]], [[ +size_t a = 1, b = 2; +char z[128]; +snprintf(z, sizeof z, "%zu%zu", a, b); +if (strcmp(z, "12") != 0) + return 1; + ]])], + [ssh_cv_func_snprintf_fmt_zu=yes], + [ssh_cv_func_snprintf_fmt_zu=no], + [ssh_cv_func_snprintf_fmt_zu=cross] +)]) +if test $ssh_cv_func_snprintf_fmt_zu = cross ; then + AC_MSG_WARN([cross compiling: assuming snprintf() understands %zu format]) + ssh_cv_func_snprintf_fmt_zu=yes +fi +if test $ssh_cv_func_snprintf_fmt_zu != yes ; then + ssh_snprintf_broken=yes + AC_MSG_WARN([*** Outdated function snprintf() - does not understand %zu format]) +fi +fi + +dnl On systems where [v]snprintf is broken, but is declared in stdio, +dnl check that the fmt argument is const char * or just char *. +if test "x$ssh_snprintf_broken" = xyes ; then + AC_DEFINE([BROKEN_SNPRINTF], [1], + [Define to 1 if snprintf is broken or outdated (lack %zu, %ld and etc.)]) + AC_MSG_CHECKING([whether snprintf declare const char *fmt]) + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ +#include +int snprintf(char *a, size_t b, const char *c, ...) +#ifndef NO_ATTRIBUTE_ON_PROTOTYPE_ARGS +__attribute__ ((__format__ (__printf__, 3, 4))) #endif - ]])], [ true ], [ AC_DEFINE([BROKEN_SNPRINTF]) ], - AC_MSG_WARN([cross compiling: Assuming working snprintf()]) +; +int snprintf(char *a, size_t b, const char *c, ...) { return 0; } + ]], [[ +snprintf(0, 0, 0); + ]])], + [ssh_snprintf_const_fmt=yes], + [ssh_snprintf_const_fmt=no] ) + AC_MSG_RESULT([$ssh_snprintf_const_fmt]) fi +if test "x$ssh_snprintf_const_fmt" = xyes ; then + AC_DEFINE([SNPRINTF_CONST], [const], + [Define as const if broken snprintf() declare const char *fmt]) +fi + dnl Checks for structure members OSSH_CHECK_HEADER_FOR_FIELD([ut_host], [utmp.h], [HAVE_HOST_IN_UTMP]) @@ -4314,6 +4643,10 @@ [], [], [[ #include #include +/* Avoid inappropriate definition from Android unified headers + * to impact detection of structure members. + */ +#undef pw_gecos ]]) AC_CHECK_MEMBER([struct __res_state.retrans], [], [AC_DEFINE([__res_state], [state], @@ -4329,14 +4662,12 @@ ]]) AC_CHECK_MEMBER([struct sockaddr_in.sin_len], - [AC_DEFINE([SOCK_HAS_LEN], [1], [sockaddr_in has sin_len])], - [], - [AC_LANG_SOURCE([[ + [AC_DEFINE([SOCK_HAS_LEN], [1], [sockaddr_in has sin_len])], + [], [[ #include #include #include - ]])] -) +]]) AC_CACHE_CHECK([for ss_family field in struct sockaddr_storage], ac_cv_have_ss_family_in_struct_ss, [ @@ -4373,15 +4704,13 @@ #include #include #include -#include ]], [[ #ifdef msg_accrights #error "msg_accrights is a macro" -exit(1); +return 1; #endif struct msghdr m; m.msg_accrights = 0; -exit(0); ]])], [ ac_cv_have_accrights_in_msghdr="yes" ], [ ac_cv_have_accrights_in_msghdr="no" ] @@ -4413,7 +4742,9 @@ AC_MSG_CHECKING([if fsid_t has member val]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include +#ifdef HAVE_SYS_STATVFS_H #include +#endif ]], [[ fsid_t t; t.val[0] = 0; ]])], [ AC_MSG_RESULT([yes]) AC_DEFINE([FSID_HAS_VAL], [1], [fsid_t has member val]) ], @@ -4422,7 +4753,9 @@ AC_MSG_CHECKING([if f_fsid has member __val]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include +#ifdef HAVE_SYS_STATVFS_H #include +#endif ]], [[ fsid_t t; t.__val[0] = 0; ]])], [ AC_MSG_RESULT([yes]) AC_DEFINE([FSID_HAS___VAL], [1], [fsid_t has member __val]) ], @@ -4435,15 +4768,13 @@ #include #include #include -#include ]], [[ #ifdef msg_control #error "msg_control is a macro" -exit(1); +return 1; #endif struct msghdr m; m.msg_control = 0; -exit(0); ]])], [ ac_cv_have_control_in_msghdr="yes" ], [ ac_cv_have_control_in_msghdr="no" ] @@ -4593,8 +4924,9 @@ #include ]) AC_CHECK_MEMBER([HEADER.ad], [AC_DEFINE([HAVE_HEADER_AD], [1], - [Define if HEADER.ad exists in arpa/nameser.h])], , - [#include ]) + [Define if HEADER.ad exists in arpa/nameser.h])], + [], + [[#include ]]) ]) AC_MSG_CHECKING([if struct __res_state _res is an extern]) @@ -4642,146 +4974,148 @@ AC_SUBST([SSHDLIBS]) # Check whether user wants Kerberos 5 support +AC_DEFUN([SSH_KRB5_IMPLEMENTATION], +[ + AC_MSG_CHECKING([whether we are using Heimdal]) + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ +#include + ]], [[ +char *tmp = heimdal_version; + ]])], + [ AC_MSG_RESULT([yes]) + krb5_implementation=heimdal], + [ AC_MSG_RESULT([no]) + krb5_implementation=mit + ]) +]) + KRB5_MSG="no" AC_ARG_WITH([kerberos5], - [ --with-kerberos5=PATH Enable Kerberos 5 support], - [ if test "x$withval" != "xno" ; then - if test "x$withval" = "xyes" ; then + [AS_HELP_STRING([--with-kerberos5@<:@=PATH@:>@], + [Enable Kerberos 5 support])], + [AS_IF([test "x$withval" != "xno"], [ + defect_krb5=config + AS_IF([test "x$withval" = "xyes"], [ KRB5ROOT="/usr/local" - else + AS_IF([test "x$PKGCONFIG" != "xno"], [ + defect_krb5=package + ]) + ], [ KRB5ROOT=${withval} - fi + ]) AC_DEFINE([KRB5], [1], [Define if you want Kerberos 5 support]) KRB5_MSG="yes" - use_pkgconfig_for_krb5= - if test "x$PKGCONFIG" != "xno"; then + AS_IF([test "x$defect_krb5" == "xpackage"], [ AC_MSG_CHECKING([if $PKGCONFIG knows about kerberos5]) - if "$PKGCONFIG" krb5; then + AS_IF(["$PKGCONFIG" krb5], [ AC_MSG_RESULT([yes]) - use_pkgconfig_for_krb5=yes - else + ], [ AC_MSG_RESULT([no]) - fi - fi - if test "x$use_pkgconfig_for_krb5" = "xyes"; then + defect_krb5=config + ]) + ]) + AS_IF([test "x$defect_krb5" == "xconfig"], [ + AC_PATH_TOOL([KRB5CONF], [krb5-config], + [false], + [$KRB5ROOT/bin:$PATH]) + AS_IF([$KRB5CONF --version > /dev/null 2>&1], [ + ], [ + defect_krb5=direct + ]) + ]) + + AS_IF([test "x$defect_krb5" = "xpackage"], [ K5CFLAGS=`$PKGCONFIG --cflags krb5` K5LIBS=`$PKGCONFIG --libs krb5` CPPFLAGS="$CPPFLAGS $K5CFLAGS" AC_MSG_CHECKING([for gssapi support]) - if "$PKGCONFIG" krb5-gssapi; then + AS_IF(["$PKGCONFIG" krb5-gssapi], [ AC_MSG_RESULT([yes]) - AC_DEFINE([GSSAPI], [1], - [Define this if you want GSSAPI - support in the version 2 protocol]) + AC_DEFINE([GSSAPI], [1]) GSSCFLAGS="`$PKGCONFIG --cflags krb5-gssapi`" GSSLIBS="`$PKGCONFIG --libs krb5-gssapi`" - CPPFLAGS="$CPPFLAGS $GSSCFLAGS" - else + AS_IF([test "x$K5CFLAGS" != "x$GSSCFLAGS"], [ + CPPFLAGS="$CPPFLAGS $GSSCFLAGS" + ]) + ], [ AC_MSG_RESULT([no]) - fi - AC_MSG_CHECKING([whether we are using Heimdal]) - AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include - ]], [[ char *tmp = heimdal_version; ]])], - [ AC_MSG_RESULT([yes]) - AC_DEFINE([HEIMDAL], [1], - [Define this if you are using the Heimdal - version of Kerberos V5]) ], - [AC_MSG_RESULT([no]) ]) - else - AC_PATH_TOOL([KRB5CONF], [krb5-config], - [$KRB5ROOT/bin/krb5-config], - [$KRB5ROOT/bin:$PATH]) - if test -x $KRB5CONF ; then - K5CFLAGS="`$KRB5CONF --cflags`" - K5LIBS="`$KRB5CONF --libs`" - CPPFLAGS="$CPPFLAGS $K5CFLAGS" - AC_MSG_CHECKING([for gssapi support]) - if $KRB5CONF | grep gssapi >/dev/null ; then - AC_MSG_RESULT([yes]) - AC_DEFINE([GSSAPI], [1], - [Define this if you want GSSAPI - support in the version 2 protocol]) - GSSCFLAGS="`$KRB5CONF --cflags gssapi`" - GSSLIBS="`$KRB5CONF --libs gssapi`" + SSH_KRB5_IMPLEMENTATION + ], + [test "x$defect_krb5" == "xconfig"], [ + K5CFLAGS="`$KRB5CONF --cflags`" + K5LIBS="`$KRB5CONF --libs`" + CPPFLAGS="$CPPFLAGS $K5CFLAGS" + + AC_MSG_CHECKING([for gssapi support]) + AS_IF([$KRB5CONF | grep gssapi >/dev/null], [ + AC_MSG_RESULT([yes]) + AC_DEFINE([GSSAPI], [1]) + GSSCFLAGS="`$KRB5CONF --cflags gssapi`" + GSSLIBS="`$KRB5CONF --libs gssapi`" + AS_IF([test "x$K5CFLAGS" != "x$GSSCFLAGS"], [ CPPFLAGS="$CPPFLAGS $GSSCFLAGS" - else - AC_MSG_RESULT([no]) - fi - AC_MSG_CHECKING([whether we are using Heimdal]) - AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include - ]], [[ char *tmp = heimdal_version; ]])], - [ AC_MSG_RESULT([yes]) - AC_DEFINE([HEIMDAL], [1], - [Define this if you are using the Heimdal - version of Kerberos V5]) ], - [AC_MSG_RESULT([no]) - ]) - else - CPPFLAGS="$CPPFLAGS -I${KRB5ROOT}/include" - LDFLAGS="$LDFLAGS -L${KRB5ROOT}/lib" - AC_MSG_CHECKING([whether we are using Heimdal]) - AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include - ]], [[ char *tmp = heimdal_version; ]])], - [ AC_MSG_RESULT([yes]) - AC_DEFINE([HEIMDAL]) - K5LIBS="-lkrb5" - K5LIBS="$K5LIBS -lcom_err -lasn1" - AC_CHECK_LIB([roken], [net_write], - [K5LIBS="$K5LIBS -lroken"]) - AC_CHECK_LIB([des], [des_cbc_encrypt], - [K5LIBS="$K5LIBS -ldes"]) - ], [ AC_MSG_RESULT([no]) - K5LIBS="-lkrb5 -lk5crypto -lcom_err" ]) + ], [ + AC_MSG_RESULT([no]) + ]) + + SSH_KRB5_IMPLEMENTATION + ], [ + CPPFLAGS="$CPPFLAGS -I${KRB5ROOT}/include" + LDFLAGS="$LDFLAGS -L${KRB5ROOT}/lib" + + SSH_KRB5_IMPLEMENTATION + AS_IF([test "x$krb5_implementation" = "xheimdal"], [ + K5LIBS="-lkrb5 -lasn1 -lroken -lcom_err" + dnl dn_expand required by roken library AC_SEARCH_LIBS([dn_expand], [resolv]) + ], [ + K5LIBS="-lkrb5 -lk5crypto -lcom_err" + ]) - AC_CHECK_LIB([gssapi_krb5], [gss_init_sec_context], - [ AC_DEFINE([GSSAPI]) - GSSLIBS="-lgssapi_krb5" ], - [ AC_CHECK_LIB([gssapi], [gss_init_sec_context], - [ AC_DEFINE([GSSAPI]) - GSSLIBS="-lgssapi" ], - [ AC_CHECK_LIB([gss], [gss_init_sec_context], - [ AC_DEFINE([GSSAPI]) - GSSLIBS="-lgss" ], - AC_MSG_WARN([Cannot find any suitable gss-api library - build may fail])) - ]) + AC_CHECK_LIB([gssapi_krb5], [gss_init_sec_context], + [ AC_DEFINE([GSSAPI], [1]) + GSSLIBS="-lgssapi_krb5" ], + [ AC_CHECK_LIB([gssapi], [gss_init_sec_context], + [ AC_DEFINE([GSSAPI], [1]) + GSSLIBS="-lgssapi" ], + [ AC_CHECK_LIB([gss], [gss_init_sec_context], + [ AC_DEFINE([GSSAPI], [1]) + GSSLIBS="-lgss" ], + AC_MSG_WARN([Cannot find any suitable gss-api library - build may fail])) ]) + ]) - AC_CHECK_HEADER([gssapi.h], , - [ unset ac_cv_header_gssapi_h - CPPFLAGS="$CPPFLAGS -I${KRB5ROOT}/include/gssapi" - AC_CHECK_HEADERS([gssapi.h], , - AC_MSG_WARN([Cannot find any suitable gss-api header - build may fail]) - ) - ] - ) - - oldCPP="$CPPFLAGS" - CPPFLAGS="$CPPFLAGS -I${KRB5ROOT}/include/gssapi" - AC_CHECK_HEADER([gssapi_krb5.h], , - [ CPPFLAGS="$oldCPP" ]) + AS_IF([test -n "$rpath_opt"], [ + LDFLAGS="$LDFLAGS $rpath_opt$KRB5ROOT/lib" + ]) + AS_IF([test ! -z "$blibpath"], [ + blibpath="$blibpath:$KRB5ROOT/lib" + ]) + ]) - fi - fi - if test -n "${rpath_opt}" ; then - LDFLAGS="$LDFLAGS ${rpath_opt}${KRB5ROOT}/lib" - fi - if test ! -z "$blibpath" ; then - blibpath="$blibpath:${KRB5ROOT}/lib" - fi + AS_IF([test "x$krb5_implementation" = "xheimdal"], [ + AC_DEFINE([HEIMDAL], [1], + [Define this if you are using the Heimdal version of Kerberos V5]) + ]) AC_CHECK_HEADERS([gssapi.h gssapi/gssapi.h]) AC_CHECK_HEADERS([gssapi_krb5.h gssapi/gssapi_krb5.h]) AC_CHECK_HEADERS([gssapi_generic.h gssapi/gssapi_generic.h]) - AC_SEARCH_LIBS([k_hasafs], [kafs], [AC_DEFINE([USE_AFS], [1], - [Define this if you want to use libkafs' AFS support])]) + saved_LIBS="$LIBS" + LIBS="$LIBS $K5LIBS" + AC_CHECK_LIB([kafs], [k_hasafs], [ + # if -L is from "config" => append library :( + K5LIBS="$K5LIBS -lkafs" + AC_DEFINE([USE_AFS], [1], [Define this if you want to use libkafs' AFS support]) + ]) + LIBS="$saved_LIBS" AC_CHECK_DECLS([GSS_C_NT_HOSTBASED_SERVICE], [], [], [[ #ifdef HAVE_GSSAPI_H @@ -4800,13 +5134,92 @@ LIBS="$LIBS $K5LIBS" AC_CHECK_FUNCS([krb5_cc_new_unique krb5_get_error_message krb5_free_error_message]) LIBS="$saved_LIBS" - - fi - ] + ])] ) AC_SUBST([GSSLIBS]) AC_SUBST([K5LIBS]) -AC_SUBST([CHANNELLIBS]) + + +# Postponed OpenSSL checks as ssl library may depend on kerberos. +AS_IF([$ssh_ocsp], [ + AC_CHECK_FUNCS([OCSP_sendreq_bio], + [ + AC_CHECK_HEADER([openssl/ocsp.h], + [], + [ + ssh_ocsp=false + AC_MSG_ERROR([OCSP header not found]) + ]) + ], + [ + ssh_ocsp=false + AC_MSG_WARN([Cannot find OCSP functions - OCSP is disabled]) + ]) +]) +AS_IF([$ssh_ocsp], [ + save_LIBS="$LIBS" + AC_MSG_CHECKING([how to link programs using OpenSSL OCSP functions]) + AS_IF([test -n "$K5LIBS"], [ + SSL_K5LIBS="$K5LIBS" + SSL_K5LIBS_MIT= + SSL_K5LIBS_HEIMDAL= + ], [ + SSL_K5LIBS= + SSL_K5LIBS_MIT="-lkrb5 -lk5crypto -lcom_err" + SSL_K5LIBS_HEIMDAL="-lkrb5 -lroken -lasn1 -lcom_err" + ]) + link_SSL=false + # first check is without extra libraries + link_SSL_first_pass=false + for L in "" "$SSL_K5LIBS" "$SSL_K5LIBS_MIT" "$SSL_K5LIBS_HEIMDAL"; do + AS_IF([$link_SSL_first_pass && test -z "$L"], [ + continue + ]) + LIBS="-lssl $L $CRYPTO_LIBS $save_LIBS" + AC_LINK_IFELSE([ + AC_LANG_PROGRAM([[ +#include + ]], [[ +#ifdef HAVE_OPENSSL_INIT_CRYPTO + OPENSSL_init_ssl(0, NULL); +#else + SSL_library_init(); +#endif + ]])], + [link_SSL=:] + ) + link_SSL_first_pass=: + $link_SSL && break + done + AS_IF([$link_SSL], [ + LIBOCSP="-lssl $L" + AC_MSG_RESULT([$LIBOCSP]) + ], [ + AC_MSG_RESULT([fail]) + AC_MSG_ERROR([cannot link with OpenSSL ssl library]) + ]) + # check for openssl ssl 1.1+ functions ... + AC_CHECK_FUNCS([ \ + TLS_client_method \ + ]) + LIBS="$save_LIBS" + + AC_DEFINE( + [SSH_OCSP_ENABLED], [1], + [Define if you want to validate X.509 certificates with OCSP]) + OCSP_ON='' + OCSP_OFF='#' + OCSP_MSG=yes +], [ + LIBOCSP= + OCSP_ON='#' + OCSP_OFF='' + OCSP_MSG=no +]) +AC_SUBST([LIBOCSP]) +AC_SUBST([OCSP_ON]) +AC_SUBST([OCSP_OFF]) + # Looking for programs, paths and files @@ -4889,8 +5302,6 @@ AC_RUN_IFELSE( [AC_LANG_PROGRAM([[ #include -#include -#include #ifdef HAVE_PATHS_H #include #endif @@ -4904,22 +5315,20 @@ fd = fopen(DATA,"w"); if(fd == NULL) - exit(1); + return 1; #if defined (_PATH_MAILDIR) if ((rc = fprintf(fd ,"_PATH_MAILDIR:%s\n", _PATH_MAILDIR)) <0) - exit(1); + return 1; #elif defined (MAILDIR) if ((rc = fprintf(fd ,"MAILDIR:%s\n", MAILDIR)) <0) - exit(1); + return 1; #elif defined (_PATH_MAIL) if ((rc = fprintf(fd ,"_PATH_MAIL:%s\n", _PATH_MAIL)) <0) - exit(1); + return 1; #else - exit (2); + return 2; #endif - - exit(0); ]])], [ maildir_what=`awk -F: '{print $1}' conftest.maildir` @@ -4947,21 +5356,20 @@ ] ) # maildir -if test ! -z "$cross_compiling" && test "x$cross_compiling" = "xyes"; then +if test "${ac_cv_file__dev_ptmx+set}" != set && test "x$cross_compiling" = "xyes"; then AC_MSG_WARN([cross compiling: Disabling /dev/ptmx test]) - disable_ptmx_check=yes -fi -if test -z "$no_dev_ptmx" ; then - if test "x$disable_ptmx_check" != "xyes" ; then - AC_CHECK_FILE(["/dev/ptmx"], - [ - AC_DEFINE_UNQUOTED([HAVE_DEV_PTMX], [1], - [Define if you have /dev/ptmx]) - have_dev_ptmx=1 - ] - ) + ac_cv_file__dev_ptmx=cross +else + if test "${ac_cv_file__dev_ptmx+set}" = set ; then + AC_CACHE_CHECK([for "/dev/ptmx"],[ac_cv_file__dev_ptmx]) + else + AC_CHECK_FILE(["/dev/ptmx"]) fi fi +if test "x$ac_cv_file__dev_ptmx" = xyes ; then + AC_DEFINE_UNQUOTED([HAVE_DEV_PTMX], [1], + [Define if you have /dev/ptmx]) +fi if test ! -z "$cross_compiling" && test "x$cross_compiling" != "xyes"; then AC_CHECK_FILE(["/dev/ptc"], @@ -5008,6 +5416,19 @@ fi AC_SUBST([mansubdir]) +# Check whether to enable MD5 passwords +MD5_MSG="no" +AC_ARG_WITH([md5-passwords], + [ --with-md5-passwords Enable use of MD5 passwords], + [ + if test "x$withval" != "xno" ; then + AC_DEFINE([HAVE_MD5_PASSWORDS], [1], + [Define if you want to allow MD5 passwords]) + MD5_MSG="yes" + fi + ] +) + # Whether to disable shadow password support AC_ARG_WITH([shadow], [ --without-shadow Disable shadow password support], @@ -5121,7 +5542,6 @@ [AC_LANG_PROGRAM([[ /* find out what STDPATH is */ #include -#include #ifdef HAVE_PATHS_H # include #endif @@ -5142,12 +5562,10 @@ fd = fopen(DATA,"w"); if(fd == NULL) - exit(1); + return 1; if ((rc = fprintf(fd,"%s", _PATH_STDPATH)) < 0) - exit(1); - - exit(0); + return 1; ]])], [ user_path=`cat conftest.stdpath` ], [ user_path="/usr/bin:/bin:/usr/sbin:/sbin" ], @@ -5168,8 +5586,8 @@ if test $? -ne 0 ; then echo $user_path | grep "^$t_bindir" > /dev/null 2>&1 if test $? -ne 0 ; then - user_path=$user_path:$t_bindir - AC_MSG_RESULT([Adding $t_bindir to USER_PATH so scp will work]) + user_path=$t_bindir:$user_path + AC_MSG_RESULT([Prepend $t_bindir to USER_PATH so scp will work]) fi fi fi ] @@ -5232,6 +5650,25 @@ ] ) + +# enable LDAP queries +LDAP_MSG=no +AC_WITH_LDAP +AS_IF([test "x$LDAP_ON" = "x"], [ + LDAP_MSG=yes + AC_CHECK_PROGS([LDAPADD], + [openldapadd ldapadd], [false], + [PATH="$LDAP_BINDIR:$PATH"]) +]) +AC_LDAP_FUNCS([\ + ldap_initialize \ + ldap_parse_result \ + ldap_sasl_bind_s \ + ldap_search_ext_s \ + ldap_unbind_ext_s \ +]) + + # Where to place sshd.pid piddir=/var/run # make sure the directory exists @@ -5279,12 +5716,17 @@ AC_ARG_ENABLE([utmpx], [ --disable-utmpx disable use of utmpx even if detected [no]], [ - if test "x$enableval" = "xno" ; then - AC_DEFINE([DISABLE_UTMPX], [1], - [Define if you don't want to use utmpx]) - fi + ssh_disable_utmpx=$enableval ] ) +if test no = $ac_cv_header_utmpx_h; then + dnl Always disable utmpx if missing header utmpx.h (Android) + ssh_disable_utmpx=yes +fi +if test yes = $ssh_disable_utmpx; then + AC_DEFINE([DISABLE_UTMPX], [1], + [Define if you don't want to use utmpx]) +fi AC_ARG_ENABLE([wtmp], [ --disable-wtmp disable use of wtmp even if detected [no]], [ @@ -5310,16 +5752,26 @@ fi ] ) + +dnl checks for utmp functions AC_ARG_ENABLE([pututline], - [ --disable-pututline disable use of pututline() etc. ([uw]tmp) [no]], - [ - if test "x$enableval" = "xno" ; then - AC_DEFINE([DISABLE_PUTUTLINE], [1], - [Define if you don't want to use pututline() - etc. to write [uw]tmp]) - fi - ] -) + [AS_HELP_STRING([--disable-pututline], + [disable use of pututline() etc. ([uw]tmp) [no]])], + [ssh_enable_pututline=$enableval], + [ssh_enable_pututline=yes] +) +AS_IF([test $ssh_enable_pututline = no], [ + AC_DEFINE([DISABLE_PUTUTLINE], [1], + [Define if you don't want to use pututline() etc. to write [uw]tmp]) +], [ + AC_CHECK_FUNCS([endutent pututline setutent]) + AC_CHECK_DECLS([endutent, pututline], [], [], [ +#ifdef HAVE_UTMP_H +# include +#endif + ]) +]) + AC_ARG_ENABLE([pututxline], [ --disable-pututxline disable use of pututxline() etc. ([uw]tmpx) [no]], [ @@ -5410,6 +5862,10 @@ #ifdef HAVE_PATHS_H # include #endif +/* Compatibility names for the strings of the canonical file names */ +#ifndef UTMP_FILE +#define UTMP_FILE _PATH_UTMP +#endif ]], [[ char *utmp = UTMP_FILE; ]])], [ AC_MSG_RESULT([yes]) ], [ AC_MSG_RESULT([no]) @@ -5440,6 +5896,10 @@ #ifdef HAVE_PATHS_H # include #endif +/* Compatibility names for the strings of the canonical file names */ +#ifndef WTMP_FILE +#define WTMP_FILE _PATH_WTMP +#endif ]], [[ char *wtmp = WTMP_FILE; ]])], [ AC_MSG_RESULT([yes]) ], [ AC_MSG_RESULT([no]) @@ -5497,7 +5957,7 @@ if test x$SKIP_DISABLE_LASTLOG_DEFINE != "xyes" ; then AC_DEFINE([DISABLE_LASTLOG]) fi - ], [ + ], [[ #ifdef HAVE_SYS_TYPES_H #include #endif @@ -5510,12 +5970,12 @@ #ifdef HAVE_LASTLOG_H #include #endif - ]) + ]]) AC_CHECK_MEMBER([struct utmp.ut_line], [], [ AC_DEFINE([DISABLE_UTMP]) AC_DEFINE([DISABLE_WTMP]) - ], [ + ], [[ #ifdef HAVE_SYS_TYPES_H #include #endif @@ -5528,7 +5988,7 @@ #ifdef HAVE_LASTLOG_H #include #endif - ]) + ]]) dnl Adding -Werror to CFLAGS early prevents configure tests from running. dnl Add now. @@ -5539,26 +5999,26 @@ else TEST_SSH_IPV6=yes fi -AC_CHECK_DECL([BROKEN_GETADDRINFO], [TEST_SSH_IPV6=no]) +AC_CHECK_DECL([BROKEN_GETADDRINFO], [TEST_SSH_IPV6=no]) AC_SUBST([TEST_SSH_IPV6], [$TEST_SSH_IPV6]) AC_SUBST([TEST_SSH_UTF8], [$TEST_SSH_UTF8]) AC_SUBST([TEST_MALLOC_OPTIONS], [$TEST_MALLOC_OPTIONS]) AC_SUBST([UNSUPPORTED_ALGORITHMS], [$unsupported_algorithms]) -AC_SUBST([DEPEND], [$(cat $srcdir/.depend)]) CFLAGS="${CFLAGS} ${CFLAGS_AFTER}" LDFLAGS="${LDFLAGS} ${LDFLAGS_AFTER}" -# Make a copy of CFLAGS/LDFLAGS without PIE options. -LDFLAGS_NOPIE=`echo "$LDFLAGS" | sed 's/ -pie//'` -CFLAGS_NOPIE=`echo "$CFLAGS" | sed 's/ -fPIE//'` -AC_SUBST([LDFLAGS_NOPIE]) -AC_SUBST([CFLAGS_NOPIE]) - AC_EXEEXT AC_CONFIG_FILES([Makefile buildpkg.sh opensshd.init openssh.xml \ openbsd-compat/Makefile openbsd-compat/regress/Makefile \ + tests/env tests/CA/Makefile \ survey.sh]) +AS_IF([test "x$OPENSSL_FIPS_MODE" = "xyes"], [ + AS_IF([test -n "$FIPSLD_CC"], [ + CC='FIPSLD_CC=$(FIPSLD_CC) '$CC + LD='FIPSLD_CC=$(FIPSLD_CC) '$LD + ]) +]) AC_OUTPUT # Print summary of options @@ -5576,10 +6036,11 @@ J=`eval echo ${superuser_path}` ; J=`eval echo ${J}` echo "" -echo "OpenSSH has been configured with the following options:" +echo "$PACKAGE_NAME has been configured with the following options:" echo " User binaries: $B" echo " System binaries: $C" echo " Configuration files: $D" +echo " CA root: $sshcadir" echo " Askpass program: $E" echo " Manual pages: $F" echo " PID file: $G" @@ -5602,8 +6063,14 @@ echo " OSF SIA support: $SIA_MSG" echo " KerberosV support: $KRB5_MSG" echo " SELinux support: $SELINUX_MSG" +echo " PKCS#11 support: $PKCS11_MSG" +echo " TCP Wrappers support: $TCPW_MSG" +echo " MD5 password support: $MD5_MSG" +echo " OCSP support: $OCSP_MSG" +echo " LDAP queries: $LDAP_MSG" echo " libedit support: $LIBEDIT_MSG" echo " libldns support: $LDNS_MSG" +echo " Compression support: $ZLIB_MSG" echo " Solaris process contract support: $SPC_MSG" echo " Solaris project support: $SP_MSG" echo " Solaris privilege support: $SPP_MSG" @@ -5612,23 +6079,22 @@ echo " BSD Auth support: $BSD_AUTH_MSG" echo " Random number source: $RAND_MSG" echo " Privsep sandbox style: $SANDBOX_STYLE" -echo " PKCS#11 support: $enable_pkcs11" -echo " U2F/FIDO support: $enable_sk" +echo " FIPS capable build: $OPENSSL_FIPS_MODE" echo "" echo " Host: ${host}" +AS_IF([test "x$OPENSSL_FIPS_MODE" = "xyes"], [ +echo " Actual compiler: $FIPSLD_CC" +]) echo " Compiler: ${CC}" echo " Compiler flags: ${CFLAGS}" echo "Preprocessor flags: ${CPPFLAGS}" echo " Linker flags: ${LDFLAGS}" echo " Libraries: ${LIBS}" -if test ! -z "${CHANNELLIBS}"; then -echo " +for channels: ${CHANNELLIBS}" -fi -if test ! -z "${LIBFIDO2}"; then -echo " +for FIDO2: ${LIBFIDO2}" -fi +AS_IF([$ssh_ocsp], [ +echo " OCSP libraries: $LIBOCSP" +]) if test ! -z "${SSHDLIBS}"; then echo " +for sshd: ${SSHDLIBS}" fi @@ -5640,6 +6106,25 @@ echo "" fi +if test "x$LDAP_MSG" = "xyes" ; then +echo "Extra LDAP flags:" +echo " LDAP compiler flags: ${LDAP_CFLAGS}" +echo "LDAP preprocessor flags: ${LDAP_CPPFLAGS}" +echo " LDAP linker flags: ${LDAP_LDFLAGS}" +echo " LDAP libraries: ${LDAP_LIBS}" +echo "" +echo "LDAP paths(used only in tests):" +echo " LDAP sysconfig dir: ${LDAP_SYSCONFDIR}" +echo " LDAP libexec dir: ${LDAP_LIBEXECDIR}" +echo " LDAP bin dir: ${LDAP_BINDIR}" +echo "" +fi + +AS_IF([test "x$OPENSSL_FIPS_MODE" = "xyes"], [ +echo " FIPS libraries: $FIPS_LIBS" +echo "" +]) + if test "x$PAM_MSG" = "xyes" ; then echo "PAM is enabled. You may need to install a PAM control file " echo "for sshd, otherwise password authentication may fail. " diff -ruN openssh-9.4p1/contrib/aix/buildbff.sh openssh-9.4p1+x509-14.2.1/contrib/aix/buildbff.sh --- openssh-9.4p1/contrib/aix/buildbff.sh 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/contrib/aix/buildbff.sh 2023-08-20 10:07:00.000000000 +0300 @@ -11,7 +11,7 @@ # # Tunable configuration settings -# create a "config.local" in your build directory or set +# create a "config.local" in your build directory or set # environment variables to override these. # [ -z "$PERMIT_ROOT_LOGIN" ] && PERMIT_ROOT_LOGIN=no @@ -52,7 +52,7 @@ # # Directories used during build: # current dir = $objdir directory you ran ./configure in. -# $objdir/$PKGDIR/ directory package files are constructed in +# $objdir/$PKGDIR/ directory package files are constructed in # $objdir/$PKGDIR/root/ package root ($FAKE_ROOT) # objdir=`pwd` diff -ruN openssh-9.4p1/contrib/aix/inventory.sh openssh-9.4p1+x509-14.2.1/contrib/aix/inventory.sh --- openssh-9.4p1/contrib/aix/inventory.sh 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/contrib/aix/inventory.sh 2023-08-20 10:07:00.000000000 +0300 @@ -45,7 +45,7 @@ print "\towner=root\n"; print "\tgroup=system\n"; printf "\tmode=%lo\n", $mod & 07777; # Mask perm bits - + if ( -l $_ ) { # Entry is SymLink print "\ttype=SYMLINK\n"; diff -ruN openssh-9.4p1/contrib/cygwin/Makefile openssh-9.4p1+x509-14.2.1/contrib/cygwin/Makefile --- openssh-9.4p1/contrib/cygwin/Makefile 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/contrib/cygwin/Makefile 2023-08-20 10:07:00.000000000 +0300 @@ -13,7 +13,7 @@ inetdefdir=$(defaultsdir)/inetd.d PRIVSEP_PATH=/var/empty INSTALL=/usr/bin/install -c -MKDIR_P=$(srcdir)/mkinstalldirs +MKDIR_P=$(srcdir)/install-sh -d DESTDIR= diff -ruN openssh-9.4p1/contrib/cygwin/ssh-host-config openssh-9.4p1+x509-14.2.1/contrib/cygwin/ssh-host-config --- openssh-9.4p1/contrib/cygwin/ssh-host-config 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/contrib/cygwin/ssh-host-config 2023-08-20 10:07:00.000000000 +0300 @@ -8,13 +8,13 @@ # purpose with or without fee is hereby granted, provided that the above # copyright notice and this permission notice appear in all copies. # -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -# IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -# DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -# OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR -# THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +# IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +# DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +# OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR +# THE USE OR OTHER DEALINGS IN THE SOFTWARE. # ====================================================================== # Initialization @@ -562,7 +562,7 @@ user_account="$1" shift ;; - + -w | --pwd ) password_value="$1" shift diff -ruN openssh-9.4p1/contrib/cygwin/ssh-user-config openssh-9.4p1+x509-14.2.1/contrib/cygwin/ssh-user-config --- openssh-9.4p1/contrib/cygwin/ssh-user-config 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/contrib/cygwin/ssh-user-config 2023-08-20 10:07:00.000000000 +0300 @@ -8,13 +8,13 @@ # purpose with or without fee is hereby granted, provided that the above # copyright notice and this permission notice appear in all copies. # -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -# IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -# DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -# OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR -# THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +# IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +# DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +# OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR +# THE USE OR OTHER DEALINGS IN THE SOFTWARE. # ====================================================================== # Initialization @@ -82,14 +82,14 @@ "There is no home directory set for you in the account database." \ 'Setting $HOME is not sufficient!' fi - + if [ ! -d "${pwdhome}" ] then csih_error_multi \ "${pwdhome} is set in the account database as your home directory" \ 'but it is not a valid directory. Cannot create user identity files.' fi - + # If home is the root dir, set home to empty string to avoid error messages # in subsequent parts of that script. if [ "X${pwdhome}" = "X/" ] @@ -104,7 +104,7 @@ exit 1 fi fi - + if [ -d "${pwdhome}" -a -n "`chmod -c g-w,o-w "${pwdhome}"`" ] then echo @@ -129,7 +129,7 @@ then csih_error "${pwdhome}/.ssh is existent but not a directory. Cannot create user identity files." fi - + if [ ! -e "${pwdhome}/.ssh" ] then mkdir "${pwdhome}/.ssh" diff -ruN openssh-9.4p1/contrib/findssl.sh openssh-9.4p1+x509-14.2.1/contrib/findssl.sh --- openssh-9.4p1/contrib/findssl.sh 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/contrib/findssl.sh 1970-01-01 02:00:00.000000000 +0200 @@ -1,184 +0,0 @@ -#!/bin/sh -# -# findssl.sh -# Search for all instances of OpenSSL headers and libraries -# and print their versions. -# Intended to help diagnose OpenSSH's "OpenSSL headers do not -# match your library" errors. -# -# Written by Darren Tucker (dtucker at zip dot com dot au) -# This file is placed in the public domain. -# -# Release history: -# 2002-07-27: Initial release. -# 2002-08-04: Added public domain notice. -# 2003-06-24: Incorporated readme, set library paths. First cvs version. -# 2004-12-13: Add traps to cleanup temp files, from Amarendra Godbole. -# -# "OpenSSL headers do not match your library" are usually caused by -# OpenSSH's configure picking up an older version of OpenSSL headers -# or libraries. You can use the following # procedure to help identify -# the cause. -# -# The output of configure will tell you the versions of the OpenSSL -# headers and libraries that were picked up, for example: -# -# checking OpenSSL header version... 90604f (OpenSSL 0.9.6d 9 May 2002) -# checking OpenSSL library version... 90602f (OpenSSL 0.9.6b [engine] 9 Jul 2001) -# checking whether OpenSSL's headers match the library... no -# configure: error: Your OpenSSL headers do not match your library -# -# Now run findssl.sh. This should identify the headers and libraries -# present and their versions. You should be able to identify the -# libraries and headers used and adjust your CFLAGS or remove incorrect -# versions. The output will show OpenSSL's internal version identifier -# and should look something like: - -# $ ./findssl.sh -# Searching for OpenSSL header files. -# 0x0090604fL /usr/include/openssl/opensslv.h -# 0x0090604fL /usr/local/ssl/include/openssl/opensslv.h -# -# Searching for OpenSSL shared library files. -# 0x0090602fL /lib/libcrypto.so.0.9.6b -# 0x0090602fL /lib/libcrypto.so.2 -# 0x0090581fL /usr/lib/libcrypto.so.0 -# 0x0090602fL /usr/lib/libcrypto.so -# 0x0090581fL /usr/lib/libcrypto.so.0.9.5a -# 0x0090600fL /usr/lib/libcrypto.so.0.9.6 -# 0x0090600fL /usr/lib/libcrypto.so.1 -# -# Searching for OpenSSL static library files. -# 0x0090602fL /usr/lib/libcrypto.a -# 0x0090604fL /usr/local/ssl/lib/libcrypto.a -# -# In this example, I gave configure no extra flags, so it's picking up -# the OpenSSL header from /usr/include/openssl (90604f) and the library -# from /usr/lib/ (90602f). - -# -# Adjust these to suit your compiler. -# You may also need to set the *LIB*PATH environment variables if -# DEFAULT_LIBPATH is not correct for your system. -# -CC=gcc -STATIC=-static - -# -# Cleanup on interrupt -# -trap 'rm -f conftest.c' INT HUP TERM - -# -# Set up conftest C source -# -rm -f findssl.log -cat >conftest.c < -int main(){printf("0x%08xL\n", SSLeay());} -EOD - -# -# Set default library paths if not already set -# -DEFAULT_LIBPATH=/usr/lib:/usr/local/lib -LIBPATH=${LIBPATH:=$DEFAULT_LIBPATH} -LD_LIBRARY_PATH=${LD_LIBRARY_PATH:=$DEFAULT_LIBPATH} -LIBRARY_PATH=${LIBRARY_PATH:=$DEFAULT_LIBPATH} -export LIBPATH LD_LIBRARY_PATH LIBRARY_PATH - -# not all platforms have a 'which' command -if which ls >/dev/null 2>/dev/null; then - : which is defined -else - which () { - saveIFS="$IFS" - IFS=: - for p in $PATH; do - if test -x "$p/$1" -a -f "$p/$1"; then - IFS="$saveIFS" - echo "$p/$1" - return 0 - fi - done - IFS="$saveIFS" - return 1 - } -fi - -# -# Search for OpenSSL headers and print versions -# -echo Searching for OpenSSL header files. -if [ -x "`which locate`" ] -then - headers=`locate opensslv.h` -else - headers=`find / -name opensslv.h -print 2>/dev/null` -fi - -for header in $headers -do - ver=`awk '/OPENSSL_VERSION_NUMBER/{printf \$3}' $header` - echo "$ver $header" -done -echo - -# -# Search for shared libraries. -# Relies on shared libraries looking like "libcrypto.s*" -# -echo Searching for OpenSSL shared library files. -if [ -x "`which locate`" ] -then - libraries=`locate libcrypto.s` -else - libraries=`find / -name 'libcrypto.s*' -print 2>/dev/null` -fi - -for lib in $libraries -do - (echo "Trying libcrypto $lib" >>findssl.log - dir=`dirname $lib` - LIBPATH="$dir:$LIBPATH" - LD_LIBRARY_PATH="$dir:$LIBPATH" - LIBRARY_PATH="$dir:$LIBPATH" - export LIBPATH LD_LIBRARY_PATH LIBRARY_PATH - ${CC} -o conftest conftest.c $lib 2>>findssl.log - if [ -x ./conftest ] - then - ver=`./conftest 2>/dev/null` - rm -f ./conftest - echo "$ver $lib" - fi) -done -echo - -# -# Search for static OpenSSL libraries and print versions -# -echo Searching for OpenSSL static library files. -if [ -x "`which locate`" ] -then - libraries=`locate libcrypto.a` -else - libraries=`find / -name libcrypto.a -print 2>/dev/null` -fi - -for lib in $libraries -do - libdir=`dirname $lib` - echo "Trying libcrypto $lib" >>findssl.log - ${CC} ${STATIC} -o conftest conftest.c -L${libdir} -lcrypto 2>>findssl.log - if [ -x ./conftest ] - then - ver=`./conftest 2>/dev/null` - rm -f ./conftest - echo "$ver $lib" - fi -done - -# -# Clean up -# -rm -f conftest.c diff -ruN openssh-9.4p1/contrib/gnome-ssh-askpass1.c openssh-9.4p1+x509-14.2.1/contrib/gnome-ssh-askpass1.c --- openssh-9.4p1/contrib/gnome-ssh-askpass1.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/contrib/gnome-ssh-askpass1.c 2023-08-20 10:07:01.000000000 +0300 @@ -75,7 +75,7 @@ grab_server = (getenv("GNOME_SSH_ASKPASS_GRAB_SERVER") != NULL); grab_pointer = (getenv("GNOME_SSH_ASKPASS_GRAB_POINTER") != NULL); - dialog = gnome_dialog_new("OpenSSH", GNOME_STOCK_BUTTON_OK, + dialog = gnome_dialog_new("Secure SHELL dialog", GNOME_STOCK_BUTTON_OK, GNOME_STOCK_BUTTON_CANCEL, NULL); messages = g_strsplit(message, "\\n", 0); @@ -129,11 +129,11 @@ passphrase = gtk_entry_get_text(GTK_ENTRY(entry)); if (result == 0) puts(passphrase); - + /* Zero passphrase in memory */ memset(passphrase, '\0', strlen(passphrase)); gtk_entry_set_text(GTK_ENTRY(entry), passphrase); - + gnome_dialog_close(GNOME_DIALOG(dialog)); return (result == 0 ? 0 : -1); @@ -147,7 +147,7 @@ if (grab_server) XUngrabServer(GDK_DISPLAY()); gnome_dialog_close(GNOME_DIALOG(dialog)); - + report_failed_grab(); return (-1); } @@ -163,7 +163,7 @@ if (argc == 2) message = argv[1]; else - message = "Enter your OpenSSH passphrase:"; + message = "Enter your passphrase:"; setvbuf(stdout, 0, _IONBF, 0); result = passphrase_dialog(message); diff -ruN openssh-9.4p1/contrib/gnome-ssh-askpass2.c openssh-9.4p1+x509-14.2.1/contrib/gnome-ssh-askpass2.c --- openssh-9.4p1/contrib/gnome-ssh-askpass2.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/contrib/gnome-ssh-askpass2.c 2023-08-20 10:07:01.000000000 +0300 @@ -187,7 +187,7 @@ dialog = gtk_message_dialog_new(GTK_WINDOW(parent_window), 0, GTK_MESSAGE_QUESTION, buttons, "%s", message); - gtk_window_set_title(GTK_WINDOW(dialog), "OpenSSH"); + gtk_window_set_title(GTK_WINDOW(dialog), "Secure SHELL dialog"); gtk_window_set_position (GTK_WINDOW(dialog), GTK_WIN_POS_CENTER); gtk_window_set_keep_above(GTK_WINDOW(dialog), TRUE); gtk_dialog_set_default_response(GTK_DIALOG(dialog), default_response); @@ -213,7 +213,7 @@ gtk_widget_show(entry); /* Make close dialog */ g_signal_connect(G_OBJECT(entry), "activate", - G_CALLBACK(ok_dialog), dialog); + G_CALLBACK(ok_dialog), dialog); } else { /* * Ensure the 'close' button is not focused by default @@ -306,7 +306,7 @@ if (grab_server) XUngrabServer(gdk_x11_get_default_xdisplay()); gtk_widget_destroy(dialog); - + report_failed_grab(parent_window, failed); return (-1); @@ -323,7 +323,7 @@ if (argc > 1) { message = g_strjoinv(" ", argv + 1); } else { - message = g_strdup("Enter your OpenSSH passphrase:"); + message = g_strdup("Enter your passphrase:"); } if ((prompt_mode = getenv("SSH_ASKPASS_PROMPT")) != NULL) { diff -ruN openssh-9.4p1/contrib/gnome-ssh-askpass3.c openssh-9.4p1+x509-14.2.1/contrib/gnome-ssh-askpass3.c --- openssh-9.4p1/contrib/gnome-ssh-askpass3.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/contrib/gnome-ssh-askpass3.c 1970-01-01 02:00:00.000000000 +0200 @@ -1,305 +0,0 @@ -/* - * Copyright (c) 2000-2002 Damien Miller. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* GTK2 support by Nalin Dahyabhai */ - -/* - * This is a simple GNOME SSH passphrase grabber. To use it, set the - * environment variable SSH_ASKPASS to point to the location of - * gnome-ssh-askpass before calling "ssh-add < /dev/null". - * - * There is only two run-time options: if you set the environment variable - * "GNOME_SSH_ASKPASS_GRAB_SERVER=true" then gnome-ssh-askpass will grab - * the X server. If you set "GNOME_SSH_ASKPASS_GRAB_POINTER=true", then the - * pointer will be grabbed too. These may have some benefit to security if - * you don't trust your X server. We grab the keyboard always. - */ - -#define GRAB_TRIES 16 -#define GRAB_WAIT 250 /* milliseconds */ - -#define PROMPT_ENTRY 0 -#define PROMPT_CONFIRM 1 -#define PROMPT_NONE 2 - -/* - * Compile with: - * - * cc -Wall `pkg-config --cflags gtk+-2.0` \ - * gnome-ssh-askpass2.c -o gnome-ssh-askpass \ - * `pkg-config --libs gtk+-2.0` - * - */ - -#include -#include -#include -#include - -#include -#include -#include -#include - -static void -ok_dialog(GtkWidget *entry, gpointer dialog) -{ - g_return_if_fail(GTK_IS_DIALOG(dialog)); - gtk_dialog_response(GTK_DIALOG(dialog), GTK_RESPONSE_OK); -} - -static gboolean -check_none(GtkWidget *widget, GdkEventKey *event, gpointer dialog) -{ - switch (event->keyval) { - case GDK_KEY_Escape: - /* esc -> close dialog */ - gtk_dialog_response(GTK_DIALOG(dialog), GTK_RESPONSE_CLOSE); - return TRUE; - case GDK_KEY_Tab: - /* tab -> focus close button */ - gtk_widget_grab_focus(gtk_dialog_get_widget_for_response( - dialog, GTK_RESPONSE_CLOSE)); - return TRUE; - default: - /* eat all other key events */ - return TRUE; - } -} - -static int -parse_env_hex_color(const char *env, GdkColor *c) -{ - const char *s; - unsigned long ul; - char *ep; - size_t n; - - if ((s = getenv(env)) == NULL) - return 0; - - memset(c, 0, sizeof(*c)); - - /* Permit hex rgb or rrggbb optionally prefixed by '#' or '0x' */ - if (*s == '#') - s++; - else if (strncmp(s, "0x", 2) == 0) - s += 2; - n = strlen(s); - if (n != 3 && n != 6) - goto bad; - ul = strtoul(s, &ep, 16); - if (*ep != '\0' || ul > 0xffffff) { - bad: - fprintf(stderr, "Invalid $%s - invalid hex color code\n", env); - return 0; - } - /* Valid hex sequence; expand into a GdkColor */ - if (n == 3) { - /* 4-bit RGB */ - c->red = ((ul >> 8) & 0xf) << 12; - c->green = ((ul >> 4) & 0xf) << 12; - c->blue = (ul & 0xf) << 12; - } else { - /* 8-bit RGB */ - c->red = ((ul >> 16) & 0xff) << 8; - c->green = ((ul >> 8) & 0xff) << 8; - c->blue = (ul & 0xff) << 8; - } - return 1; -} - -static int -passphrase_dialog(char *message, int prompt_type) -{ - const char *failed; - char *passphrase, *local; - int result, grab_tries, grab_server, grab_pointer; - int buttons, default_response; - GtkWidget *parent_window, *dialog, *entry, *err; - GdkGrabStatus status; - GdkColor fg, bg; - GdkSeat *seat; - GdkDisplay *display; - GdkSeatCapabilities caps; - int fg_set = 0, bg_set = 0; - - grab_server = (getenv("GNOME_SSH_ASKPASS_GRAB_SERVER") != NULL); - grab_pointer = (getenv("GNOME_SSH_ASKPASS_GRAB_POINTER") != NULL); - grab_tries = 0; - - fg_set = parse_env_hex_color("GNOME_SSH_ASKPASS_FG_COLOR", &fg); - bg_set = parse_env_hex_color("GNOME_SSH_ASKPASS_BG_COLOR", &bg); - - /* Create an invisible parent window so that GtkDialog doesn't - * complain. */ - parent_window = gtk_window_new(GTK_WINDOW_TOPLEVEL); - - switch (prompt_type) { - case PROMPT_CONFIRM: - buttons = GTK_BUTTONS_YES_NO; - default_response = GTK_RESPONSE_YES; - break; - case PROMPT_NONE: - buttons = GTK_BUTTONS_CLOSE; - default_response = GTK_RESPONSE_CLOSE; - break; - default: - buttons = GTK_BUTTONS_OK_CANCEL; - default_response = GTK_RESPONSE_OK; - break; - } - - dialog = gtk_message_dialog_new(GTK_WINDOW(parent_window), 0, - GTK_MESSAGE_QUESTION, buttons, "%s", message); - - gtk_window_set_title(GTK_WINDOW(dialog), "OpenSSH"); - gtk_window_set_position (GTK_WINDOW(dialog), GTK_WIN_POS_CENTER); - gtk_window_set_keep_above(GTK_WINDOW(dialog), TRUE); - gtk_dialog_set_default_response(GTK_DIALOG(dialog), default_response); - gtk_window_set_keep_above(GTK_WINDOW(dialog), TRUE); - - if (fg_set) - gtk_widget_modify_fg(dialog, GTK_STATE_NORMAL, &fg); - if (bg_set) - gtk_widget_modify_bg(dialog, GTK_STATE_NORMAL, &bg); - - if (prompt_type == PROMPT_ENTRY || prompt_type == PROMPT_NONE) { - entry = gtk_entry_new(); - if (fg_set) - gtk_widget_modify_fg(entry, GTK_STATE_NORMAL, &fg); - if (bg_set) - gtk_widget_modify_bg(entry, GTK_STATE_NORMAL, &bg); - gtk_box_pack_start( - GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), - entry, FALSE, FALSE, 0); - gtk_entry_set_visibility(GTK_ENTRY(entry), FALSE); - gtk_widget_grab_focus(entry); - if (prompt_type == PROMPT_ENTRY) { - gtk_widget_show(entry); - /* Make close dialog */ - g_signal_connect(G_OBJECT(entry), "activate", - G_CALLBACK(ok_dialog), dialog); - } else { - /* - * Ensure the 'close' button is not focused by default - * but is still reachable via tab. This is a bit of a - * hack - it uses a hidden entry that responds to a - * couple of keypress events (escape and tab only). - */ - gtk_widget_realize(entry); - g_signal_connect(G_OBJECT(entry), "key_press_event", - G_CALLBACK(check_none), dialog); - } - } - /* Grab focus */ - gtk_widget_show_now(dialog); - display = gtk_widget_get_display(GTK_WIDGET(dialog)); - seat = gdk_display_get_default_seat(display); - caps = GDK_SEAT_CAPABILITY_KEYBOARD; - if (grab_pointer) - caps |= GDK_SEAT_CAPABILITY_ALL_POINTING; - if (grab_server) - caps = GDK_SEAT_CAPABILITY_ALL; - for (;;) { - status = gdk_seat_grab(seat, gtk_widget_get_window(dialog), - caps, TRUE, NULL, NULL, NULL, NULL); - if (status == GDK_GRAB_SUCCESS) - break; - usleep(GRAB_WAIT * 1000); - if (++grab_tries > GRAB_TRIES) - goto nograb; - } - - result = gtk_dialog_run(GTK_DIALOG(dialog)); - - /* Ungrab */ - gdk_seat_ungrab(seat); - gdk_display_flush(display); - - /* Report passphrase if user selected OK */ - if (prompt_type == PROMPT_ENTRY) { - passphrase = g_strdup(gtk_entry_get_text(GTK_ENTRY(entry))); - if (result == GTK_RESPONSE_OK) { - local = g_locale_from_utf8(passphrase, - strlen(passphrase), NULL, NULL, NULL); - if (local != NULL) { - puts(local); - memset(local, '\0', strlen(local)); - g_free(local); - } else { - puts(passphrase); - } - } - /* Zero passphrase in memory */ - memset(passphrase, '\b', strlen(passphrase)); - gtk_entry_set_text(GTK_ENTRY(entry), passphrase); - memset(passphrase, '\0', strlen(passphrase)); - g_free(passphrase); - } - - gtk_widget_destroy(dialog); - if (result != GTK_RESPONSE_OK && result != GTK_RESPONSE_YES) - return -1; - return 0; - - nograb: - gtk_widget_destroy(dialog); - err = gtk_message_dialog_new(GTK_WINDOW(parent_window), 0, - GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, - "Could not grab input. A malicious client may be eavesdropping " - "on your session."); - gtk_window_set_position(GTK_WINDOW(err), GTK_WIN_POS_CENTER); - gtk_dialog_run(GTK_DIALOG(err)); - gtk_widget_destroy(err); - return -1; -} - -int -main(int argc, char **argv) -{ - char *message, *prompt_mode; - int result, prompt_type = PROMPT_ENTRY; - - gtk_init(&argc, &argv); - - if (argc > 1) { - message = g_strjoinv(" ", argv + 1); - } else { - message = g_strdup("Enter your OpenSSH passphrase:"); - } - - if ((prompt_mode = getenv("SSH_ASKPASS_PROMPT")) != NULL) { - if (strcasecmp(prompt_mode, "confirm") == 0) - prompt_type = PROMPT_CONFIRM; - else if (strcasecmp(prompt_mode, "none") == 0) - prompt_type = PROMPT_NONE; - } - - setvbuf(stdout, 0, _IONBF, 0); - result = passphrase_dialog(message, prompt_type); - g_free(message); - - return (result); -} diff -ruN openssh-9.4p1/contrib/hpux/egd.rc openssh-9.4p1+x509-14.2.1/contrib/hpux/egd.rc --- openssh-9.4p1/contrib/hpux/egd.rc 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/contrib/hpux/egd.rc 2023-08-20 10:07:00.000000000 +0300 @@ -64,7 +64,6 @@ else echo "ERROR: $WHAT_CONFIG defaults file MISSING" fi - if [ "$EGD_START" -eq 1 -a -x $WHAT_PATH ]; then EGD_LOG=${EGD_LOG:-$WHAT_LOG} diff -ruN openssh-9.4p1/contrib/hpux/sshd.rc openssh-9.4p1+x509-14.2.1/contrib/hpux/sshd.rc --- openssh-9.4p1/contrib/hpux/sshd.rc 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/contrib/hpux/sshd.rc 2023-08-20 10:07:00.000000000 +0300 @@ -62,7 +62,7 @@ else echo "ERROR: $WHAT_CONFIG defaults file MISSING" fi - + if [ "$SSHD_START" -eq 1 -a -x "$WHAT_PATH" ]; then $WHAT_PATH $SSHD_ARGS && echo "$WHAT started" set_return diff -ruN openssh-9.4p1/contrib/Makefile openssh-9.4p1+x509-14.2.1/contrib/Makefile --- openssh-9.4p1/contrib/Makefile 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/contrib/Makefile 2023-08-20 10:07:00.000000000 +0300 @@ -1,22 +1,43 @@ PKG_CONFIG = pkg-config +PKG_CONFIG_CFLAGS = $(PKG_CONFIG) --cflags +PKG_CONFIG_LIBS = $(PKG_CONFIG) --libs + all: - @echo "Valid targets: gnome-ssh-askpass1 gnome-ssh-askpass2 gnome-ssk-askpass3" + @echo "Valid targets:" >&2 + @echo " ssh-askpass-gnome" >&2 + @echo " ssh-askpass-gtk+2" >&2 + @echo " ssh-askpass-gtk+3" >&2 + @echo " ssh-askpass2-gtk+3" >&2 -gnome-ssh-askpass1: gnome-ssh-askpass1.c +ssh-askpass-gnome: gnome-ssh-askpass1.c $(CC) $(CFLAGS) `gnome-config --cflags gnome gnomeui` \ - gnome-ssh-askpass1.c -o gnome-ssh-askpass1 \ + -o $@ gnome-ssh-askpass1.c \ `gnome-config --libs gnome gnomeui` -gnome-ssh-askpass2: gnome-ssh-askpass2.c - $(CC) $(CFLAGS) `$(PKG_CONFIG) --cflags gtk+-2.0` \ - gnome-ssh-askpass2.c -o gnome-ssh-askpass2 \ - `$(PKG_CONFIG) --libs gtk+-2.0 x11` - -gnome-ssh-askpass3: gnome-ssh-askpass3.c - $(CC) $(CFLAGS) `$(PKG_CONFIG) --cflags gtk+-3.0` \ - gnome-ssh-askpass3.c -o gnome-ssh-askpass3 \ - `$(PKG_CONFIG) --libs gtk+-3.0 x11` +ssh-askpass-gtk+2: gnome-ssh-askpass2.c + $(CC) $(CFLAGS) `$(PKG_CONFIG_CFLAGS) gtk+-2.0` \ + -o $@ gnome-ssh-askpass2.c \ + `$(PKG_CONFIG_LIBS) gtk+-2.0 x11` + +ssh-askpass-gtk+3: gnome-ssh-askpass2.c + $(CC) $(CFLAGS) `$(PKG_CONFIG_CFLAGS) gtk+-3.0` \ + -o $@ gnome-ssh-askpass2.c \ + `$(PKG_CONFIG_LIBS) gtk+-3.0 x11` + +ssh-askpass2-gtk+3: ssh-askpass2-gtk+3.c + $(CC) $(CFLAGS) `$(PKG_CONFIG_CFLAGS) gtk+-3.0` \ + -o $@ ssh-askpass-gtk+3.c \ + `$(PKG_CONFIG_LIBS) gtk+-3.0 x11` clean: rm -f *.o gnome-ssh-askpass gnome-ssh-askpass[123] + rm -f ssh-askpass-gnome ssh-askpass-gtk+[23] ssh-askpass2-gtk+3 + + +#obsolete targets - still used in redhat/openssh.spec (TODO) +gnome-ssh-askpass1: ssh-askpass-gnome + cp ssh-askpass-gnome $@ + +gnome-ssh-askpass2: ssh-askpass-gtk+2 + cp ssh-askpass-gtk+2 $@ diff -ruN openssh-9.4p1/contrib/README openssh-9.4p1+x509-14.2.1/contrib/README --- openssh-9.4p1/contrib/README 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/contrib/README 2023-08-20 10:07:00.000000000 +0300 @@ -1,5 +1,5 @@ -Other patches and addons for OpenSSH. Please send submissions to -djm@mindrot.org +Other patches and addons for PKIX-SSH. Please send submissions to +PKIX-SSH mailing list - ssh_x509@roumenpetrov.info . Externally maintained --------------------- @@ -14,14 +14,6 @@ https://bitbucket.org/gotoh/connect/wiki/Home -X11 SSH Askpass: - -Jim Knoble has written an excellent X11 -passphrase requester. This is highly recommended: - -http://www.jmknoble.net/software/x11-ssh-askpass/ - - In this directory ----------------- @@ -30,10 +22,16 @@ Phil Hands' shell script to automate the process of adding your public key to a remote machine's ~/.ssh/authorized_keys file. -gnome-ssh-askpass[12]: +ssh-askpass-kdialog: -A GNOME and Gtk2 passphrase requesters. Use "make gnome-ssh-askpass1" or -"make gnome-ssh-askpass2" to build. +A born shell passphrase requester that wraps KDialog. + +gnome-ssh-askpass[12].c: + +A GNOME and GTK+ passphrase requesters. Use "make ssh-askpass-gnome" or +"make ssh-askpass-gtk+2" or "make ssh-askpass2-gtk+3" to build. +For compatibility with existing installations you could use +"make gnome-ssh-askpass1" or "make gnome-ssh-askpass2". sshd.pam.generic: @@ -44,12 +42,6 @@ A PAM config file which works with FreeBSD's PAM port. Contributed by Dominik Brettnacher -findssl.sh: - -Search for all instances of OpenSSL headers and libraries and print their -versions. This is intended to help diagnose OpenSSH's "OpenSSL headers do not -match your library" errors. - aix: Files to build an AIX native (installp or SMIT installable) package. diff -ruN openssh-9.4p1/contrib/redhat/openssh.spec openssh-9.4p1+x509-14.2.1/contrib/redhat/openssh.spec --- openssh-9.4p1/contrib/redhat/openssh.spec 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/contrib/redhat/openssh.spec 2023-08-20 10:07:00.000000000 +0300 @@ -66,7 +66,7 @@ # rpm -ba|--rebuild --define "smartcard 1" %{?smartcard:%global scard 1} -# Is this a build for the rescue CD (without PAM)? (1=yes 0=no) +# Is this a build for the rescue CD (without PAM, with MD5)? (1=yes 0=no) %global rescue 0 %{?build_rescue:%global rescue 1} @@ -211,6 +211,7 @@ --with-default-path=/usr/local/bin:/bin:/usr/bin \ --with-superuser-path=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin \ --with-privsep-path=%{_var}/empty/sshd \ + --with-md5-passwords \ --mandir=%{_mandir} \ --with-mantype=man \ --disable-strip \ @@ -362,10 +363,8 @@ %attr(0755,root,root) %dir %{_libexecdir}/openssh %attr(4711,root,root) %{_libexecdir}/openssh/ssh-keysign %attr(0755,root,root) %{_libexecdir}/openssh/ssh-pkcs11-helper -%attr(0755,root,root) %{_libexecdir}/openssh/ssh-sk-helper %attr(0644,root,root) %{_mandir}/man8/ssh-keysign.8* %attr(0644,root,root) %{_mandir}/man8/ssh-pkcs11-helper.8* -%attr(0644,root,root) %{_mandir}/man8/ssh-sk-helper.8* %endif %if %{scard} %attr(0755,root,root) %dir %{_datadir}/openssh @@ -423,12 +422,6 @@ %endif %changelog -* Thu Oct 28 2021 Damien Miller -- Remove remaining traces of --with-md5-passwords - -* Mon Jul 20 2020 Damien Miller -- Add ssh-sk-helper and corresponding manual page. - * Sat Feb 10 2018 Darren Tucker - Update openssl-devel dependency to match current requirements. - Handle Fedora >=6 openssl 1.0 compat libs. diff -ruN openssh-9.4p1/contrib/redhat/pkixssh.spec openssh-9.4p1+x509-14.2.1/contrib/redhat/pkixssh.spec --- openssh-9.4p1/contrib/redhat/pkixssh.spec 1970-01-01 02:00:00.000000000 +0200 +++ openssh-9.4p1+x509-14.2.1/contrib/redhat/pkixssh.spec 2023-08-20 10:07:00.000000000 +0300 @@ -0,0 +1,279 @@ +# +# spec file for pkixssh package +# +# This is free software; see Copyright file in the source +# distribution for precise wording. +# +# Copyright (c) 2019-2022 Roumen Petrov +# + +# Do we want to enable building with ldap? (1=yes 0=no) +%global enable_ldap 1 + +# Do we want to enable test with ldap? (1=yes 0=no) +%global enable_ldap_test 1 + +# Do we use FIPS capable OpenSSL library ? (1=yes 0=no) +%global enable_openssl_fips 1 + +# Do we want to enable FIPS test? (1=yes 0=no) +%global enable_fips_test 1 + +# Do we want to use fipscheck? (1=yes 0=no) +%global use_fipscheck 1 + +# Do we want to use Linux auditing? (1=yes 0=no) +%global enable_audit_module 1 + +# TODO: do not produce debug package(temporary) +%global debug_package %{nil} + + +# Disable non-working configurations +%if 0%{?centos_version} >= 800 +# No more openldap server package on CentOS 8 +%undefine enable_ldap_test +%global enable_ldap_test 0 +%endif + +%if 0%{?fedora} >= 36 +# OpenSSL 3+ FIPS model is not supported yet +%undefine enable_openssl_fips +%global enable_openssl_fips 0 +%endif +%if !%{enable_openssl_fips} +%undefine enable_fips_test +%global enable_fips_test 0 +%endif + +%if 0%{?fedora} >= 33 +%undefine use_fipscheck +%global use_fipscheck 0 +%endif +%if 0%{?rhel_version} && 0%{?rhel_version} > 500 +%undefine use_fipscheck +%global use_fipscheck 0 +%endif +%if !%{enable_openssl_fips} +%undefine use_fipscheck +%global use_fipscheck 0 +%endif + +%global use_groff_package 0 +%if 0%{?rhel_version} && 0%{?rhel_version} < 700 +%undefine use_groff_package +%global use_groff_package 1 +%endif +%if 0%{?centos_version} && 0%{?centos_version} < 700 +%undefine use_groff_package +%global use_groff_package 1 +%endif + + +# norootforbuild + +Url: https://roumenpetrov.info/secsh/ + +Name: pkixssh +Summary: PKIX-SSH, Advanced secure shell implementation +Version: 14.2.1 +Release: 1 +License: BSD +Group: Productivity/Networking/SSH + +BuildRequires: zlib-devel +BuildRequires: pam-devel +BuildRequires: openssl-devel openssl +%if %{enable_ldap} +BuildRequires: openldap-devel openldap openldap-clients +%endif +%if %{enable_ldap_test} +BuildRequires: openldap-servers +%endif +%if %{use_fipscheck} +BuildRequires: fipscheck-devel fipscheck +%endif +%if %{use_groff_package} +BuildRequires: groff +%else +BuildRequires: groff-base +%endif +%if %{enable_audit_module} +BuildRequires: audit-libs-devel +Requires: audit-libs +%endif +# Next is not part of preinstalled packages on some build configurations +# (RHEL5?) +BuildRequires: which +BuildRoot: %{_tmppath}/%{name}-%{version}-build + +%if 0%{?rhel_version} && 0%{?rhel_version} < 600 +Source0: https://roumenpetrov.info/secsh/src/%{name}-%{version}.tar.gz +%else +Source0: https://roumenpetrov.info/secsh/src/%{name}-%{version}.tar.xz +%endif + + +# Default values for additional components + +%define ssh_sysconfdir %{_sysconfdir}/ssh +%define ssh_libexecdir %{_libexecdir}/ssh + +# Define the UID/GID to use for privilege separation +%define sshd_gid 74 +%define sshd_uid 74 + + +%description +Ssh (Secure Shell) is a program for logging into a remote machine and for +executing commands in a remote machine. It is intended to replace +rlogin and rsh, and provide secure encrypted communications between +two untrusted hosts over an insecure network. + + +%prep +%setup -q + + +%build +%configure \ + --prefix=/usr \ + --libexecdir=%{ssh_libexecdir} \ + --sysconfdir=%{ssh_sysconfdir} \ + --mandir=%{_mandir} \ +%if %{enable_ldap} + --enable-ldap --with-ldap-libexecdir=/usr/sbin \ +%else + --disable-ldap \ +%endif +%if %{enable_openssl_fips} + --enable-openssl-fips \ +%else + --disable-openssl-fips \ +%endif +%if %{enable_audit_module} + --with-audit=linux \ +%endif + --with-pie \ + --with-pam \ + --with-privsep-path=%{_var}/empty/sshd +make + + +%check +TERM=dumb \ +make check + +%if %{enable_ldap_test} +%if 0%{?rhel_version} && 0%{?rhel_version} < 700 +SSH_LDAP_DB=hdb \ +%endif +TERM=dumb \ +SSH_X509TESTS="by_ldap" \ +make check-certs +%endif + +TERM=dumb \ +make t-exec LTESTS=percent || : + +TERM=dumb \ +make t-exec LTESTS=multiplex || : + +%if %{enable_fips_test} +# ignore failures as tests are sensitive to used sandbox +TERM=dumb \ +make t-exec LTESTS=fips-connect-privsep || : +TERM=dumb \ +make t-exec LTESTS=fips-try-ciphers || : +%endif + + +%install +make install DESTDIR=%{buildroot} + +install -d %{buildroot}/etc/pam.d/ +install -m644 contrib/redhat/sshd.pam %{buildroot}/etc/pam.d/sshd + +install -d %{buildroot}/etc/rc.d/init.d/ +install -m744 contrib/redhat/sshd.init %{buildroot}/etc/rc.d/init.d/sshd + + +%clean + + +%pre +/usr/sbin/groupadd -g %{sshd_gid} -o -r sshd 2> /dev/null || : +/usr/sbin/useradd -r -o -g sshd -u %{sshd_uid} -s /bin/false -c "SSH Privilege Separation User" -d /var/lib/sshd sshd 2> /dev/null || : + + +%post +/usr/bin/ssh-keygen -A +%{fillup_and_insserv -n -y ssh sshd} +%run_permissions + + +%verifyscript +%verify_permissions \ + -e %{ssh_sysconfdir}/sshd_config \ + -e %{ssh_sysconfdir}/ssh_config \ + -e %{_bindir}/ssh + + +%preun +%stop_on_removal sshd + + +%postun +%restart_on_update sshd +%{insserv_cleanup} + + +%files +%defattr(-,root,root) +%doc CREDITS LICENCE OVERVIEW PROTOCOL* README* +%doc TODO +%attr(0755,root,root) %dir %{ssh_sysconfdir} +%attr(0644,root,root) %config(noreplace) %{ssh_sysconfdir}/ssh_config +%attr(0600,root,root) %config(noreplace) %{ssh_sysconfdir}/sshd_config +%attr(0600,root,root) %config(noreplace) %{ssh_sysconfdir}/moduli +%attr(0644,root,root) %config(noreplace) /etc/pam.d/sshd +%attr(0755,root,root) %config /etc/rc.d/init.d/sshd +%if %{use_fipscheck} +# TODO: installation into fipscheck "lib" directory +%attr(0644,root,root) %{_bindir}/.ssh.hmac +%attr(0644,root,root) %{_bindir}/.ssh-agent.hmac +%attr(0644,root,root) %{_bindir}/.ssh-keygen.hmac +%attr(0644,root,root) %{_sbindir}/.sshd.hmac +%endif +%attr(0755,root,root) %{_bindir}/scp +%attr(0755,root,root) %{_bindir}/sftp +%attr(0755,root,root) %{_bindir}/ssh +%attr(0755,root,root) %{_bindir}/ssh-add +%attr(0755,root,root) %{_bindir}/ssh-agent +%attr(0755,root,root) %{_bindir}/ssh-keygen +%attr(0755,root,root) %{_bindir}/ssh-keyscan +%attr(0755,root,root) %{_sbindir}/sshd +%attr(0755,root,root) %dir %{ssh_libexecdir} +%attr(0755,root,root) %{ssh_libexecdir}/sftp-server +#FIXME setuid +%attr(4711,root,root) %{ssh_libexecdir}/ssh-keysign +%attr(0755,root,root) %{ssh_libexecdir}/ssh-pkcs11-helper +%attr(0644,root,root) %doc %{_mandir}/man1/scp.1* +%attr(0644,root,root) %doc %{_mandir}/man1/sftp.1* +%attr(0644,root,root) %doc %{_mandir}/man1/ssh.1* +%attr(0644,root,root) %doc %{_mandir}/man1/ssh-add.1* +%attr(0644,root,root) %doc %{_mandir}/man1/ssh-agent.1* +%attr(0644,root,root) %doc %{_mandir}/man1/ssh-keygen.1* +%attr(0644,root,root) %doc %{_mandir}/man1/ssh-keyscan.1* +%attr(0644,root,root) %doc %{_mandir}/man5/moduli.5* +%attr(0644,root,root) %doc %{_mandir}/man5/ssh_config.5* +%attr(0644,root,root) %doc %{_mandir}/man5/ssh_engine.5* +%attr(0644,root,root) %doc %{_mandir}/man5/sshd_config.5* +%attr(0644,root,root) %doc %{_mandir}/man8/sftp-server.8* +%attr(0644,root,root) %doc %{_mandir}/man8/ssh-keysign.8* +%attr(0644,root,root) %doc %{_mandir}/man8/ssh-pkcs11-helper.8* +%attr(0644,root,root) %doc %{_mandir}/man8/sshd.8* + + +%changelog +# Not managed, please see source repository for changes. diff -ruN openssh-9.4p1/contrib/redhat/sshd.init openssh-9.4p1+x509-14.2.1/contrib/redhat/sshd.init --- openssh-9.4p1/contrib/redhat/sshd.init 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/contrib/redhat/sshd.init 2023-08-20 10:07:00.000000000 +0300 @@ -24,6 +24,7 @@ # Some functions to make the below more readable SSHD=/usr/sbin/sshd PID_FILE=/var/run/sshd.pid +KEYGEN=/usr/bin/ssh-keygen do_restart_sanity_check() { @@ -38,11 +39,12 @@ start() { # Create keys if necessary - /usr/bin/ssh-keygen -A + $KEYGEN -A if [ -x /sbin/restorecon ]; then - /sbin/restorecon /etc/ssh/ssh_host_rsa_key.pub - /sbin/restorecon /etc/ssh/ssh_host_dsa_key.pub - /sbin/restorecon /etc/ssh/ssh_host_ecdsa_key.pub + for f in /etc/ssh/ssh_host_*_key.pub ; do + test -f $F || continue + /sbin/restorecon $f + done fi echo -n $"Starting $prog:" diff -ruN openssh-9.4p1/contrib/redhat/sshd.init.old openssh-9.4p1+x509-14.2.1/contrib/redhat/sshd.init.old --- openssh-9.4p1/contrib/redhat/sshd.init.old 1970-01-01 02:00:00.000000000 +0200 +++ openssh-9.4p1+x509-14.2.1/contrib/redhat/sshd.init.old 2023-08-20 10:07:00.000000000 +0300 @@ -0,0 +1,121 @@ +#!/bin/bash +# +# Init file for OpenSSH server daemon +# +# chkconfig: 2345 55 25 +# description: OpenSSH server daemon +# +# processname: sshd +# config: /etc/ssh/ssh_host_key +# config: /etc/ssh/ssh_host_key.pub +# config: /etc/ssh/ssh_random_seed +# config: /etc/ssh/sshd_config +# pidfile: /var/run/sshd.pid + +# source function library +. /etc/rc.d/init.d/functions + +# pull in sysconfig settings +[ -f /etc/sysconfig/sshd ] && . /etc/sysconfig/sshd + +RETVAL=0 +prog="sshd" + +# Some functions to make the below more readable +KEYGEN=/usr/bin/ssh-keygen +SSHD=/usr/sbin/sshd +PID_FILE=/var/run/sshd.pid + +my_success() { + local msg + if [ $# -gt 1 ]; then + msg="$2" + else + msg="done" + fi + case "`type -type success`" in + function) + success "$1" + ;; + *) + echo -n "${msg}" + ;; + esac +} +my_failure() { + local msg + if [ $# -gt 1 ]; then + msg="$2" + else + msg="FAILED" + fi + case "`type -type failure`" in + function) + failure "$1" + ;; + *) + echo -n "${msg}" + ;; + esac +} +do_restart_sanity_check() { + $SSHD -t + RETVAL=$? + if [ ! "$RETVAL" = 0 ]; then + my_failure "Configuration file or keys" + echo + fi +} + + +case "$1" in + start) + # Create keys if necessary + $KEYGEN -A + echo -n "Starting sshd: " + if [ ! -f $PID_FILE ] ; then + sshd $OPTIONS + RETVAL=$? + if [ "$RETVAL" = "0" ] ; then + my_success "sshd startup" "sshd" + touch /var/lock/subsys/sshd + else + my_failure "sshd startup" "" + fi + fi + echo + ;; + stop) + echo -n "Shutting down sshd: " + if [ -f $PID_FILE ] ; then + killproc sshd + RETVAL=$? + [ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/sshd + fi + echo + ;; + restart) + do_restart_sanity_check + $0 stop + $0 start + RETVAL=$? + ;; + condrestart) + if [ -f /var/lock/subsys/sshd ] ; then + do_restart_sanity_check + $0 stop + $0 start + RETVAL=$? + fi + ;; + status) + status sshd + RETVAL=$? + ;; + *) + echo "Usage: sshd {start|stop|restart|status|condrestart}" + exit 1 + ;; +esac + +exit $RETVAL diff -ruN openssh-9.4p1/contrib/redhat/sshd.pam.old openssh-9.4p1+x509-14.2.1/contrib/redhat/sshd.pam.old --- openssh-9.4p1/contrib/redhat/sshd.pam.old 1970-01-01 02:00:00.000000000 +0200 +++ openssh-9.4p1+x509-14.2.1/contrib/redhat/sshd.pam.old 2023-08-20 10:07:00.000000000 +0300 @@ -0,0 +1,8 @@ +#%PAM-1.0 +auth required /lib/security/pam_pwdb.so shadow nodelay +auth required /lib/security/pam_nologin.so +account required /lib/security/pam_pwdb.so +password required /lib/security/pam_cracklib.so +password required /lib/security/pam_pwdb.so shadow nullok use_authtok +session required /lib/security/pam_pwdb.so +session required /lib/security/pam_limits.so diff -ruN openssh-9.4p1/contrib/ssh-askpass2-gtk+3.c openssh-9.4p1+x509-14.2.1/contrib/ssh-askpass2-gtk+3.c --- openssh-9.4p1/contrib/ssh-askpass2-gtk+3.c 1970-01-01 02:00:00.000000000 +0200 +++ openssh-9.4p1+x509-14.2.1/contrib/ssh-askpass2-gtk+3.c 2023-08-20 10:07:01.000000000 +0300 @@ -0,0 +1,354 @@ +/* + * Copyright (c) 2000-2002 Damien Miller. All rights reserved. + * Copyright (c) 2021 Roumen Petrov. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* GTK2 support by Nalin Dahyabhai */ + +/* + * This is a simple GNOME SSH passphrase grabber. To use it, set the + * environment variable SSH_ASKPASS to point to the location of + * gnome-ssh-askpass before calling "ssh-add < /dev/null". + * + * There is only two run-time options: if you set the environment variable + * "GNOME_SSH_ASKPASS_GRAB_SERVER=true" then gnome-ssh-askpass will grab + * the X server. If you set "GNOME_SSH_ASKPASS_GRAB_POINTER=true", then the + * pointer will be grabbed too. These may have some benefit to security if + * you don't trust your X server. We grab the keyboard always. + */ + +#define GRAB_TRIES 16 +#define GRAB_WAIT 250 /* milliseconds */ + +#define PROMPT_ENTRY 0 +#define PROMPT_CONFIRM 1 +#define PROMPT_NONE 2 + +/* + * Compile with: + * + * cc -Wall `pkg-config --cflags gtk+-2.0` \ + * gnome-ssh-askpass2.c -o gnome-ssh-askpass \ + * `pkg-config --libs gtk+-2.0` + * + */ + +#include +#include +#include +#include + +#include +#include +#include +#include + +static void +report_failed_grab (GtkWidget *parent_window, const char *what) +{ + GtkWidget *err; + + err = gtk_message_dialog_new(GTK_WINDOW(parent_window), 0, + GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, + "Could not grab %s. A malicious client may be eavesdropping " + "on your session.", what); + gtk_window_set_position(GTK_WINDOW(err), GTK_WIN_POS_CENTER); + + gtk_dialog_run(GTK_DIALOG(err)); + + gtk_widget_destroy(err); +} + +static void +ok_dialog(GtkWidget *entry, gpointer dialog) +{ + g_return_if_fail(GTK_IS_DIALOG(dialog)); + gtk_dialog_response(GTK_DIALOG(dialog), GTK_RESPONSE_OK); +} + +static gboolean +check_none(GtkWidget *widget, GdkEventKey *event, gpointer dialog) +{ + switch (event->keyval) { + case GDK_KEY_Escape: + /* esc -> close dialog */ + gtk_dialog_response(GTK_DIALOG(dialog), GTK_RESPONSE_CLOSE); + return TRUE; + case GDK_KEY_Tab: + /* tab -> focus close button */ + gtk_widget_grab_focus(gtk_dialog_get_widget_for_response( + dialog, GTK_RESPONSE_CLOSE)); + return TRUE; + default: + /* eat all other key events */ + return TRUE; + } +} + +static int +parse_env_hex_color(const char *env, GdkRGBA *c) +{ + const char *s; + unsigned long ul; + char *ep; + size_t n; + + if ((s = getenv(env)) == NULL) + return 0; + + memset(c, 0, sizeof(*c)); + + /* Permit hex rgb or rrggbb optionally prefixed by '#' or '0x' */ + if (*s == '#') + s++; + else if (strncmp(s, "0x", 2) == 0) + s += 2; + n = strlen(s); + if (n != 3 && n != 6) + goto bad; + ul = strtoul(s, &ep, 16); + if (*ep != '\0' || ul > 0xffffff) { + bad: + fprintf(stderr, "Invalid $%s - invalid hex color code\n", env); + return 0; + } + /* Valid hex sequence; expand into a GdkColor */ + if (n == 3) { + /* 4-bit RGB */ + c->red = ((ul >> 8) & 0xf) << 12; + c->green = ((ul >> 4) & 0xf) << 12; + c->blue = (ul & 0xf) << 12; + } else { + /* 8-bit RGB */ + c->red = ((ul >> 16) & 0xff) << 8; + c->green = ((ul >> 8) & 0xff) << 8; + c->blue = (ul & 0xff) << 8; + } + return 1; +} + +static int +passphrase_dialog(char *message, int prompt_type) +{ + const char *failed; + char *passphrase, *local; + int result, grab_tries, grab_server, grab_pointer; + int buttons, default_response; + GtkWidget *parent_window, *dialog, *entry; + GdkGrabStatus status; + GdkRGBA fg, bg; + GdkDisplay *display; + GdkDeviceManager *device_manager; + GdkDevice *pointer; + GdkDevice* keyboard; + int fg_set = 0, bg_set = 0; + + grab_server = (getenv("GNOME_SSH_ASKPASS_GRAB_SERVER") != NULL); + grab_pointer = (getenv("GNOME_SSH_ASKPASS_GRAB_POINTER") != NULL); + grab_tries = 0; + + fg_set = parse_env_hex_color("GNOME_SSH_ASKPASS_FG_COLOR", &fg); + bg_set = parse_env_hex_color("GNOME_SSH_ASKPASS_BG_COLOR", &bg); + + /* Create an invisible parent window so that GtkDialog doesn't + * complain. */ + parent_window = gtk_window_new(GTK_WINDOW_TOPLEVEL); + + switch (prompt_type) { + case PROMPT_CONFIRM: + buttons = GTK_BUTTONS_YES_NO; + default_response = GTK_RESPONSE_YES; + break; + case PROMPT_NONE: + buttons = GTK_BUTTONS_CLOSE; + default_response = GTK_RESPONSE_CLOSE; + break; + default: + buttons = GTK_BUTTONS_OK_CANCEL; + default_response = GTK_RESPONSE_OK; + break; + } + + dialog = gtk_message_dialog_new(GTK_WINDOW(parent_window), 0, + GTK_MESSAGE_QUESTION, buttons, "%s", message); + + gtk_window_set_title(GTK_WINDOW(dialog), "Secure SHELL dialog"); + gtk_window_set_position (GTK_WINDOW(dialog), GTK_WIN_POS_CENTER); + gtk_window_set_keep_above(GTK_WINDOW(dialog), TRUE); + gtk_dialog_set_default_response(GTK_DIALOG(dialog), default_response); + gtk_window_set_keep_above(GTK_WINDOW(dialog), TRUE); + + if (fg_set) + gtk_widget_override_color(dialog, GTK_STATE_NORMAL, &fg); + if (bg_set) + gtk_widget_override_background_color(dialog, GTK_STATE_NORMAL, &bg); + + if (prompt_type == PROMPT_ENTRY || prompt_type == PROMPT_NONE) { + entry = gtk_entry_new(); + if (fg_set) + gtk_widget_override_color(entry, GTK_STATE_NORMAL, &fg); + if (bg_set) + gtk_widget_override_background_color(entry, GTK_STATE_NORMAL, &bg); + gtk_box_pack_start( + GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), + entry, FALSE, FALSE, 0); + gtk_entry_set_visibility(GTK_ENTRY(entry), FALSE); + gtk_widget_grab_focus(entry); + if (prompt_type == PROMPT_ENTRY) { + gtk_widget_show(entry); + /* Make close dialog */ + g_signal_connect(G_OBJECT(entry), "activate", + G_CALLBACK(ok_dialog), dialog); + } else { + /* + * Ensure the 'close' button is not focused by default + * but is still reachable via tab. This is a bit of a + * hack - it uses a hidden entry that responds to a + * couple of keypress events (escape and tab only). + */ + gtk_widget_realize(entry); + g_signal_connect(G_OBJECT(entry), "key_press_event", + G_CALLBACK(check_none), dialog); + } + } + + + display = gdk_display_get_default(); + device_manager = gdk_display_get_device_manager(display); + pointer = gdk_device_manager_get_client_pointer(device_manager); + keyboard = gdk_device_get_associated_device(pointer); + + /* Grab focus */ + gtk_widget_show_now(dialog); + if (grab_pointer) { + for(;;) { + status = gdk_device_grab(pointer, + (gtk_widget_get_window(GTK_WIDGET(dialog))), + GDK_OWNERSHIP_WINDOW, TRUE, 0, NULL, + GDK_CURRENT_TIME); + if (status == GDK_GRAB_SUCCESS) + break; + usleep(GRAB_WAIT * 1000); + if (++grab_tries > GRAB_TRIES) { + failed = "mouse"; + goto nograb; + } + } + } + for(;;) { + status = gdk_device_grab(keyboard, + (gtk_widget_get_window(GTK_WIDGET(dialog))), + GDK_OWNERSHIP_WINDOW, FALSE, GDK_ALL_EVENTS_MASK, NULL, + GDK_CURRENT_TIME); + if (status == GDK_GRAB_SUCCESS) + break; + usleep(GRAB_WAIT * 1000); + if (++grab_tries > GRAB_TRIES) { + failed = "keyboard"; + goto nograbkb; + } + } + if (grab_server) { + gdk_x11_grab_server(); + } + + result = gtk_dialog_run(GTK_DIALOG(dialog)); + + /* Ungrab */ + if (grab_server) + XUngrabServer(gdk_x11_get_default_xdisplay()); + if (grab_pointer) + gdk_device_ungrab(pointer, GDK_CURRENT_TIME); + gdk_device_ungrab(keyboard, GDK_CURRENT_TIME); + gdk_flush(); + + /* Report passphrase if user selected OK */ + if (prompt_type == PROMPT_ENTRY) { + passphrase = g_strdup(gtk_entry_get_text(GTK_ENTRY(entry))); + if (result == GTK_RESPONSE_OK) { + local = g_locale_from_utf8(passphrase, + strlen(passphrase), NULL, NULL, NULL); + if (local != NULL) { + puts(local); + memset(local, '\0', strlen(local)); + g_free(local); + } else { + puts(passphrase); + } + } + /* Zero passphrase in memory */ + memset(passphrase, '\b', strlen(passphrase)); + gtk_entry_set_text(GTK_ENTRY(entry), passphrase); + memset(passphrase, '\0', strlen(passphrase)); + g_free(passphrase); + } + + gtk_widget_destroy(dialog); + if (result != GTK_RESPONSE_OK && result != GTK_RESPONSE_YES) + return -1; + return 0; + + nograbkb: + /* + * At least one grab failed - ungrab what we got, and report + * the failure to the user. Note that XGrabServer() cannot + * fail. + */ + gdk_device_ungrab(pointer, GDK_CURRENT_TIME); + nograb: + if (grab_server) + XUngrabServer(gdk_x11_get_default_xdisplay()); + gtk_widget_destroy(dialog); + + report_failed_grab(parent_window, failed); + + return (-1); +} + +int +main(int argc, char **argv) +{ + char *message, *prompt_mode; + int result, prompt_type = PROMPT_ENTRY; + + gtk_init(&argc, &argv); + + if (argc > 1) { + message = g_strjoinv(" ", argv + 1); + } else { + message = g_strdup("Enter your passphrase:"); + } + + if ((prompt_mode = getenv("SSH_ASKPASS_PROMPT")) != NULL) { + if (strcasecmp(prompt_mode, "confirm") == 0) + prompt_type = PROMPT_CONFIRM; + else if (strcasecmp(prompt_mode, "none") == 0) + prompt_type = PROMPT_NONE; + } + + setvbuf(stdout, 0, _IONBF, 0); + result = passphrase_dialog(message, prompt_type); + g_free(message); + + return (result); +} diff -ruN openssh-9.4p1/contrib/ssh-askpass-kdialog openssh-9.4p1+x509-14.2.1/contrib/ssh-askpass-kdialog --- openssh-9.4p1/contrib/ssh-askpass-kdialog 1970-01-01 02:00:00.000000000 +0200 +++ openssh-9.4p1+x509-14.2.1/contrib/ssh-askpass-kdialog 2023-08-20 10:07:00.000000000 +0300 @@ -0,0 +1,38 @@ +#! /bin/sh +# +# Copyright (c) 2018-2019 Roumen Petrov. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +if test "x$SSH_ASKPASS_PROMPT" = "xconfirm" ; then + prompt="${1-Unknown confirmation request}" + exec \ + kdialog --yesno "Secure SHELL confirmation:\n$prompt" +fi +if test "x$SSH_ASKPASS_PROMPT" = "xnone" ; then + prompt="${1-Unknown notification}" + exec \ + kdialog --msgbox "Secure SHELL notification:\n$prompt" +fi + +prompt="${1-Enter your passphrase:}" +exec \ +kdialog --title "Secure SHELL" --password "$prompt" diff -ruN openssh-9.4p1/contrib/ssh-copy-id openssh-9.4p1+x509-14.2.1/contrib/ssh-copy-id --- openssh-9.4p1/contrib/ssh-copy-id 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/contrib/ssh-copy-id 2023-08-20 10:07:00.000000000 +0300 @@ -1,8 +1,9 @@ -#!/bin/sh +#! /bin/sh # Copyright (c) 1999-2023 Philip Hands # 2021 Carlos Rodríguez Gili # 2020 Matthias Blümel +# 2019-2023 Roumen Petrov, Sofia, Bulgaria # 2017 Sebastien Boyron # 2013 Martin Kletzander # 2010 Adeodato =?iso-8859-1?Q?Sim=F3?= @@ -36,8 +37,6 @@ # Shell script to install your public key(s) on a remote machine # See the ssh-copy-id(1) man page for details -# shellcheck shell=dash - # check that we have something mildly sane as our shell, or try to find something better if false ^ printf "%s: WARNING: ancient shell, hunting for a more modern one... " "$0" then @@ -61,10 +60,10 @@ fi fi -# shellcheck disable=SC2010 DEFAULT_PUB_ID_FILE=$(ls -t "${HOME}"/.ssh/id*.pub 2>/dev/null | grep -v -- '-cert.pub$' | head -n 1) SSH="ssh -a -x" -TARGET_PATH=".ssh/authorized_keys" +SFTP= +TARGET_PATH=.ssh/authorized_keys umask 0177 usage () { @@ -85,7 +84,7 @@ use_id_file() { L_ID_FILE="$1" - if [ -z "$L_ID_FILE" ] ; then + if test -z "$L_ID_FILE" ; then printf '%s: ERROR: no ID file found\n' "$0" exit 1 fi @@ -96,13 +95,13 @@ PUB_ID_FILE="$L_ID_FILE.pub" fi - [ "$FORCED" ] || PRIV_ID_FILE=$(dirname "$PUB_ID_FILE")/$(basename "$PUB_ID_FILE" .pub) + $FORCED || PRIV_ID_FILE=$(dirname "$PUB_ID_FILE")/$(basename "$PUB_ID_FILE" .pub) # check that the files are readable for f in "$PUB_ID_FILE" ${PRIV_ID_FILE:+"$PRIV_ID_FILE"} ; do ErrMSG=$( { : < "$f" ; } 2>&1 ) || { L_PRIVMSG="" - [ "$f" = "$PRIV_ID_FILE" ] && L_PRIVMSG=" (to install the contents of '$PUB_ID_FILE' anyway, look at the -f option)" + test "$f" = "$PRIV_ID_FILE" && L_PRIVMSG=" (to install the contents of '$PUB_ID_FILE' anyway, look at the -f option)" printf "\\n%s: ERROR: failed to open ID file '%s': %s\\n" "$0" "$f" "$(printf '%s\n%s\n' "$ErrMSG" "$L_PRIVMSG" | sed -e 's/.*: *//')" exit 1 } @@ -111,29 +110,34 @@ GET_ID="cat \"$PUB_ID_FILE\"" } -if [ -n "$SSH_AUTH_SOCK" ] && ssh-add -L >/dev/null 2>&1 ; then +if test -n "$SSH_AUTH_SOCK" && ssh-add -L >/dev/null 2>&1 ; then GET_ID="ssh-add -L" fi +SEEN_OPT_I=false +FORCED=false +DRY_RUN=false +OPTS_oF= +SSH_PORT= while getopts "i:o:p:F:t:fnsxh?" OPT do case "$OPT" in i) - [ "${SEEN_OPT_I}" ] && { + if $SEEN_OPT_I ; then printf '\n%s: ERROR: -i option must not be specified more than once\n\n' "$0" usage - } - SEEN_OPT_I="yes" + fi + SEEN_OPT_I=: use_id_file "${OPTARG:-$DEFAULT_PUB_ID_FILE}" ;; o|F) OPTS_oF="${OPTS_oF:+$OPTS_oF }-$OPT '$(quote "${OPTARG}")'" ;; f) - FORCED=1 + FORCED=: ;; n) - DRY_RUN=1 + DRY_RUN=: ;; p) SSH_PORT=${OPTARG} @@ -142,7 +146,7 @@ SFTP=sftp ;; t) - TARGET_PATH="${OPTARG}" + TARGET_PATH="$OPTARG" ;; x) SET_X="set -x;" @@ -154,12 +158,12 @@ esac done #shift all args to keep only USER_HOST -shift $((OPTIND-1)) +shift `expr $OPTIND - 1` -if [ $# = 0 ] ; then +if test $# = 0 ; then usage fi -if [ $# != 1 ] ; then +if test $# != 1 ; then printf '%s: ERROR: Too many arguments. Expecting a target hostname, got: %s\n\n' "$0" "$SAVEARGS" >&2 usage fi @@ -171,13 +175,11 @@ # and populate "$@" for later use (only way to get proper quoting of options) eval set -- "$SSH_OPTS" -# shellcheck disable=SC2086 -if [ -z "$(eval $GET_ID)" ] && [ -r "${PUB_ID_FILE:=$DEFAULT_PUB_ID_FILE}" ] ; then +if test -z "$(eval $GET_ID)" && test -r "${PUB_ID_FILE:=$DEFAULT_PUB_ID_FILE}" ; then use_id_file "$PUB_ID_FILE" fi -# shellcheck disable=SC2086 -if [ -z "$(eval $GET_ID)" ] ; then +if test -z "$(eval $GET_ID)" ; then printf '%s: ERROR: No identities found\n' "$0" >&2 exit 1 fi @@ -192,7 +194,7 @@ # repopulate "$@" inside this function eval set -- "$SSH_OPTS" - while read -r ID || [ "$ID" ] ; do + while read -r ID || test -n "$ID" ; do printf '%s\n' "$ID" > "$L_TMP_ID_FILE" # the next line assumes $PRIV_ID_FILE only set if using a single id file - this @@ -203,16 +205,16 @@ -o ControlPath=none \ -o LogLevel=INFO \ -o PreferredAuthentications=publickey \ - -o IdentitiesOnly=yes "$@" exit >"$L_OUTPUT_FILE" 2>&1 /dev/null + -o IdentitiesOnly=yes "$@" exit > "$L_OUTPUT_FILE" 2>&1 /dev/null # this error counts as a success if we're setting up an sftp connection } then : > "$L_TMP_ID_FILE" else - grep 'Permission denied' "$L_OUTPUT_FILE" >/dev/null || { - sed -e 's/^/ERROR: /' <"$L_OUTPUT_FILE" >"$L_TMP_ID_FILE" + grep 'Permission denied' "$L_OUTPUT_FILE" > /dev/null 2>&1 || { + sed -e 's/^/ERROR: /' < "$L_OUTPUT_FILE" > "$L_TMP_ID_FILE" cat >/dev/null #consume the other keys, causing loop to end } fi @@ -224,21 +226,19 @@ # populate_new_ids() uses several global variables ($USER_HOST, $SSH_OPTS ...) # and has the side effect of setting $NEW_IDS populate_new_ids() { - if [ "$FORCED" ] ; then - # shellcheck disable=SC2086 + if $FORCED ; then NEW_IDS=$(eval $GET_ID) return fi printf '%s: INFO: attempting to log in with the new key(s), to filter out any that are already installed\n' "$0" >&2 - # shellcheck disable=SC2086 NEW_IDS=$(eval $GET_ID | filter_ids $1) if expr "$NEW_IDS" : "^ERROR: " >/dev/null ; then printf '\n%s: %s\n\n' "$0" "$NEW_IDS" >&2 exit 1 fi - if [ -z "$NEW_IDS" ] ; then + if test -z "$NEW_IDS" ; then printf '\n%s: WARNING: All keys were skipped because they already exist on the remote system.\n' "$0" >&2 printf '\t\t(if you think this is a mistake, you may want to use -f option)\n\n' >&2 exit 0 @@ -249,41 +249,42 @@ # installkey_sh [target_path] # produce a one-liner to add the keys to remote $TARGET_PATH installkeys_sh() { - # In setting INSTALLKEYS_SH: - # the tr puts it all on one line (to placate tcsh) - # (hence the excessive use of semi-colons (;) ) - # then in the command: + # In the command: # cd to be at $HOME, just in case; - # the -z `tail ...` checks for a trailing newline. The echo adds one if was missing + # OpenWrt has a special case for root only + # the -z "`tail ...`" checks for a trailing newline. The echo adds one if was missing # the cat adds the keys we're getting via STDIN # and if available restorecon is used to restore the SELinux context - # OpenWrt has a special case for root only. - INSTALLKEYS_SH=$(tr '\t\n' ' ' <<-EOF + # then: + # the tr puts it all on one line (to placate tcsh) + # (hence the excessive use of semi-colons (;) ) + INSTALLKEYS_SH=$( +cat </dev/null\`" ] || - echo >> "\${AUTH_KEY_FILE}" || exit 1; } && - cat >> "\${AUTH_KEY_FILE}" || exit 1; + AUTH_KEY_DIR=\`dirname "\$AUTH_KEY_FILE"\`; + mkdir -p "\$AUTH_KEY_DIR" && + { test -z "\`tail -1c "\$AUTH_KEY_FILE" 2>/dev/null\`" || + echo >> "\$AUTH_KEY_FILE" || exit 1; } && + cat >> "\$AUTH_KEY_FILE" || exit 1; if type restorecon >/dev/null 2>&1; then - restorecon -F "\${AUTH_KEY_DIR}" "\${AUTH_KEY_FILE}"; + restorecon -F "\$AUTH_KEY_DIR" "\$AUTH_KEY_FILE"; fi - EOF - ) +EOF +) + INSTALLKEYS_SH=$(echo $INSTALLKEYS_SH || tr '\t\n' ' ') # to defend against quirky remote shells: use 'exec sh -c' to get POSIX; printf "exec sh -c '%s'" "${INSTALLKEYS_SH}" } -#shellcheck disable=SC2120 # the 'eval set' confuses this installkeys_via_sftp() { - AUTH_KEY_FILE=${TARGET_PATH} - AUTH_KEY_DIR=$(dirname "${AUTH_KEY_FILE}") + AUTH_KEY_FILE="$TARGET_PATH" + AUTH_KEY_DIR=$(dirname "$AUTH_KEY_FILE") # repopulate "$@" inside this function eval set -- "$SSH_OPTS" @@ -292,13 +293,12 @@ L_SHARED_CON=$SCRATCH_DIR/master-conn $SSH -f -N -M -S "$L_SHARED_CON" "$@" L_CLEANUP="$SSH -S $L_SHARED_CON -O exit 'ignored' >/dev/null 2>&1 ; $SCRATCH_CLEANUP" - #shellcheck disable=SC2064 trap "$L_CLEANUP" EXIT TERM INT QUIT sftp -b - -o "ControlPath=$L_SHARED_CON" "ignored" <<-EOF || return 1 -get "$AUTH_KEY_FILE" "$L_KEYS" EOF # add a newline or create file if it's missing, same like above - [ -z "$(tail -1c "$L_KEYS" 2>/dev/null)" ] || echo >> "$L_KEYS" + test -z "$(tail -1c "$L_KEYS" 2>/dev/null)" || echo >> "$L_KEYS" # append the keys being piped in here cat >> "$L_KEYS" sftp -b - -o "ControlPath=$L_SHARED_CON" "ignored" <<-EOF || return 1 @@ -307,18 +307,16 @@ put $L_KEYS "$AUTH_KEY_FILE" chmod 600 "$AUTH_KEY_FILE" EOF - #shellcheck disable=SC2064 eval "$L_CLEANUP" && trap "$SCRATCH_CLEANUP" EXIT TERM INT QUIT } # create a scratch dir for any temporary files needed if SCRATCH_DIR=$(mktemp -d ~/.ssh/ssh-copy-id.XXXXXXXXXX) && - [ "$SCRATCH_DIR" ] && [ -d "$SCRATCH_DIR" ] + test -n "$SCRATCH_DIR" && test -d "$SCRATCH_DIR" then chmod 0700 "$SCRATCH_DIR" SCRATCH_CLEANUP="rm -rf \"$SCRATCH_DIR\"" - #shellcheck disable=SC2064 trap "$SCRATCH_CLEANUP" EXIT TERM INT QUIT else printf '%s: ERROR: failed to create required temporary directory under ~/.ssh\n' "$0" >&2 @@ -328,44 +326,43 @@ REMOTE_VERSION=$($SSH -v -o PreferredAuthentications=',' -o ControlPath=none "$@" 2>&1 | sed -ne 's/.*remote software version //p') -# shellcheck disable=SC2029 case "$REMOTE_VERSION" in NetScreen*) populate_new_ids 1 for KEY in $(printf "%s" "$NEW_IDS" | cut -d' ' -f2) ; do - KEY_NO=$((KEY_NO + 1)) + KEY_NO=`expr $KEY_NO + 1` printf '%s\n' "$KEY" | grep ssh-dss >/dev/null || { printf '%s: WARNING: Non-dsa key (#%d) skipped (NetScreen only supports DSA keys)\n' "$0" "$KEY_NO" >&2 continue } - [ "$DRY_RUN" ] || printf 'set ssh pka-dsa key %s\nsave\nexit\n' "$KEY" | $SSH -T "$@" >/dev/null 2>&1 - if [ $? = 255 ] ; then + $DRY_RUN || printf 'set ssh pka-dsa key %s\nsave\nexit\n' "$KEY" | $SSH -T "$@" >/dev/null 2>&1 + if test $? = 255 ; then printf '%s: ERROR: installation of key #%d failed (please report a bug describing what caused this, so that we can make this message useful)\n' "$0" "$KEY_NO" >&2 else - ADDED=$((ADDED + 1)) + ADDED=`expr $ADDED + 1` fi done - if [ -z "$ADDED" ] ; then + if test -z "$ADDED" ; then exit 1 fi ;; *) # Assuming that the remote host treats $TARGET_PATH as one might expect populate_new_ids 0 - if ! [ "$DRY_RUN" ] ; then + if ! $DRY_RUN ; then printf '%s\n' "$NEW_IDS" | \ - if [ "$SFTP" ] ; then - #shellcheck disable=SC2119 - installkeys_via_sftp - else - $SSH "$@" "$(installkeys_sh)" - fi || exit 1 + if test -n "$SFTP" ; then + installkeys_via_sftp + else + $SSH "$@" "$(installkeys_sh)" + fi \ + || exit 1 fi ADDED=$(printf '%s\n' "$NEW_IDS" | wc -l) ;; esac -if [ "$DRY_RUN" ] ; then +if $DRY_RUN ; then cat <<-EOF =-=-=-=-=-=-=-= Would have added the following key(s): @@ -374,7 +371,7 @@ =-=-=-=-=-=-=-= EOF else - [ -z "$SFTP" ] || PORT_OPT=P + test -z "$SFTP" || PORT_OPT=P cat <<-EOF Number of key(s) added: $ADDED diff -ruN openssh-9.4p1/contrib/ssh-copy-id.1 openssh-9.4p1+x509-14.2.1/contrib/ssh-copy-id.1 --- openssh-9.4p1/contrib/ssh-copy-id.1 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/contrib/ssh-copy-id.1 2023-08-20 10:07:00.000000000 +0300 @@ -93,17 +93,6 @@ do a dry-run. Instead of installing keys on the remote system simply prints the key(s) that would have been installed. -.It Fl s -SFTP mode: usually the public keys are installed -by executing commands on the remote side. -With this option the user's -.Pa ~/.ssh/authorized_keys -file will be downloaded, modified locally and uploaded with sftp. -This option is useful if the server has restrictions -on commands which can be used on the remote side. -.It Fl t Ar target_path -the path on the target system where the keys should be added -(defaults to ".ssh/authorized_keys") .It Fl p Ar port , Fl o Ar ssh_option These two options are simply passed through untouched, along with their argument, to allow one to set the port or other @@ -115,6 +104,17 @@ .Xr ssh 1 Ns 's configuration file: .Xr ssh_config 5 . +.It Fl s +SFTP mode: usually the public keys are installed +by executing commands on the remote side. +With this option the user's +.Pa ~/.ssh/authorized_keys +file will be downloaded, modified locally and uploaded with sftp. +This option is useful if the server has restrictions +on commands which can be used on the remote side. +.It Fl t Ar target_path +the path on the target system where the keys should be added +(defaults to ".ssh/authorized_keys") .It Fl x This option is for debugging the .Nm @@ -137,7 +137,7 @@ rather than the comment contained in that file, which is a bit of a shame. Otherwise, if .Xr ssh-add 1 -provides no keys contents of the +provides no keys contents of the .Ic default_ID_file will be used. .Pp diff -ruN openssh-9.4p1/contrib/suse/openssh.spec openssh-9.4p1+x509-14.2.1/contrib/suse/openssh.spec --- openssh-9.4p1/contrib/suse/openssh.spec 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/contrib/suse/openssh.spec 2023-08-20 10:07:00.000000000 +0300 @@ -75,8 +75,6 @@ This package contains an X Window System passphrase dialog for OpenSSH. %changelog -* Mon Jul 20 2020 Damien Miller -- Add ssh-sk-helper and corresponding manual page. * Wed Oct 26 2005 Iain Morgan - Removed accidental inclusion of --without-zlib-version-check * Tue Oct 25 2005 Iain Morgan @@ -213,7 +211,6 @@ %attr(0755,root,root) %{_libdir}/ssh/sftp-server %attr(4711,root,root) %{_libdir}/ssh/ssh-keysign %attr(0755,root,root) %{_libdir}/ssh/ssh-pkcs11-helper -%attr(0755,root,root) %{_libdir}/ssh/ssh-sk-helper %attr(0644,root,root) %doc %{_mandir}/man1/scp.1* %attr(0644,root,root) %doc %{_mandir}/man1/sftp.1* %attr(0644,root,root) %doc %{_mandir}/man1/ssh.1* @@ -227,7 +224,6 @@ %attr(0644,root,root) %doc %{_mandir}/man8/sftp-server.8* %attr(0644,root,root) %doc %{_mandir}/man8/ssh-keysign.8* %attr(0644,root,root) %doc %{_mandir}/man8/ssh-pkcs11-helper.8* -%attr(0644,root,root) %doc %{_mandir}/man8/ssh-sk-helper.8* %attr(0644,root,root) %doc %{_mandir}/man8/sshd.8* %attr(0644,root,root) /var/adm/fillup-templates/sysconfig.ssh diff -ruN openssh-9.4p1/contrib/suse/pkixssh.changes openssh-9.4p1+x509-14.2.1/contrib/suse/pkixssh.changes --- openssh-9.4p1/contrib/suse/pkixssh.changes 1970-01-01 02:00:00.000000000 +0200 +++ openssh-9.4p1+x509-14.2.1/contrib/suse/pkixssh.changes 2023-08-20 10:07:00.000000000 +0300 @@ -0,0 +1 @@ +# Not managed, please see source repository for ./pkixssh.spec changes. diff -ruN openssh-9.4p1/contrib/suse/pkixssh.spec openssh-9.4p1+x509-14.2.1/contrib/suse/pkixssh.spec --- openssh-9.4p1/contrib/suse/pkixssh.spec 1970-01-01 02:00:00.000000000 +0200 +++ openssh-9.4p1+x509-14.2.1/contrib/suse/pkixssh.spec 2023-08-20 10:07:00.000000000 +0300 @@ -0,0 +1,316 @@ +# +# spec file for pkixssh package +# +# This is free software; see Copyright file in the source +# distribution for precise wording. +# +# Copyright (c) 2019-2022 Roumen Petrov +# + +# Do we want to enable building with ldap? (1=yes 0=no) +%global enable_ldap 1 + +# Do we want to enable test with ldap? (1=yes 0=no) +%global enable_ldap_test 1 + +# Do we use FIPS capable OpenSSL library ? (1=yes 0=no) +%global enable_openssl_fips 1 + +# Do we want to enable FIPS test? (1=yes 0=no) +%global enable_fips_test 1 + +# Do we want to use fipscheck? (1=yes 0=no) +%global use_fipscheck 1 + +# Do we want to use Linux auditing? (1=yes 0=no) +%global enable_audit_module 1 + + +# Disable non-working configurations +%if !%{enable_openssl_fips} +%undefine enable_fips_test +%global enable_fips_test 0 +%endif + +%if 0%{?sle_version} >= 120000 && 0%{?sle_version} < 120200 +# NOTE: Exclude fipscheck on SLE 12 releases before SP2 due to +# missing package with header files (fipscheck-devel). Why? +%undefine use_fipscheck +%global use_fipscheck 0 +%endif +%if 0%{?sles_version} == 11 +%undefine use_fipscheck +%global use_fipscheck 0 +%endif +%if !%{enable_openssl_fips} +%undefine use_fipscheck +%global use_fipscheck 0 +%endif + + +# Conditional configurations +# Note openSUSE Tumbleweed: +# {?suse_version} > 1500 - current upcoming release (changing) +%if 0%{?sle_version} >= 150000 || 0%{?suse_version} > 1500 +%define ldap_libexecdir /usr/sbin +%define ldap_moduledir %{_libdir}/openldap +%else +%define ldap_libexecdir /usr/lib/openldap +%define ldap_moduledir /usr/lib/openldap/modules +%endif + + +# norootforbuild + +Url: https://roumenpetrov.info/secsh/ + +Name: pkixssh +Summary: PKIX-SSH, Advanced secure shell implementation +Version: 14.2.1 +Release: 1 +License: BSD-2-Clause +Group: Productivity/Networking/SSH + +PreReq: permissions +Requires(pre): %insserv_prereq %fillup_prereq + +BuildRequires: libselinux-devel +BuildRequires: zlib-devel +BuildRequires: pam-devel +BuildRequires: libopenssl-devel openssl +%if %{enable_ldap} +BuildRequires: openldap2-devel openldap2-client +%endif +%if %{enable_ldap_test} +BuildRequires: openldap2 +%endif +%if %{enable_openssl_fips} +# Actually check-sum files for OpenSSL libraries are is separate package! +# To minimise installation difficulties let make them required at run time. +%if 0%{?suse_version} == 1500 +BuildRequires: libopenssl1_1-hmac +Requires: libopenssl1_1-hmac +%endif +%if 0%{?suse_version} == 1315 +BuildRequires: libopenssl1_0_0-hmac +Requires: libopenssl1_0_0-hmac +%endif +%if 0%{?suse_version} == 1110 +BuildRequires: libopenssl0_9_8-hmac +Requires: libopenssl0_9_8-hmac +%endif +%endif +%if %{use_fipscheck} +BuildRequires: fipscheck-devel fipscheck +%endif +BuildRequires: groff +%if %{enable_audit_module} +BuildRequires: audit-devel +%if 0%{?sle_version} >= 120000 +Requires: libaudit1 +%else +Requires: audit-libs +%endif +%endif +BuildRoot: %{_tmppath}/%{name}-%{version}-build + +%if 0%{?sle_version} >= 120000 +Source0: https://roumenpetrov.info/secsh/src/%{name}-%{version}.tar.xz +%else +Source0: https://roumenpetrov.info/secsh/src/%{name}-%{version}.tar.gz +%endif + + +# Default values for additional components + +%define ssh_sysconfdir %{_sysconfdir}/ssh +%define ssh_libexecdir %{_libexecdir}/ssh +%define ssh_privsep_path /var/lib/sshd + +# Define the UID/GID to use for privilege separation +%define sshd_gid 475 +%define sshd_uid 472 + +%if ! %{defined _fillupdir} + %define _fillupdir /var/adm/fillup-templates +%endif + + +%description +Ssh (Secure Shell) is a program for logging into a remote machine and for +executing commands in a remote machine. It is intended to replace +rlogin and rsh, and provide secure encrypted communications between +two untrusted hosts over an insecure network. + + +%prep +%setup -q + + +%build +%configure \ + --prefix=/usr \ + --libexecdir=%{ssh_libexecdir} \ + --sysconfdir=%{ssh_sysconfdir} \ + --mandir=%{_mandir} \ +%if %{enable_ldap} + --enable-ldap --with-ldap-libexecdir=%{ldap_libexecdir} \ +%else + --disable-ldap \ +%endif +%if %{enable_openssl_fips} + --enable-openssl-fips \ +%else + --disable-openssl-fips \ +%endif +%if %{enable_audit_module} + --with-audit=linux \ +%endif + --with-pie \ + --with-pam \ + --with-privsep-path=%{ssh_privsep_path} +make + + +%check +TERM=dumb \ +make check + +%if %{enable_ldap_test} +%if 0%{?sle_version} < 120000 && !0%{?is_opensuse} +SSH_LDAP_DB=hdb \ +%endif +LDAP_MODULEDIR=%{ldap_moduledir} \ +TERM=dumb \ +SSH_X509TESTS="by_ldap" \ +make check-certs +%endif + +TERM=dumb \ +make t-exec LTESTS=percent || : + +TERM=dumb \ +make t-exec LTESTS=multiplex || : + +%if %{enable_fips_test} +# ignore failures as tests are sensitive to used sandbox +TERM=dumb \ +make t-exec LTESTS=fips-connect-privsep || : +TERM=dumb \ +make t-exec LTESTS=fips-try-ciphers || : +%endif + + +%install +make install DESTDIR=%{buildroot} + +install -d %{buildroot}/etc/pam.d/ +install -m644 contrib/sshd.pam.generic %{buildroot}/etc/pam.d/sshd + +install -d %{buildroot}/etc/init.d/ +install -m744 contrib/suse/rc.sshd %{buildroot}/etc/init.d/sshd + +install -d %{buildroot}%{_fillupdir} +install -m744 contrib/suse/sysconfig.ssh %{buildroot}%{_fillupdir} + + +#obsolete#%clean + + +%pre +/usr/sbin/groupadd -g %{sshd_gid} -o -r sshd 2> /dev/null || : +/usr/sbin/useradd -r -o -g sshd -u %{sshd_uid} -s /bin/false -c "SSH daemon" -d %{ssh_privsep_path} sshd 2> /dev/null || : + + +%post +/usr/bin/ssh-keygen -A +%if 0%{?sles_version} == 11 +%run_permissions %{ssh_sysconfdir}/ssh_config +%run_permissions %{ssh_sysconfdir}/sshd_config +%run_permissions %{ssh_sysconfdir}/moduli +%run_permissions %{ssh_libexecdir}/ssh-keysign +%else +%set_permissions %{ssh_sysconfdir}/ssh_config +%set_permissions %{ssh_sysconfdir}/sshd_config +%set_permissions %{ssh_sysconfdir}/moduli +%set_permissions %{ssh_libexecdir}/ssh-keysign +%endif +%{fillup_and_insserv -n -y ssh sshd} + + +%verifyscript +%verify_permissions -e %{ssh_sysconfdir}/ssh_config +%verify_permissions -e %{ssh_sysconfdir}/sshd_config +%verify_permissions -e %{ssh_sysconfdir}/moduli +%verify_permissions -e %{ssh_libexecdir}/ssh-keysign + + +%preun +%stop_on_removal sshd + + +%postun +%restart_on_update sshd +%{insserv_cleanup} + + +%files +%defattr(-,root,root) +%if 0%{?suse_version} >= 1500 +%license LICENCE +%endif +%doc CREDITS LICENCE OVERVIEW PROTOCOL* README* +%doc TODO +%attr(0755,root,root) %dir %{ssh_sysconfdir} +%attr(0644,root,root) %verify(not mode) %config(noreplace) %{ssh_sysconfdir}/ssh_config +%if 0%{?sles_version} == 11 +%attr(0640,root,root) %verify(not mode) %config(noreplace) %{ssh_sysconfdir}/sshd_config +%else +%attr(0600,root,root) %verify(not mode) %config(noreplace) %{ssh_sysconfdir}/sshd_config +%endif +%attr(0600,root,root) %verify(not mode) %config(noreplace) %{ssh_sysconfdir}/moduli +%attr(0644,root,root) %config(noreplace) /etc/pam.d/sshd +%attr(0755,root,root) %config /etc/init.d/sshd +%if %{use_fipscheck} +# TODO: installation into fipscheck "lib" directory? +%attr(0644,root,root) %{_bindir}/.ssh.hmac +%attr(0644,root,root) %{_bindir}/.ssh-agent.hmac +%attr(0644,root,root) %{_bindir}/.ssh-keygen.hmac +%attr(0644,root,root) %{_sbindir}/.sshd.hmac +%endif +%attr(0755,root,root) %{_bindir}/scp +%attr(0755,root,root) %{_bindir}/sftp +%attr(0755,root,root) %{_bindir}/ssh +%attr(0755,root,root) %{_bindir}/ssh-add +%attr(0755,root,root) %{_bindir}/ssh-agent +%attr(0755,root,root) %{_bindir}/ssh-keygen +%attr(0755,root,root) %{_bindir}/ssh-keyscan +%attr(0755,root,root) %{_sbindir}/sshd +%attr(0755,root,root) %dir %{ssh_libexecdir} +%attr(0755,root,root) %{ssh_libexecdir}/sftp-server +%if 0 +#TODO setuid +%attr(4711,root,root) %verify(not mode) %{ssh_libexecdir}/ssh-keysign +%else +%attr(0755,root,root) %verify(not mode) %{ssh_libexecdir}/ssh-keysign +%endif +%attr(0755,root,root) %{ssh_libexecdir}/ssh-pkcs11-helper +%attr(0644,root,root) %doc %{_mandir}/man1/scp.1* +%attr(0644,root,root) %doc %{_mandir}/man1/sftp.1* +%attr(0644,root,root) %doc %{_mandir}/man1/ssh.1* +%attr(0644,root,root) %doc %{_mandir}/man1/ssh-add.1* +%attr(0644,root,root) %doc %{_mandir}/man1/ssh-agent.1* +%attr(0644,root,root) %doc %{_mandir}/man1/ssh-keygen.1* +%attr(0644,root,root) %doc %{_mandir}/man1/ssh-keyscan.1* +%attr(0644,root,root) %doc %{_mandir}/man5/moduli.5* +%attr(0644,root,root) %doc %{_mandir}/man5/ssh_config.5* +%attr(0644,root,root) %doc %{_mandir}/man5/ssh_engine.5* +%attr(0644,root,root) %doc %{_mandir}/man5/sshd_config.5* +%attr(0644,root,root) %doc %{_mandir}/man8/sftp-server.8* +%attr(0644,root,root) %doc %{_mandir}/man8/ssh-keysign.8* +%attr(0644,root,root) %doc %{_mandir}/man8/ssh-pkcs11-helper.8* +%attr(0644,root,root) %doc %{_mandir}/man8/sshd.8* +%if 0%{?sles_version} != 11 +%attr(0755,root,root) %dir %{_fillupdir} +%endif +%attr(0644,root,root) %{_fillupdir}/sysconfig.ssh diff -ruN openssh-9.4p1/contrib/suse/rc.sshd openssh-9.4p1+x509-14.2.1/contrib/suse/rc.sshd --- openssh-9.4p1/contrib/suse/rc.sshd 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/contrib/suse/rc.sshd 2023-08-20 10:07:00.000000000 +0300 @@ -43,13 +43,11 @@ case "$1" in start) - # Generate any missing host keys - ssh-keygen -A echo -n "Starting SSH daemon" ## Start daemon with startproc(8). If this fails ## the echo return value is set appropriate. - startproc -f -p $SSHD_PIDFILE $SSHD_BIN $SSHD_OPTS -o "PidFile=$SSHD_PIDFILE" + startproc -f -p $SSHD_PIDFILE $SSHD_BIN $SSHD_OPTS -o "PidFile=$SSHD_PIDFILE" # Remember status and be verbose rc_status -v @@ -65,7 +63,7 @@ rc_status -v ;; try-restart) - ## Stop the service and if this succeeds (i.e. the + ## Stop the service and if this succeeds (i.e. the ## service was running before), start it again. $0 status >/dev/null && $0 restart diff -ruN openssh-9.4p1/crypto_api.h openssh-9.4p1+x509-14.2.1/crypto_api.h --- openssh-9.4p1/crypto_api.h 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/crypto_api.h 2023-08-20 10:07:00.000000000 +0300 @@ -1,5 +1,4 @@ /* $OpenBSD: crypto_api.h,v 1.8 2023/01/15 23:05:32 djm Exp $ */ - /* * Assembled from generated headers and source files by Markus Friedl. * Placed in the public domain. diff -ruN openssh-9.4p1/defines.h openssh-9.4p1+x509-14.2.1/defines.h --- openssh-9.4p1/defines.h 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/defines.h 2023-08-20 10:07:00.000000000 +0300 @@ -1,5 +1,6 @@ /* * Copyright (c) 1999-2003 Damien Miller. All rights reserved. + * Copyright (c) 2011-2023 Roumen Petrov. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -25,6 +26,8 @@ #ifndef _DEFINES_H #define _DEFINES_H +#include "config.h" + /* Constants */ #if defined(HAVE_DECL_SHUT_RD) && HAVE_DECL_SHUT_RD == 0 @@ -210,6 +213,10 @@ #define INADDR_LOOPBACK ((u_long)0x7f000001) #endif +#ifndef IN_LOOPBACK +#define IN_LOOPBACK(a) ((((long int) (a)) & 0xff000000) == 0x7f000000) +#endif + /* Types */ /* If sys/types.h does not supply intXX_t, supply them ourselves */ @@ -256,17 +263,12 @@ #define __BIT_TYPES_DEFINED__ #endif -#if !defined(LLONG_MIN) && defined(LONG_LONG_MIN) -#define LLONG_MIN LONG_LONG_MIN -#endif -#if !defined(LLONG_MAX) && defined(LONG_LONG_MAX) -#define LLONG_MAX LONG_LONG_MAX -#endif - #ifndef UINT32_MAX -# if defined(HAVE_DECL_UINT32_MAX) && (HAVE_DECL_UINT32_MAX == 0) +# if !HAVE_DECL_UINT32_MAX # if (SIZEOF_INT == 4) -# define UINT32_MAX UINT_MAX +# define UINT32_MAX UINT_MAX +# elif (SIZEOF_LONG_INT == 4) +# define UINT32_MAX ULONG_MAX # endif # endif #endif @@ -317,10 +319,6 @@ # define HAVE_U_CHAR #endif /* HAVE_U_CHAR */ -#ifndef ULLONG_MAX -# define ULLONG_MAX ((unsigned long long)-1) -#endif - #ifndef SIZE_T_MAX #define SIZE_T_MAX ULONG_MAX #endif /* SIZE_T_MAX */ @@ -335,10 +333,38 @@ #define SIZE_MAX SIZE_T_MAX #endif +#ifndef LLONG_MIN +/* LLONG_MIN is known as LONGLONG_MIN on AIX */ +# ifdef LONGLONG_MIN +# define LLONG_MIN LONGLONG_MIN +# endif + +/* LLONG_MIN is known as LONG_LONG_MIN on HP-UX */ +# ifdef LONG_LONG_MIN +# define LLONG_MIN LONG_LONG_MIN +# endif +#endif /*ndef LLONG_MIN*/ + +#ifndef LLONG_MAX +/* LLONG_MAX is known as LONGLONG_MAX on AIX */ +# ifdef LONGLONG_MAX +# define LLONG_MAX LONGLONG_MAX +# endif + +/* LLONG_MAX is known as LONG_LONG_MAX on HP-UX */ +# ifdef LONG_LONG_MAX +# define LLONG_MAX LONG_LONG_MAX +# endif +#endif /*ndef LLONG_MAX*/ + +#ifndef ULLONG_MAX +# define ULLONG_MAX ((unsigned long long)-1) +#endif + #ifndef INT32_MAX # if (SIZEOF_INT == 4) # define INT32_MAX INT_MAX -# elif (SIZEOF_LONG == 4) +# elif (SIZEOF_LONG_INT == 4) # define INT32_MAX LONG_MAX # else # error "need INT32_MAX" @@ -348,7 +374,7 @@ #ifndef INT64_MAX # if (SIZEOF_INT == 8) # define INT64_MAX INT_MAX -# elif (SIZEOF_LONG == 8) +# elif (SIZEOF_LONG_INT == 8) # define INT64_MAX LONG_MAX # elif (SIZEOF_LONG_LONG_INT == 8) # define INT64_MAX LLONG_MAX @@ -494,11 +520,20 @@ #ifndef MAX # define MAX(a,b) (((a)>(b))?(a):(b)) +#endif +#ifndef MIN # define MIN(a,b) (((a)<(b))?(a):(b)) #endif -#ifndef roundup -# define roundup(x, y) ((((x)+((y)-1))/(y))*(y)) +#ifndef MAXIMUM +# define MAXIMUM MAX +#endif +#ifndef MINIMUM +# define MINIMUM MIN +#endif + +#ifndef ROUNDUP +# define ROUNDUP(x, y) ((((x)+((y)-1))/(y))*(y)) #endif #ifndef timersub @@ -527,46 +562,6 @@ } #endif -#ifndef timespeccmp -#define timespeccmp(tsp, usp, cmp) \ - (((tsp)->tv_sec == (usp)->tv_sec) ? \ - ((tsp)->tv_nsec cmp (usp)->tv_nsec) : \ - ((tsp)->tv_sec cmp (usp)->tv_sec)) -#endif - -/* Operations on timespecs. */ -#ifndef timespecclear -#define timespecclear(tsp) (tsp)->tv_sec = (tsp)->tv_nsec = 0 -#endif -#ifndef timespeccmp -#define timespeccmp(tsp, usp, cmp) \ - (((tsp)->tv_sec == (usp)->tv_sec) ? \ - ((tsp)->tv_nsec cmp (usp)->tv_nsec) : \ - ((tsp)->tv_sec cmp (usp)->tv_sec)) -#endif -#ifndef timespecadd -#define timespecadd(tsp, usp, vsp) \ - do { \ - (vsp)->tv_sec = (tsp)->tv_sec + (usp)->tv_sec; \ - (vsp)->tv_nsec = (tsp)->tv_nsec + (usp)->tv_nsec; \ - if ((vsp)->tv_nsec >= 1000000000L) { \ - (vsp)->tv_sec++; \ - (vsp)->tv_nsec -= 1000000000L; \ - } \ - } while (0) -#endif -#ifndef timespecsub -#define timespecsub(tsp, usp, vsp) \ - do { \ - (vsp)->tv_sec = (tsp)->tv_sec - (usp)->tv_sec; \ - (vsp)->tv_nsec = (tsp)->tv_nsec - (usp)->tv_nsec; \ - if ((vsp)->tv_nsec < 0) { \ - (vsp)->tv_sec--; \ - (vsp)->tv_nsec += 1000000000L; \ - } \ - } while (0) -#endif - #ifndef __P # define __P(x) x #endif @@ -696,11 +691,7 @@ # define DO_LOG_SAFE_IN_SIGHAND #endif -#if !defined(HAVE_MEMMOVE) && defined(HAVE_BCOPY) -# define memmove(s1, s2, n) bcopy((s2), (s1), (n)) -#endif /* !defined(HAVE_MEMMOVE) && defined(HAVE_BCOPY) */ - -#ifndef GETPGRP_VOID +#if !GETPGRP_VOID # include # define getpgrp() getpgrp(0) #endif @@ -888,10 +879,6 @@ #define INET6_ADDRSTRLEN 46 #endif -#ifndef SSH_IOBUFSZ -# define SSH_IOBUFSZ 8192 -#endif - /* * We want functions in openbsd-compat, if enabled, to override system ones. * We no-op out the weak symbol definition rather than remove it to reduce @@ -900,15 +887,6 @@ */ #define DEF_WEAK(x) void __ssh_compat_weak_##x(void) -/* - * Platforms that have arc4random_uniform() and not arc4random_stir() - * shouldn't need the latter. - */ -#if defined(HAVE_ARC4RANDOM) && defined(HAVE_ARC4RANDOM_UNIFORM) && \ - !defined(HAVE_ARC4RANDOM_STIR) -# define arc4random_stir() -#endif - #ifndef HAVE_VA_COPY # ifdef HAVE___VA_COPY # define va_copy(dest, src) __va_copy(dest, src) @@ -935,11 +913,84 @@ # define USE_SYSTEM_GLOB #endif -/* - * sntrup761 uses variable length arrays and c99-style declarations after code, - * so only enable if the compiler supports them. + +/* LDAP use conditions */ +#undef USE_LDAP_STORE +#if defined(USE_OPENSSL_STORE2) && \ + defined(LDAP_ENABLED) && defined(USE_OPENSSL_ENGINE) + /* OpenSSL >= 1.1.1 */ +# define USE_LDAP_STORE 1 +#endif + +#undef USE_X509_LOOKUP_STORE +#if defined(USE_OPENSSL_STORE2) && defined(HAVE_X509_LOOKUP_STORE) + /* OpenSSL >= 3.0 */ +# define USE_X509_LOOKUP_STORE 1 +#endif + +#undef USE_X509_LOOKUP_MYSTORE +#if defined(USE_OPENSSL_STORE2) && !defined(HAVE_X509_LOOKUP_STORE) + /* OpenSSL 1.1.1* only */ +# define USE_X509_LOOKUP_MYSTORE 1 +#endif + + +/* NOTE: + * OpenSSL 1.1.* resets EVP_CIPHER_CTX on each call of EVP_CipherInit()! + * Remark: Pre 1.1.0 behaviour is restored in 1.1.0g (issue #4613). + * Let mark EVP_CipherInit as broken for all OpenSSL 1.1.0* releases: + * - LibreSSL not impacted + * - OPENSSL_init_crypto: OpenSSL 1.1 function + * - EC_POINT_get_affine_coordinates: OpenSSL 1.1.1 function + */ +#if !defined(LIBRESSL_VERSION_NUMBER) && \ + defined(HAVE_OPENSSL_INIT_CRYPTO) && \ + !defined(HAVE_EC_POINT_GET_AFFINE_COORDINATES) +# define BROKEN_EVP_CIPHERINIT +#endif + +#undef USE_BUILTIN_CHACHAPOLY +#ifndef HAVE_EVP_CHACHA20 +# define USE_BUILTIN_CHACHAPOLY +#endif +#ifdef LIBRESSL_VERSION_NUMBER +# if LIBRESSL_VERSION_NUMBER < 0x3010000fL +/* broken EVP_chacha20 */ +# undef USE_BUILTIN_CHACHAPOLY +# define USE_BUILTIN_CHACHAPOLY +# endif +#else +# ifdef BROKEN_EVP_CIPHERINIT +/* crypto-based chachapoly is not usable with OpenSSL 1.1.0-1.1.0f + * (extended to all 1.1.0* releases to avoid run-time test) */ -#if defined(VARIABLE_LENGTH_ARRAYS) && defined(VARIABLE_DECLARATION_AFTER_CODE) -# define USE_SNTRUP761X25519 1 +# undef USE_BUILTIN_CHACHAPOLY +# define USE_BUILTIN_CHACHAPOLY +# endif +#endif + + +#ifndef HAVE_EVP_SHA512 +/* check only for EVP_sha512() as build with OpenSSL is required */ +# undef ENABLE_KEX_SNTRUP761X25519 +#endif + + +#undef USE_RSA_METHOD +#ifndef OPENSSL_NO_RSA +/* TODO: to decide at configuration time */ +# define USE_RSA_METHOD #endif + + +#ifndef UNUSED +# define UNUSED(x) (void)(x) +#endif + +/* secure shell typedefs */ +typedef struct ssh_compat_st ssh_compat; +typedef struct ssh_sign_context_st ssh_sign_ctx; +typedef struct ssh_verify_context_st ssh_verify_ctx; +typedef struct ssh_evp_md_st ssh_evp_md; + #endif /* _DEFINES_H */ diff -ruN openssh-9.4p1/.depend openssh-9.4p1+x509-14.2.1/.depend --- openssh-9.4p1/.depend 2023-08-10 04:11:20.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/.depend 1970-01-01 02:00:00.000000000 +0200 @@ -1,178 +0,0 @@ -# Automatically generated by makedepend. -# Run "make depend" to rebuild. - -# DO NOT DELETE -addr.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h addr.h -addrmatch.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h addr.h match.h log.h ssherr.h -atomicio.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h atomicio.h -audit-bsm.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h -audit-linux.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h -audit.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h -auth-bsdauth.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h -auth-krb5.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h xmalloc.h ssh.h packet.h openbsd-compat/sys-queue.h dispatch.h log.h ssherr.h sshbuf.h sshkey.h misc.h servconf.h uidswap.h hostfile.h auth.h auth-pam.h audit.h loginrec.h -auth-options.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h openbsd-compat/sys-queue.h xmalloc.h ssherr.h log.h sshbuf.h misc.h sshkey.h match.h ssh2.h auth-options.h -auth-pam.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h -auth-passwd.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h packet.h openbsd-compat/sys-queue.h dispatch.h sshbuf.h ssherr.h log.h misc.h servconf.h sshkey.h hostfile.h auth.h auth-pam.h audit.h loginrec.h auth-options.h -auth-rhosts.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h packet.h openbsd-compat/sys-queue.h dispatch.h uidswap.h pathnames.h log.h ssherr.h misc.h xmalloc.h sshbuf.h sshkey.h servconf.h canohost.h hostfile.h auth.h auth-pam.h audit.h loginrec.h -auth-shadow.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h -auth-sia.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h -auth.o: authfile.h monitor_wrap.h channels.h -auth.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h xmalloc.h match.h groupaccess.h log.h ssherr.h sshbuf.h misc.h servconf.h openbsd-compat/sys-queue.h sshkey.h hostfile.h auth.h auth-pam.h audit.h loginrec.h auth-options.h canohost.h uidswap.h packet.h dispatch.h -auth2-chall.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h xmalloc.h ssh2.h sshkey.h hostfile.h auth.h auth-pam.h audit.h loginrec.h sshbuf.h packet.h openbsd-compat/sys-queue.h dispatch.h ssherr.h log.h misc.h servconf.h -auth2-gss.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h -auth2-hostbased.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h xmalloc.h ssh2.h packet.h openbsd-compat/sys-queue.h dispatch.h kex.h mac.h crypto_api.h sshbuf.h log.h ssherr.h misc.h servconf.h sshkey.h hostfile.h auth.h auth-pam.h audit.h loginrec.h canohost.h -auth2-hostbased.o: monitor_wrap.h pathnames.h match.h -auth2-kbdint.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h xmalloc.h packet.h openbsd-compat/sys-queue.h dispatch.h hostfile.h auth.h auth-pam.h audit.h loginrec.h log.h ssherr.h misc.h servconf.h -auth2-none.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h atomicio.h xmalloc.h sshkey.h hostfile.h auth.h auth-pam.h audit.h loginrec.h packet.h openbsd-compat/sys-queue.h dispatch.h log.h ssherr.h misc.h servconf.h ssh2.h monitor_wrap.h -auth2-passwd.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h packet.h openbsd-compat/sys-queue.h dispatch.h ssherr.h log.h sshkey.h hostfile.h auth.h auth-pam.h audit.h loginrec.h monitor_wrap.h misc.h servconf.h -auth2-pubkey.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h xmalloc.h ssh.h ssh2.h packet.h openbsd-compat/sys-queue.h dispatch.h kex.h mac.h crypto_api.h sshbuf.h log.h ssherr.h misc.h servconf.h compat.h sshkey.h hostfile.h auth.h auth-pam.h audit.h loginrec.h -auth2-pubkey.o: pathnames.h uidswap.h auth-options.h canohost.h monitor_wrap.h authfile.h match.h channels.h session.h sk-api.h -auth2-pubkeyfile.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h ssh.h log.h ssherr.h misc.h sshkey.h digest.h hostfile.h auth.h auth-pam.h audit.h loginrec.h auth-options.h authfile.h match.h -auth2.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h atomicio.h xmalloc.h ssh2.h packet.h openbsd-compat/sys-queue.h dispatch.h log.h ssherr.h sshbuf.h misc.h servconf.h sshkey.h hostfile.h auth.h auth-pam.h audit.h loginrec.h pathnames.h monitor_wrap.h digest.h -authfd.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h xmalloc.h ssh.h sshbuf.h sshkey.h authfd.h cipher.h cipher-chachapoly.h chacha.h poly1305.h cipher-aesctr.h rijndael.h log.h ssherr.h atomicio.h misc.h -authfile.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h cipher.h cipher-chachapoly.h chacha.h poly1305.h cipher-aesctr.h rijndael.h ssh.h log.h ssherr.h authfile.h misc.h atomicio.h sshkey.h sshbuf.h krl.h -bitmap.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h bitmap.h -canohost.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h xmalloc.h packet.h openbsd-compat/sys-queue.h dispatch.h log.h ssherr.h canohost.h misc.h -chacha.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h chacha.h -channels.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h openbsd-compat/sys-queue.h xmalloc.h ssh.h ssh2.h ssherr.h sshbuf.h packet.h dispatch.h log.h misc.h channels.h compat.h canohost.h sshkey.h authfd.h pathnames.h match.h -cipher-aes.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h openbsd-compat/openssl-compat.h -cipher-aesctr.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h cipher-aesctr.h rijndael.h -cipher-chachapoly-libcrypto.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h -cipher-chachapoly.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h log.h ssherr.h sshbuf.h cipher-chachapoly.h chacha.h poly1305.h -cipher.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h cipher.h cipher-chachapoly.h chacha.h poly1305.h cipher-aesctr.h rijndael.h misc.h sshbuf.h ssherr.h digest.h openbsd-compat/openssl-compat.h -cleanup.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h log.h ssherr.h -clientloop.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h openbsd-compat/sys-queue.h xmalloc.h ssh.h ssh2.h packet.h dispatch.h sshbuf.h compat.h channels.h sshkey.h cipher.h cipher-chachapoly.h chacha.h poly1305.h cipher-aesctr.h rijndael.h kex.h mac.h crypto_api.h -clientloop.o: myproposal.h log.h ssherr.h misc.h readconf.h clientloop.h sshconnect.h authfd.h atomicio.h sshpty.h match.h msg.h hostfile.h -compat.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h xmalloc.h packet.h openbsd-compat/sys-queue.h dispatch.h compat.h log.h ssherr.h match.h -dh.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h -digest-libc.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h ssherr.h sshbuf.h digest.h -digest-openssl.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h -dispatch.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h ssh2.h log.h ssherr.h dispatch.h packet.h openbsd-compat/sys-queue.h -dns.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h xmalloc.h sshkey.h ssherr.h dns.h log.h digest.h -ed25519.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h crypto_api.h -entropy.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h -fatal.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h log.h ssherr.h -groupaccess.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h xmalloc.h groupaccess.h match.h log.h ssherr.h -gss-genr.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h -gss-serv-krb5.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h -gss-serv.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h -hash.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h crypto_api.h -hmac.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h sshbuf.h digest.h hmac.h -hostfile.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h xmalloc.h match.h sshkey.h hostfile.h log.h ssherr.h misc.h pathnames.h digest.h hmac.h sshbuf.h -kex.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h ssh.h ssh2.h atomicio.h version.h packet.h openbsd-compat/sys-queue.h dispatch.h compat.h cipher.h cipher-chachapoly.h chacha.h poly1305.h cipher-aesctr.h rijndael.h sshkey.h kex.h mac.h crypto_api.h log.h ssherr.h -kex.o: match.h misc.h monitor.h myproposal.h sshbuf.h digest.h xmalloc.h -kexc25519.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h sshkey.h kex.h mac.h crypto_api.h sshbuf.h digest.h ssherr.h ssh2.h -kexdh.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h -kexecdh.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h ssherr.h -kexgen.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h sshkey.h kex.h mac.h crypto_api.h log.h ssherr.h packet.h openbsd-compat/sys-queue.h dispatch.h ssh2.h sshbuf.h digest.h -kexgex.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h -kexgexc.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h -kexgexs.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h -kexsntrup761x25519.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h ssherr.h -krl.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h ./openbsd-compat/sys-tree.h openbsd-compat/sys-queue.h sshbuf.h ssherr.h sshkey.h authfile.h misc.h log.h digest.h bitmap.h utf8.h krl.h -log.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h log.h ssherr.h match.h -loginrec.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h xmalloc.h sshkey.h hostfile.h ssh.h loginrec.h log.h ssherr.h atomicio.h packet.h openbsd-compat/sys-queue.h dispatch.h canohost.h auth.h auth-pam.h audit.h sshbuf.h misc.h -logintest.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h loginrec.h -mac.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h digest.h hmac.h umac.h mac.h misc.h ssherr.h sshbuf.h openbsd-compat/openssl-compat.h -match.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h xmalloc.h match.h misc.h -misc.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h xmalloc.h misc.h log.h ssherr.h ssh.h sshbuf.h -moduli.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h -monitor.o: chacha.h poly1305.h cipher-aesctr.h rijndael.h kex.h mac.h crypto_api.h dh.h packet.h dispatch.h auth-options.h sshpty.h channels.h session.h sshlogin.h canohost.h log.h ssherr.h misc.h servconf.h monitor.h monitor_wrap.h monitor_fdpass.h compat.h ssh2.h authfd.h match.h sk-api.h -monitor.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h ./openbsd-compat/sys-tree.h openbsd-compat/sys-queue.h openbsd-compat/openssl-compat.h atomicio.h xmalloc.h ssh.h sshkey.h sshbuf.h hostfile.h auth.h auth-pam.h audit.h loginrec.h cipher.h cipher-chachapoly.h -monitor_fdpass.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h log.h ssherr.h monitor_fdpass.h -monitor_wrap.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h openbsd-compat/sys-queue.h xmalloc.h ssh.h sshbuf.h sshkey.h cipher.h cipher-chachapoly.h chacha.h poly1305.h cipher-aesctr.h rijndael.h kex.h mac.h crypto_api.h hostfile.h auth.h auth-pam.h audit.h -monitor_wrap.o: loginrec.h auth-options.h packet.h dispatch.h log.h ssherr.h monitor.h monitor_wrap.h atomicio.h monitor_fdpass.h misc.h channels.h session.h servconf.h -msg.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h sshbuf.h ssherr.h log.h atomicio.h msg.h misc.h -mux.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h openbsd-compat/sys-queue.h xmalloc.h log.h ssherr.h ssh.h ssh2.h pathnames.h misc.h match.h sshbuf.h channels.h msg.h packet.h dispatch.h monitor_fdpass.h sshpty.h sshkey.h readconf.h clientloop.h -nchan.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h openbsd-compat/sys-queue.h ssh2.h sshbuf.h ssherr.h packet.h dispatch.h channels.h compat.h log.h -packet.o: channels.h ssh.h packet.h dispatch.h sshbuf.h -packet.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h openbsd-compat/sys-queue.h xmalloc.h compat.h ssh2.h cipher.h cipher-chachapoly.h chacha.h poly1305.h cipher-aesctr.h rijndael.h sshkey.h kex.h mac.h crypto_api.h digest.h log.h ssherr.h canohost.h misc.h -platform-misc.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h -platform-pledge.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h -platform-tracing.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h log.h ssherr.h -platform.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h log.h ssherr.h misc.h servconf.h openbsd-compat/sys-queue.h sshkey.h hostfile.h auth.h auth-pam.h audit.h loginrec.h -poly1305.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h poly1305.h -progressmeter.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h progressmeter.h atomicio.h misc.h utf8.h -readconf.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h openbsd-compat/glob.h xmalloc.h ssh.h ssherr.h cipher.h cipher-chachapoly.h chacha.h poly1305.h cipher-aesctr.h rijndael.h pathnames.h log.h sshkey.h misc.h readconf.h match.h kex.h mac.h crypto_api.h uidswap.h -readconf.o: myproposal.h digest.h -readpass.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h xmalloc.h misc.h pathnames.h log.h ssherr.h ssh.h uidswap.h -rijndael.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h rijndael.h -sandbox-capsicum.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h -sandbox-darwin.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h -sandbox-null.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h -sandbox-pledge.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h -sandbox-rlimit.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h -sandbox-seccomp-filter.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h -sandbox-solaris.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h -sandbox-systrace.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h -scp.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h openbsd-compat/glob.h xmalloc.h ssh.h atomicio.h pathnames.h log.h ssherr.h misc.h progressmeter.h utf8.h sftp.h sftp-common.h sftp-client.h -servconf.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h openbsd-compat/glob.h openbsd-compat/sys-queue.h xmalloc.h ssh.h log.h ssherr.h sshbuf.h misc.h servconf.h pathnames.h cipher.h cipher-chachapoly.h chacha.h poly1305.h cipher-aesctr.h rijndael.h sshkey.h kex.h -servconf.o: mac.h crypto_api.h match.h channels.h groupaccess.h canohost.h packet.h dispatch.h hostfile.h auth.h auth-pam.h audit.h loginrec.h myproposal.h digest.h -serverloop.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h openbsd-compat/sys-queue.h xmalloc.h packet.h dispatch.h sshbuf.h log.h ssherr.h misc.h servconf.h canohost.h sshpty.h channels.h ssh2.h sshkey.h cipher.h cipher-chachapoly.h chacha.h poly1305.h cipher-aesctr.h -serverloop.o: rijndael.h kex.h mac.h crypto_api.h hostfile.h auth.h auth-pam.h audit.h loginrec.h session.h auth-options.h serverloop.h -session.o: hostfile.h auth.h auth-pam.h audit.h loginrec.h auth-options.h authfd.h pathnames.h log.h misc.h servconf.h sshlogin.h serverloop.h canohost.h session.h kex.h mac.h crypto_api.h monitor_wrap.h sftp.h atomicio.h -session.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h openbsd-compat/sys-queue.h xmalloc.h ssh.h ssh2.h sshpty.h packet.h dispatch.h sshbuf.h ssherr.h match.h uidswap.h channels.h sshkey.h cipher.h cipher-chachapoly.h chacha.h poly1305.h cipher-aesctr.h rijndael.h -sftp-client.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h openbsd-compat/sys-queue.h xmalloc.h ssherr.h sshbuf.h log.h atomicio.h progressmeter.h misc.h utf8.h sftp.h sftp-common.h sftp-client.h openbsd-compat/glob.h -sftp-common.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h xmalloc.h ssherr.h sshbuf.h log.h misc.h sftp.h sftp-common.h -sftp-glob.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h xmalloc.h sftp.h sftp-common.h sftp-client.h openbsd-compat/glob.h -sftp-realpath.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h -sftp-server-main.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h log.h ssherr.h sftp.h misc.h xmalloc.h -sftp-server.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h atomicio.h xmalloc.h sshbuf.h ssherr.h log.h misc.h match.h uidswap.h sftp.h sftp-common.h -sftp-usergroup.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h ./openbsd-compat/sys-tree.h log.h ssherr.h xmalloc.h sftp-common.h sftp-client.h openbsd-compat/glob.h sftp-usergroup.h -sftp.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h xmalloc.h log.h ssherr.h pathnames.h misc.h utf8.h sftp.h sshbuf.h sftp-common.h sftp-client.h openbsd-compat/glob.h sftp-usergroup.h -sk-usbhid.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h -sntrup761.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h -srclimit.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h addr.h canohost.h log.h ssherr.h misc.h srclimit.h xmalloc.h -ssh-add.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h xmalloc.h ssh.h log.h ssherr.h sshkey.h sshbuf.h authfd.h authfile.h pathnames.h misc.h digest.h ssh-sk.h sk-api.h hostfile.h -ssh-agent.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h openbsd-compat/sys-queue.h xmalloc.h ssh.h ssh2.h sshbuf.h sshkey.h authfd.h log.h ssherr.h misc.h digest.h match.h msg.h pathnames.h ssh-pkcs11.h sk-api.h myproposal.h -ssh-dss.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h -ssh-ecdsa-sk.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h openbsd-compat/openssl-compat.h sshbuf.h ssherr.h digest.h sshkey.h -ssh-ecdsa.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h -ssh-ed25519-sk.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h crypto_api.h log.h ssherr.h sshbuf.h sshkey.h ssh.h digest.h -ssh-ed25519.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h crypto_api.h log.h ssherr.h sshbuf.h sshkey.h ssh.h -ssh-keygen.o: cipher-chachapoly.h chacha.h poly1305.h cipher-aesctr.h rijndael.h -ssh-keygen.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h xmalloc.h sshkey.h authfile.h sshbuf.h pathnames.h log.h ssherr.h misc.h match.h hostfile.h dns.h ssh.h ssh2.h ssh-pkcs11.h atomicio.h krl.h digest.h utf8.h authfd.h sshsig.h ssh-sk.h sk-api.h cipher.h -ssh-keyscan.o: dispatch.h log.h ssherr.h atomicio.h misc.h hostfile.h ssh_api.h ssh2.h dns.h addr.h -ssh-keyscan.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h openbsd-compat/sys-queue.h xmalloc.h ssh.h sshbuf.h sshkey.h cipher.h cipher-chachapoly.h chacha.h poly1305.h cipher-aesctr.h rijndael.h digest.h kex.h mac.h crypto_api.h compat.h myproposal.h packet.h -ssh-keysign.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h xmalloc.h log.h ssherr.h sshkey.h ssh.h ssh2.h misc.h sshbuf.h authfile.h msg.h canohost.h pathnames.h readconf.h uidswap.h -ssh-pkcs11-client.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h -ssh-pkcs11-helper.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h openbsd-compat/sys-queue.h xmalloc.h sshbuf.h log.h ssherr.h misc.h sshkey.h authfd.h ssh-pkcs11.h -ssh-pkcs11.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h log.h ssherr.h sshkey.h -ssh-rsa.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h -ssh-sk-client.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h log.h ssherr.h sshbuf.h sshkey.h msg.h digest.h pathnames.h ssh-sk.h misc.h -ssh-sk-helper.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h xmalloc.h log.h ssherr.h sshkey.h authfd.h misc.h sshbuf.h msg.h uidswap.h ssh-sk.h -ssh-sk.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h -ssh-xmss.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h -ssh.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h openbsd-compat/openssl-compat.h openbsd-compat/sys-queue.h xmalloc.h ssh.h ssh2.h canohost.h compat.h cipher.h cipher-chachapoly.h chacha.h poly1305.h cipher-aesctr.h rijndael.h packet.h dispatch.h sshbuf.h channels.h -ssh.o: sshkey.h authfd.h authfile.h pathnames.h clientloop.h log.h ssherr.h misc.h readconf.h sshconnect.h kex.h mac.h crypto_api.h sshpty.h match.h msg.h version.h myproposal.h utf8.h -ssh_api.o: authfile.h misc.h version.h myproposal.h sshbuf.h openbsd-compat/openssl-compat.h -ssh_api.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h ssh_api.h openbsd-compat/sys-queue.h cipher.h cipher-chachapoly.h chacha.h poly1305.h cipher-aesctr.h rijndael.h sshkey.h kex.h mac.h crypto_api.h ssh.h ssh2.h packet.h dispatch.h compat.h log.h ssherr.h -sshbuf-getput-basic.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h ssherr.h sshbuf.h -sshbuf-getput-crypto.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h -sshbuf-io.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h ssherr.h sshbuf.h atomicio.h -sshbuf-misc.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h ssherr.h sshbuf.h -sshbuf.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h ssherr.h sshbuf.h misc.h -sshconnect.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h xmalloc.h hostfile.h ssh.h sshbuf.h packet.h openbsd-compat/sys-queue.h dispatch.h sshkey.h sshconnect.h log.h ssherr.h misc.h readconf.h atomicio.h dns.h monitor_fdpass.h ssh2.h version.h authfile.h authfd.h -sshconnect.o: kex.h mac.h crypto_api.h -sshconnect2.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h openbsd-compat/sys-queue.h xmalloc.h ssh.h ssh2.h sshbuf.h packet.h dispatch.h compat.h cipher.h cipher-chachapoly.h chacha.h poly1305.h cipher-aesctr.h rijndael.h sshkey.h kex.h mac.h crypto_api.h -sshconnect2.o: sshconnect.h authfile.h dh.h authfd.h log.h ssherr.h misc.h readconf.h match.h canohost.h msg.h pathnames.h uidswap.h hostfile.h utf8.h ssh-sk.h sk-api.h -sshd.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h ./openbsd-compat/sys-tree.h openbsd-compat/sys-queue.h xmalloc.h ssh.h ssh2.h sshpty.h packet.h dispatch.h log.h ssherr.h sshbuf.h misc.h match.h servconf.h uidswap.h compat.h cipher.h cipher-chachapoly.h chacha.h -sshd.o: poly1305.h cipher-aesctr.h rijndael.h digest.h sshkey.h kex.h mac.h crypto_api.h authfile.h pathnames.h atomicio.h canohost.h hostfile.h auth.h auth-pam.h audit.h loginrec.h authfd.h msg.h channels.h session.h monitor.h monitor_wrap.h ssh-sandbox.h auth-options.h version.h sk-api.h srclimit.h dh.h -ssherr.o: ssherr.h -sshkey-xmss.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h -sshkey.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h crypto_api.h ssh2.h ssherr.h misc.h sshbuf.h cipher.h cipher-chachapoly.h chacha.h poly1305.h cipher-aesctr.h rijndael.h digest.h sshkey.h match.h ssh-sk.h openbsd-compat/openssl-compat.h -sshlogin.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h sshlogin.h ssherr.h loginrec.h log.h sshbuf.h misc.h servconf.h openbsd-compat/sys-queue.h -sshpty.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h sshpty.h log.h ssherr.h misc.h -sshsig.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h authfd.h authfile.h log.h ssherr.h misc.h sshbuf.h sshsig.h sshkey.h match.h digest.h -sshtty.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h sshpty.h -ttymodes.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h packet.h openbsd-compat/sys-queue.h dispatch.h log.h ssherr.h compat.h sshbuf.h ttymodes.h -uidswap.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h log.h ssherr.h uidswap.h xmalloc.h -umac.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h xmalloc.h umac.h misc.h rijndael.h -umac128.o: umac.c includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h xmalloc.h umac.h misc.h rijndael.h -utf8.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h utf8.h -xmalloc.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h xmalloc.h log.h ssherr.h -xmss_commons.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h -xmss_fast.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h -xmss_hash.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h -xmss_hash_address.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h -xmss_wots.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h diff -ruN openssh-9.4p1/dh.c openssh-9.4p1+x509-14.2.1/dh.c --- openssh-9.4p1/dh.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/dh.c 2023-08-20 10:07:01.000000000 +0300 @@ -1,6 +1,7 @@ /* $OpenBSD: dh.c,v 1.74 2021/04/03 06:18:40 djm Exp $ */ /* * Copyright (c) 2000 Niels Provos. All rights reserved. + * Copyright (c) 2021 Roumen Petrov. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -43,20 +44,37 @@ #include "misc.h" #include "ssherr.h" -#include "openbsd-compat/openssl-compat.h" -static const char *moduli_filename; +struct dhgroup { + int size; + BIGNUM *g; + BIGNUM *p; +}; + + +static DH *dh_new_group_fallback(int); +extern DH* _dh_new_group(BIGNUM *, BIGNUM *); +extern DH* _dh_new_group_asc(const char *, const char *); +extern DH* _dh_new_group_num(int); +extern DH* _choose_dh(int, int, int); + +extern void dh_set_moduli_file(const char *); + + +static const char *moduli_filename = NULL; void dh_set_moduli_file(const char *filename) { moduli_filename = filename; } -static const char * get_moduli_filename(void) +static inline const char* +get_moduli_filename(void) { - return moduli_filename ? moduli_filename : _PATH_DH_MODULI; + return moduli_filename != NULL ? moduli_filename : _PATH_DH_MODULI; } + static int parse_prime(int linenum, char *line, struct dhgroup *dhg) { @@ -155,8 +173,9 @@ return 0; } + DH * -choose_dh(int min, int wantbits, int max) +_choose_dh(int min, int wantbits, int max) { FILE *f; char *line = NULL; @@ -227,148 +246,24 @@ return (dh_new_group_fallback(max)); } - return (dh_new_group(dhg.g, dhg.p)); + return _dh_new_group(dhg.p, dhg.g); } /* diffie-hellman-groupN-sha1 */ -int -dh_pub_is_valid(const DH *dh, const BIGNUM *dh_pub) -{ - int i; - int n = BN_num_bits(dh_pub); - int bits_set = 0; - BIGNUM *tmp; - const BIGNUM *dh_p; - - DH_get0_pqg(dh, &dh_p, NULL, NULL); - - if (BN_is_negative(dh_pub)) { - logit("invalid public DH value: negative"); - return 0; - } - if (BN_cmp(dh_pub, BN_value_one()) != 1) { /* pub_exp <= 1 */ - logit("invalid public DH value: <= 1"); - return 0; - } - - if ((tmp = BN_new()) == NULL) { - error_f("BN_new failed"); - return 0; - } - if (!BN_sub(tmp, dh_p, BN_value_one()) || - BN_cmp(dh_pub, tmp) != -1) { /* pub_exp > p-2 */ - BN_clear_free(tmp); - logit("invalid public DH value: >= p-1"); - return 0; - } - BN_clear_free(tmp); - - for (i = 0; i <= n; i++) - if (BN_is_bit_set(dh_pub, i)) - bits_set++; - debug2("bits set: %d/%d", bits_set, BN_num_bits(dh_p)); - - /* - * if g==2 and bits_set==1 then computing log_g(dh_pub) is trivial - */ - if (bits_set < 4) { - logit("invalid public DH value (%d/%d)", - bits_set, BN_num_bits(dh_p)); - return 0; - } - return 1; -} - -int -dh_gen_key(DH *dh, int need) -{ - int pbits; - const BIGNUM *dh_p, *pub_key; - - DH_get0_pqg(dh, &dh_p, NULL, NULL); - - if (need < 0 || dh_p == NULL || - (pbits = BN_num_bits(dh_p)) <= 0 || - need > INT_MAX / 2 || 2 * need > pbits) - return SSH_ERR_INVALID_ARGUMENT; - if (need < 256) - need = 256; - /* - * Pollard Rho, Big step/Little Step attacks are O(sqrt(n)), - * so double requested need here. - */ - if (!DH_set_length(dh, MINIMUM(need * 2, pbits - 1))) - return SSH_ERR_LIBCRYPTO_ERROR; - - if (DH_generate_key(dh) == 0) - return SSH_ERR_LIBCRYPTO_ERROR; - DH_get0_key(dh, &pub_key, NULL); - if (!dh_pub_is_valid(dh, pub_key)) - return SSH_ERR_INVALID_FORMAT; - return 0; -} - -DH * -dh_new_group_asc(const char *gen, const char *modulus) -{ - DH *dh; - BIGNUM *dh_p = NULL, *dh_g = NULL; - - if ((dh = DH_new()) == NULL) - return NULL; - if (BN_hex2bn(&dh_p, modulus) == 0 || - BN_hex2bn(&dh_g, gen) == 0) - goto fail; - if (!DH_set0_pqg(dh, dh_p, NULL, dh_g)) - goto fail; - return dh; - fail: - DH_free(dh); - BN_clear_free(dh_p); - BN_clear_free(dh_g); - return NULL; -} - -/* - * This just returns the group, we still need to generate the exchange - * value. - */ -DH * -dh_new_group(BIGNUM *gen, BIGNUM *modulus) -{ - DH *dh; - - if ((dh = DH_new()) == NULL) - return NULL; - if (!DH_set0_pqg(dh, modulus, NULL, gen)) { - DH_free(dh); - return NULL; - } - - return dh; -} - -/* rfc2409 "Second Oakley Group" (1024 bits) */ -DH * -dh_new_group1(void) -{ - static char *gen = "2", *group1 = +DH* +_dh_new_group_num(int num) { + switch (num) { + /* rfc2409 "Second Oakley Group" (1024 bits) */ + case 1: return _dh_new_group_asc("2", "FFFFFFFF" "FFFFFFFF" "C90FDAA2" "2168C234" "C4C6628B" "80DC1CD1" "29024E08" "8A67CC74" "020BBEA6" "3B139B22" "514A0879" "8E3404DD" "EF9519B3" "CD3A431B" "302B0A6D" "F25F1437" "4FE1356D" "6D51C245" "E485B576" "625E7EC6" "F44C42E9" "A637ED6B" "0BFF5CB6" "F406B7ED" "EE386BFB" "5A899FA5" "AE9F2411" "7C4B1FE6" "49286651" "ECE65381" - "FFFFFFFF" "FFFFFFFF"; - - return (dh_new_group_asc(gen, group1)); -} - -/* rfc3526 group 14 "2048-bit MODP Group" */ -DH * -dh_new_group14(void) -{ - static char *gen = "2", *group14 = + "FFFFFFFF" "FFFFFFFF"); + /* rfc3526 group 14 "2048-bit MODP Group" */ + case 14: return _dh_new_group_asc("2", "FFFFFFFF" "FFFFFFFF" "C90FDAA2" "2168C234" "C4C6628B" "80DC1CD1" "29024E08" "8A67CC74" "020BBEA6" "3B139B22" "514A0879" "8E3404DD" "EF9519B3" "CD3A431B" "302B0A6D" "F25F1437" "4FE1356D" "6D51C245" @@ -379,16 +274,9 @@ "670C354E" "4ABC9804" "F1746C08" "CA18217C" "32905E46" "2E36CE3B" "E39E772C" "180E8603" "9B2783A2" "EC07A28F" "B5C55DF0" "6F4C52C9" "DE2BCBF6" "95581718" "3995497C" "EA956AE5" "15D22618" "98FA0510" - "15728E5A" "8AACAA68" "FFFFFFFF" "FFFFFFFF"; - - return (dh_new_group_asc(gen, group14)); -} - -/* rfc3526 group 16 "4096-bit MODP Group" */ -DH * -dh_new_group16(void) -{ - static char *gen = "2", *group16 = + "15728E5A" "8AACAA68" "FFFFFFFF" "FFFFFFFF"); + /* rfc3526 group 16 "4096-bit MODP Group" */ + case 16: return _dh_new_group_asc("2", "FFFFFFFF" "FFFFFFFF" "C90FDAA2" "2168C234" "C4C6628B" "80DC1CD1" "29024E08" "8A67CC74" "020BBEA6" "3B139B22" "514A0879" "8E3404DD" "EF9519B3" "CD3A431B" "302B0A6D" "F25F1437" "4FE1356D" "6D51C245" @@ -410,16 +298,9 @@ "287C5947" "4E6BC05D" "99B2964F" "A090C3A2" "233BA186" "515BE7ED" "1F612970" "CEE2D7AF" "B81BDD76" "2170481C" "D0069127" "D5B05AA9" "93B4EA98" "8D8FDDC1" "86FFB7DC" "90A6C08F" "4DF435C9" "34063199" - "FFFFFFFF" "FFFFFFFF"; - - return (dh_new_group_asc(gen, group16)); -} - -/* rfc3526 group 18 "8192-bit MODP Group" */ -DH * -dh_new_group18(void) -{ - static char *gen = "2", *group18 = + "FFFFFFFF" "FFFFFFFF"); + /* rfc3526 group 18 "8192-bit MODP Group" */ + case 18: return _dh_new_group_asc("2", "FFFFFFFF" "FFFFFFFF" "C90FDAA2" "2168C234" "C4C6628B" "80DC1CD1" "29024E08" "8A67CC74" "020BBEA6" "3B139B22" "514A0879" "8E3404DD" "EF9519B3" "CD3A431B" "302B0A6D" "F25F1437" "4FE1356D" "6D51C245" @@ -462,9 +343,9 @@ "B1D510BD" "7EE74D73" "FAF36BC3" "1ECFA268" "359046F4" "EB879F92" "4009438B" "481C6CD7" "889A002E" "D5EE382B" "C9190DA6" "FC026E47" "9558E447" "5677E9AA" "9E3050E2" "765694DF" "C81F56E8" "80B96E71" - "60C980DD" "98EDD3DF" "FFFFFFFF" "FFFFFFFF"; - - return (dh_new_group_asc(gen, group18)); + "60C980DD" "98EDD3DF" "FFFFFFFF" "FFFFFFFF"); + } + return NULL; } /* Select fallback group used by DH-GEX if moduli file cannot be read. */ @@ -474,32 +355,12 @@ debug3_f("requested max size %d", max); if (max < 3072) { debug3("using 2k bit group 14"); - return dh_new_group14(); + return _dh_new_group_num(14); } else if (max < 6144) { debug3("using 4k bit group 16"); - return dh_new_group16(); + return _dh_new_group_num(16); } debug3("using 8k bit group 18"); - return dh_new_group18(); + return _dh_new_group_num(18); } - -/* - * Estimates the group order for a Diffie-Hellman group that has an - * attack complexity approximately the same as O(2**bits). - * Values from NIST Special Publication 800-57: Recommendation for Key - * Management Part 1 (rev 3) limited by the recommended maximum value - * from RFC4419 section 3. - */ -u_int -dh_estimate(int bits) -{ - if (bits <= 112) - return 2048; - if (bits <= 128) - return 3072; - if (bits <= 192) - return 7680; - return 8192; -} - #endif /* WITH_OPENSSL */ diff -ruN openssh-9.4p1/dh.h openssh-9.4p1+x509-14.2.1/dh.h --- openssh-9.4p1/dh.h 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/dh.h 2023-08-20 10:07:00.000000000 +0300 @@ -2,6 +2,7 @@ /* * Copyright (c) 2000 Niels Provos. All rights reserved. + * Copyright (c) 2021 Roumen Petrov. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -26,29 +27,6 @@ #ifndef DH_H #define DH_H -#ifdef WITH_OPENSSL - -struct dhgroup { - int size; - BIGNUM *g; - BIGNUM *p; -}; - -DH *choose_dh(int, int, int); -DH *dh_new_group_asc(const char *, const char *); -DH *dh_new_group(BIGNUM *, BIGNUM *); -DH *dh_new_group1(void); -DH *dh_new_group14(void); -DH *dh_new_group16(void); -DH *dh_new_group18(void); -DH *dh_new_group_fallback(int); - -int dh_gen_key(DH *, int); -int dh_pub_is_valid(const DH *, const BIGNUM *); - -u_int dh_estimate(int); -void dh_set_moduli_file(const char *); - /* * Max value from RFC4419. * Min value from RFC8270. @@ -79,6 +57,4 @@ #define MODULI_TESTS_JACOBI (0x08) #define MODULI_TESTS_ELLIPTIC (0x10) -#endif /* WITH_OPENSSL */ - #endif /* DH_H */ diff -ruN openssh-9.4p1/digest.h openssh-9.4p1+x509-14.2.1/digest.h --- openssh-9.4p1/digest.h 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/digest.h 2023-08-20 10:07:00.000000000 +0300 @@ -1,6 +1,7 @@ /* $OpenBSD: digest.h,v 1.8 2017/05/08 22:57:38 djm Exp $ */ /* * Copyright (c) 2013 Damien Miller + * Copyright (c) 2018 Roumen Petrov. All rights reserved. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -41,6 +42,9 @@ /* Returns the algorithm's digest length in bytes or 0 for invalid algorithm */ size_t ssh_digest_bytes(int alg); +/* Returns the digest algorithm with maximum digest length */ +int ssh_digest_maxbytes(void); + /* Returns the block size of the digest, e.g. for implementing HMAC */ size_t ssh_digest_blocksize(struct ssh_digest_ctx *ctx); diff -ruN openssh-9.4p1/digest-libc.c openssh-9.4p1+x509-14.2.1/digest-libc.c --- openssh-9.4p1/digest-libc.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/digest-libc.c 2023-08-20 10:07:01.000000000 +0300 @@ -27,13 +27,14 @@ #if 0 #include -#include #endif #ifdef HAVE_SHA1_H #include #endif #ifdef HAVE_SHA2_H -#include +# include +#else +# include "openbsd-compat/sha2.h" #endif #if !defined(SHA256_BLOCK_LENGTH) && defined(SHA256_HMAC_BLOCK_SIZE) @@ -127,6 +128,9 @@ static const struct ssh_digest * ssh_digest_by_alg(int alg) { +#ifdef OPENSSL_FIPS +# include "use openssl based digest for FIPS build" +#endif if (alg < 0 || alg >= SSH_DIGEST_MAX) return NULL; if (digests[alg].id != alg) /* sanity */ @@ -162,6 +166,19 @@ return digest == NULL ? 0 : digest->digest_len; } +int +ssh_digest_maxbytes(void) { + int k; + + /*NOTE digest table is sorted in ascending order by digest length*/ + for (k = SSH_DIGEST_MAX - 1; k >= 0; k--) { + const struct ssh_digest *d = ssh_digest_by_alg(k); + if (d == NULL) continue; + return digests[k].id; + } + return -1; +} + size_t ssh_digest_blocksize(struct ssh_digest_ctx *ctx) { @@ -238,8 +255,7 @@ if (ctx != NULL) { digest = ssh_digest_by_alg(ctx->alg); if (digest) { - explicit_bzero(ctx->mdctx, digest->ctx_len); - free(ctx->mdctx); + freezero(ctx->mdctx, digest->ctx_len); freezero(ctx, sizeof(*ctx)); } } diff -ruN openssh-9.4p1/digest-openssl.c openssh-9.4p1+x509-14.2.1/digest-openssl.c --- openssh-9.4p1/digest-openssl.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/digest-openssl.c 2023-08-20 10:07:01.000000000 +0300 @@ -1,6 +1,7 @@ /* $OpenBSD: digest-openssl.c,v 1.9 2020/10/29 02:52:43 djm Exp $ */ /* * Copyright (c) 2013 Damien Miller + * Copyright (c) 2018 Roumen Petrov. All rights reserved. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -26,8 +27,7 @@ #include -#include "openbsd-compat/openssl-compat.h" - +#include "evp-compat.h" #include "sshbuf.h" #include "digest.h" #include "ssherr.h" @@ -73,6 +73,13 @@ return NULL; if (digests[alg].mdfunc == NULL) return NULL; +#ifdef OPENSSL_FIPS + if (FIPS_mode()) { + const EVP_MD *md = digests[alg].mdfunc(); + if ((EVP_MD_flags(md) & EVP_MD_FLAG_FIPS) == 0) + return NULL; + } +#endif return &(digests[alg]); } @@ -104,6 +111,19 @@ return digest == NULL ? 0 : digest->digest_len; } +int +ssh_digest_maxbytes(void) { + int k; + + /*NOTE digest table is sorted in ascending order by digest length*/ + for (k = SSH_DIGEST_MAX - 1; k >= 0; k--) { + const struct ssh_digest *d = ssh_digest_by_alg(k); + if (d == NULL) continue; + return digests[k].id; + } + return -1; +} + size_t ssh_digest_blocksize(struct ssh_digest_ctx *ctx) { @@ -135,7 +155,6 @@ { if (from->alg != to->alg) return SSH_ERR_INVALID_ARGUMENT; - /* we have bcopy-style order while openssl has memcpy-style */ if (!EVP_MD_CTX_copy_ex(to->mdctx, from->mdctx)) return SSH_ERR_LIBCRYPTO_ERROR; return 0; diff -ruN openssh-9.4p1/dispatch.c openssh-9.4p1+x509-14.2.1/dispatch.c --- openssh-9.4p1/dispatch.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/dispatch.c 2023-08-20 10:07:01.000000000 +0300 @@ -53,6 +53,7 @@ int dispatch_protocol_ignore(int type, u_int32_t seq, struct ssh *ssh) { + UNUSED(ssh); logit("dispatch_protocol_ignore: type %d seq %u", type, seq); return 0; } diff -ruN openssh-9.4p1/dns.c openssh-9.4p1+x509-14.2.1/dns.c --- openssh-9.4p1/dns.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/dns.c 2023-08-20 10:07:01.000000000 +0300 @@ -1,8 +1,8 @@ -/* $OpenBSD: dns.c,v 1.44 2023/03/10 04:06:21 dtucker Exp $ */ - +/* $OpenBSD: dns.c,v 1.43 2023/02/10 04:56:30 djm Exp $ */ /* * Copyright (c) 2003 Wesley Griffin. All rights reserved. * Copyright (c) 2003 Jakob Schlyter. All rights reserved. + * Copyright (c) 2005-2021 Roumen Petrov. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -35,14 +35,28 @@ #include #include #include +#include -#include "xmalloc.h" -#include "sshkey.h" -#include "ssherr.h" +#include "ssh-x509.h" #include "dns.h" +#include "xmalloc.h" #include "log.h" #include "digest.h" + +struct ssh_dns_cert_param_s { + int cert_type; + int key_tag; + int algo; + u_char *cert_data; + size_t cert_len; + u_char *b64_data; + size_t b64_len; +}; + +typedef struct ssh_dns_cert_param_s ssh_dns_cert_param; + + static const char * const errset_text[] = { "success", /* 0 ERRSET_SUCCESS */ "out of memory", /* 1 ERRSET_NOMEMORY */ @@ -91,15 +105,19 @@ case KEY_DSA: *algorithm = SSHFP_KEY_DSA; break; +#ifdef OPENSSL_HAS_ECC case KEY_ECDSA: *algorithm = SSHFP_KEY_ECDSA; break; +#endif case KEY_ED25519: *algorithm = SSHFP_KEY_ED25519; break; +#ifdef WITH_XMSS case KEY_XMSS: *algorithm = SSHFP_KEY_XMSS; break; +#endif default: *algorithm = SSHFP_KEY_RESERVED; /* 0 */ } @@ -108,9 +126,11 @@ case SSHFP_HASH_SHA1: fp_alg = SSH_DIGEST_SHA1; break; +#ifdef HAVE_EVP_SHA256 case SSHFP_HASH_SHA256: fp_alg = SSH_DIGEST_SHA256; break; +#endif /*def HAVE_EVP_SHA256*/ default: *digest_type = SSHFP_HASH_RESERVED; /* 0 */ } @@ -128,6 +148,168 @@ return success; } +static void +cert_param_clean(ssh_dns_cert_param *param) { + if (param == NULL) return; + + if (param->cert_data) { + param->cert_len = 0; + free(param->cert_data); + param->cert_data = NULL; + } + if (param->b64_data) { + param->b64_len = 0; + free(param->b64_data); + param->b64_data = NULL; + } +} + +static const char* +bind_cert_type(const ssh_dns_cert_param *param) { + switch(param->cert_type) { + case DNS_CERT_TYPE_PKIX: return "PKIX"; +#if 0 + case DNS_CERT_TYPE_SPKI: return "SPKI"; + case DNS_CERT_TYPE_PGP : return "PGP"; + case DNS_CERT_TYPE_URI : return "URI"; + case DNS_CERT_TYPE_OID : return "OID"; +#endif + default: + break; + } + return ""; +} + +static const char* +bind_key_algo(const ssh_dns_cert_param *param) { + switch(param->algo) { +#if 0 + case DNS_KEY_ALGO_UNKNOWN: /*specific case for CERT RR*/ + return "????"; +#endif + case DNS_KEY_ALGO_RSASHA1 : return "RSASHA1"; + case DNS_KEY_ALGO_RSAMD5 : return "RSAMD5"; + case DNS_KEY_ALGO_DSA : return "DSA"; + } + return ""; +} + +static u_int16_t +calc_dns_key_tag(X509 *x509) { + /* [RFC 2535] Appendix C: Key Tag Calculation */ + + UNUSED(x509); + /* TODO: to be implemented or not ? + * I'm happy without this. + */ + return 1; +} + +static inline const X509_ALGOR* +ssh_X509_get0_tbs_sigalg(X509 *x509) { + if (x509 == NULL) return NULL; + +#ifdef HAVE_X509_GET0_TBS_SIGALG + return X509_get0_tbs_sigalg(x509); +#else +{ + X509_CINF *ci = x509->cert_info; + return ci != NULL ? ci->signature: NULL; +} +#endif +} + +static u_int8_t +get_dns_sign_algo(X509 *x509) { + int rsa_algo = DNS_KEY_ALGO_UNKNOWN; + int algo_nid; + + const X509_ALGOR *sig; + ASN1_OBJECT *alg; + + sig = ssh_X509_get0_tbs_sigalg(x509); + if (sig == NULL) goto done; + + alg = sig->algorithm; + if (alg == NULL) goto done; + + algo_nid = OBJ_obj2nid(alg); + debug3_f("nid=%d(%s)\n", algo_nid, OBJ_nid2ln(algo_nid)); + + switch(algo_nid) { + case NID_md5WithRSAEncryption: + rsa_algo = DNS_KEY_ALGO_RSAMD5; + break; + case NID_sha1WithRSAEncryption: + rsa_algo = DNS_KEY_ALGO_RSASHA1; + break; + case NID_dsaWithSHA1: + rsa_algo = DNS_KEY_ALGO_DSA; + break; + default: + rsa_algo = DNS_KEY_ALGO_UNKNOWN; + } + +done: + return rsa_algo; +} + +/* + * Initialize DNS CERT parameters from key certificate. + */ +static int/*bool*/ +cert_param_from_key(ssh_dns_cert_param *param, const struct sshkey *key) +{ + int ret = 0; + X509 *x509; + BIO *bio = NULL; + int k = 0; + + if (param == NULL) goto done; + if (key == NULL) goto done; + + x509 = SSH_X509_get_cert(key->x509_data); + if (x509 == NULL) goto done; + + bio = BIO_new(BIO_s_mem()); + if (bio == NULL) goto done; + + i2d_X509_bio(bio, x509); + (void)BIO_flush(bio); + + cert_param_clean(param); + + k = BIO_pending(bio); + param->cert_data = xmalloc(k + 1); /*fatal on error*/ + param->cert_len = BIO_read(bio, param->cert_data, k); + +{ + struct sshbuf *b = sshbuf_from(param->cert_data, param->cert_len); + if (b == NULL) { + ret = 0; + goto done; + } + param->b64_data = sshbuf_dtob64_string(b, 0); + if (param->b64_data == NULL) { + sshbuf_free(b); + ret = 0; + goto done; + } + param->b64_len = strlen(param->b64_data); + sshbuf_free(b); +} + + param->algo = get_dns_sign_algo(x509); + param->key_tag = calc_dns_key_tag(x509); + param->cert_type = DNS_CERT_TYPE_PKIX; + + ret = 1; + +done: + BIO_free_all(bio); + return ret; +} + /* * Read SSHFP parameters from rdata buffer. */ @@ -189,11 +371,134 @@ } /* + * Read CERT parameters from rdata buffer. + */ +static int/*bool*/ +dns_read_cert_rdata(ssh_dns_cert_param *param, u_char *rdata, int rdata_len) +{ + size_t len ; + + cert_param_clean(param); + + if (rdata_len < 5) return 0; + + param->cert_type = (rdata[0] << 8) + rdata[1]; + param->key_tag = (rdata[2] << 8) + rdata[3]; + param->algo = rdata[4]; + + len = rdata_len - 5; + param->cert_len = len; + if (len > 0) { + param->cert_data = (u_char *) xmalloc(len); + memcpy(param->cert_data, rdata + 5, len); + } + return 1; +} + +/* + * Verify the given hostname, address and host key using DNS. + * Returns 0 if lookup succeeds, -1 otherwise + */ +static int +verify_hostcert_dns(const char *hostname, const struct sshkey *hostkey, int *flags) +{ + u_int counter; + int result; + struct rrsetinfo *certs = NULL; + + ssh_dns_cert_param hostkey_param; + ssh_dns_cert_param dnskey_param; + + debug3_f("..."); + + memset(&hostkey_param, 0, sizeof(hostkey_param)); + memset(&dnskey_param , 0, sizeof(dnskey_param )); + + result = getrrsetbyname(hostname, DNS_RDATACLASS_IN, + DNS_RDATATYPE_CERT, 0, &certs); + if (result) { + verbose("DNS lookup error: %s", dns_result_totext(result)); + return -1; + } + + if (certs->rri_flags & RRSET_VALIDATED) { + *flags |= DNS_VERIFY_SECURE; + debug("found %d secure certificates in DNS", + certs->rri_nrdatas); + } else { + debug("found %d insecure certificates in DNS", + certs->rri_nrdatas); + } + + /* Initialize host key CERT parameters */ + if (!cert_param_from_key(&hostkey_param, hostkey)) { + error("Error calculating host key certificate."); + cert_param_clean(&hostkey_param); + freerrset(certs); + return -1; + } + + if (certs->rri_nrdatas) + *flags |= DNS_VERIFY_FOUND; + + for (counter = 0 ; counter < certs->rri_nrdatas ; counter++) { + struct sshkey* dns_cert = NULL; + /* + * Extract the key from the answer. Ignore any badly + * formatted certificates. + */ + if (!dns_read_cert_rdata(&dnskey_param, + certs->rri_rdatas[counter].rdi_data, + certs->rri_rdatas[counter].rdi_length + )) { + verbose("Error parsing certificate from DNS."); + goto next; + } + + if (hostkey_param.cert_type != dnskey_param.cert_type) continue; + + /* We will skip useless "key tag" */ + + /* We will ignore "algorithm" since number of + * algorithms defined in [RFC 2535] is limited. + */ + { int r = X509key_from_blob(dnskey_param.cert_data, dnskey_param.cert_len, &dns_cert); + if (r != 0) { + verbose("Invalid certificate from DNS."); + goto next; + } + } + if (ssh_x509_cmp_cert(hostkey, dns_cert) == 0) { + *flags |= DNS_VERIFY_MATCH; + } + sshkey_free(dns_cert); + dns_cert = NULL; + +next: + cert_param_clean(&dnskey_param); + } + + cert_param_clean(&hostkey_param); + freerrset(certs); + + if (*flags & DNS_VERIFY_FOUND) + if (*flags & DNS_VERIFY_MATCH) + debug("matching host key certificate found in DNS"); + else + debug("mismatching host key certificate found in DNS"); + else + debug("no host key certificate found in DNS"); + + return 0; +} + +/* * Verify the given hostname, address and host key using DNS. * Returns 0 if lookup succeeds, -1 otherwise */ int verify_host_key_dns(const char *hostname, struct sockaddr *address, + const struct ssh_conn_info *cinfo, struct sshkey *hostkey, int *flags) { u_int counter; @@ -209,9 +514,11 @@ u_char *dnskey_digest; size_t dnskey_digest_len; + UNUSED(address); + UNUSED(cinfo); *flags = 0; - debug3("verify_host_key_dns"); + debug3_f("..."); if (hostkey == NULL) fatal("No key to look up!"); @@ -220,6 +527,13 @@ return -1; } + if (sshkey_is_x509(hostkey)) { + result = verify_hostcert_dns(hostname, hostkey, flags); + if (*flags & DNS_VERIFY_FOUND) + return result; + /*try to found SSHFP RR*/ + } + result = getrrsetbyname(hostname, DNS_RDATACLASS_IN, DNS_RDATATYPE_SSHFP, 0, &fingerprints); if (result) { @@ -268,11 +582,11 @@ hostkey_digest_len == dnskey_digest_len) { if (timingsafe_bcmp(hostkey_digest, dnskey_digest, hostkey_digest_len) == 0) { - debug_f("matched SSHFP type %d fptype %d", + debug3_f("matched SSHFP type %d fptype %d", dnskey_algorithm, dnskey_digest_type); *flags |= DNS_VERIFY_MATCH; } else { - debug_f("failed SSHFP type %d fptype %d", + debug3_f("failed SSHFP type %d fptype %d", dnskey_algorithm, dnskey_digest_type); *flags |= DNS_VERIFY_FAILED; } @@ -310,8 +624,55 @@ u_int8_t dtype; u_char *rdata_digest; size_t i, rdata_digest_len; + ssh_dns_cert_param cert_param; int success = 0; + memset(&cert_param, 0, sizeof(cert_param)); + + if (cert_param_from_key(&cert_param, key)) { + u_char *p; + int k; + + if (generic || (cert_param.algo == DNS_KEY_ALGO_UNKNOWN)) { + fprintf(f, "%s\tIN\tTYPE%d \\# %d %04x %04x %02x (\n\t" + , hostname + , DNS_RDATATYPE_CERT + , (int)(5 + cert_param.cert_len) + , cert_param.cert_type + , cert_param.key_tag + , cert_param.algo + ); + p = cert_param.cert_data; + i = cert_param.cert_len; + k = 32; + for (; i > 0; i--, p++) { + fprintf(f, "%02x", (int) *p); + if (--k <= 0) { + fprintf(f, "\n\t"); + k = 32; + } + } + } else { + fprintf(f, "%s\tIN\tCERT\t%s %d %s (\n\t" + , hostname + , bind_cert_type(&cert_param) + , cert_param.key_tag + , bind_key_algo(&cert_param) + ); + p = cert_param.b64_data; + i = cert_param.b64_len; + k = 64; + for (; i > 0; i--, p++) { + fprintf(f, "%c", *p); + if (--k <= 0) { + fprintf(f, "\n\t"); + k = 64; + } + } + } + fprintf(f, "\n\t)\n"); + success = 1; + } else for (dtype = SSHFP_HASH_SHA1; dtype < SSHFP_HASH_MAX; dtype++) { if (alg != -1 && dtype != alg) continue; @@ -340,5 +701,6 @@ error_f("unsupported algorithm and/or digest_type"); } + cert_param_clean(&cert_param); return success; } diff -ruN openssh-9.4p1/dns.h openssh-9.4p1+x509-14.2.1/dns.h --- openssh-9.4p1/dns.h 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/dns.h 2023-08-20 10:07:00.000000000 +0300 @@ -1,8 +1,8 @@ /* $OpenBSD: dns.h,v 1.20 2023/02/10 04:56:30 djm Exp $ */ - /* * Copyright (c) 2003 Wesley Griffin. All rights reserved. * Copyright (c) 2003 Jakob Schlyter. All rights reserved. + * Copyright (c) 2005-2023 Roumen Petrov. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -28,6 +28,10 @@ #ifndef DNS_H #define DNS_H +#include "includes.h" + +struct ssh_conn_info; + enum sshfp_types { SSHFP_KEY_RESERVED = 0, SSHFP_KEY_RSA = 1, @@ -37,14 +41,47 @@ SSHFP_KEY_XMSS = 5 }; +enum dns_cert_types { + DNS_CERT_TYPE_RESERVER = 0, + DNS_CERT_TYPE_PKIX = 1, /* X.509 as per PKIX */ + DNS_CERT_TYPE_SPKI = 2, /* SPKI cert */ + DNS_CERT_TYPE_PGP = 3, /* PGP cert */ +/* 4-252 available for IANA assignment */ + DNS_CERT_TYPE_URI = 253, /* URI private */ + DNS_CERT_TYPE_OID = 254, /* OID private */ +/* 255-65534 available for IANA assignment */ + DNS_CERT_TYPE_RESERVER2 = 65535 +}; + enum sshfp_hashes { SSHFP_HASH_RESERVED = 0, SSHFP_HASH_SHA1 = 1, +#ifdef HAVE_EVP_SHA256 SSHFP_HASH_SHA256 = 2, SSHFP_HASH_MAX = 3 +#else + SSHFP_HASH_MAX = 2 +#endif +}; + +enum dns_key_algo { + DNS_KEY_ALGO_RESERVED = 0, /* reserved, see [RFC 2535] Section 11 */ + DNS_KEY_ALGO_UNKNOWN = 0, /* when algorithm is unknown to a secure DNS [RFC 2538] */ + DNS_KEY_ALGO_RSAMD5 = 1, /* RSA/MD5 [RFC 2537] */ + DNS_KEY_ALGO_DH = 2, /* Diffie-Hellman [RFC 2539] */ + DNS_KEY_ALGO_DSA = 3, /* DSA [RFC 2536] */ + DNS_KEY_ALGO_ECC = 4, /* reserved for elliptic curve crypto */ +/* 5-251 available, see [RFC 2535] Section 11 */ + DNS_KEY_ALGO_RSASHA1 = 5, /* RSA/SHA1 [RFC 3110] */ +/* 6-251 available, see [RFC 4034] Section A.1. */ + DNS_KEY_ALGO_INDIRECT = 252, /* reserved for indirect keys */ + DNS_KEY_ALGO_PRIVATEDNS = 253, /* private - domain name (see [RFC 2535]) */ + DNS_KEY_ALGO_PRIVATEOID = 254, /* private - OID (see [RFC 2535]) */ + DNS_KEY_ALGO_RESERVED2 = 255 /* reserved, see [RFC 2535] Section 11 */ }; #define DNS_RDATACLASS_IN 1 +#define DNS_RDATATYPE_CERT 37 #define DNS_RDATATYPE_SSHFP 44 #define DNS_VERIFY_FOUND 0x00000001 @@ -53,7 +90,7 @@ #define DNS_VERIFY_FAILED 0x00000008 int verify_host_key_dns(const char *, struct sockaddr *, - struct sshkey *, int *); + const struct ssh_conn_info *, struct sshkey *, int *); int export_dns_rr(const char *, struct sshkey *, FILE *, int, int); #endif /* DNS_H */ diff -ruN openssh-9.4p1/ed25519.sh openssh-9.4p1+x509-14.2.1/ed25519.sh --- openssh-9.4p1/ed25519.sh 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/ed25519.sh 2023-08-20 10:07:00.000000000 +0300 @@ -29,6 +29,8 @@ sed -e '/Alphabetical order:/d' -e 's/^/ * - /' < $AUTHOR echo ' */' echo +echo '#include "includes.h"' +echo echo '#include ' echo echo '#include "crypto_api.h"' diff -ruN openssh-9.4p1/.editorconfig openssh-9.4p1+x509-14.2.1/.editorconfig --- openssh-9.4p1/.editorconfig 1970-01-01 02:00:00.000000000 +0200 +++ openssh-9.4p1+x509-14.2.1/.editorconfig 2023-08-20 10:07:00.000000000 +0300 @@ -0,0 +1,12 @@ +[*] +tab_width = 8 +indent_style = tab +indent_size = tab +trim_trailing_whitespace = true +insert_final_newline = true +charset = utf-8 + +[*sh,*.inc] +indent_style = space +indent_size = 2 +end_of_line = lf diff -ruN openssh-9.4p1/e_ldap.c openssh-9.4p1+x509-14.2.1/e_ldap.c --- openssh-9.4p1/e_ldap.c 1970-01-01 02:00:00.000000000 +0200 +++ openssh-9.4p1+x509-14.2.1/e_ldap.c 2023-08-20 10:07:01.000000000 +0300 @@ -0,0 +1,420 @@ +/* + * Copyright (c) 2019-2023 Roumen Petrov. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifndef USE_OPENSSL_PROVIDER +/* TODO: implement OpenSSL 4.0 API, as OpenSSL 3.* is quite nonfunctional */ +# define OPENSSL_SUPPRESS_DEPRECATED +#endif + +#include "ssh_ldap.h" + +#ifdef USE_LDAP_STORE + +#include +#include +#include + +/* engine store */ + +static const char ldap_store_scheme[] = "ldap"; + + +struct ossl_store_loader_ctx_st { + ldaphost *lh; + int result; + LDAPMessage *res; + ldapsearch_result *it; + + int expected; + X509_NAME *name; +}; + + +static OSSL_STORE_LOADER_CTX* +OSSL_STORE_LOADER_CTX_new(void) { + OSSL_STORE_LOADER_CTX *ctx; + + ctx = OPENSSL_malloc(sizeof(OSSL_STORE_LOADER_CTX)); + if (ctx == NULL) return NULL; + + ctx->lh = NULL; + ctx->result = LDAP_SUCCESS; + ctx->res = NULL; + ctx->it = NULL; + + ctx->expected = -1; + ctx->name = NULL; + + return ctx; +} + + +static void +OSSL_STORE_LOADER_CTX_free(OSSL_STORE_LOADER_CTX* ctx) { +TRACE_BY_LDAP(__func__, "ctx=%p", (void*)ctx); + if (ctx == NULL) return; + + OPENSSL_free(ctx->it); + ldap_msgfree(ctx->res); + ldaphost_free(ctx->lh); + + X509_NAME_free(ctx->name); + + OPENSSL_free(ctx); +} + + +static OSSL_STORE_LOADER_CTX* +ldap_store_open( + const OSSL_STORE_LOADER *loader, const char *uri, + const UI_METHOD *ui_method, void *ui_data +) { + OSSL_STORE_LOADER_CTX *ctx; + ldaphost *lh; + +TRACE_BY_LDAP(__func__, "uri='%s'", uri); + UNUSED(loader); + UNUSED(ui_method); + UNUSED(ui_data); + + ctx = OSSL_STORE_LOADER_CTX_new(); + if (ctx == NULL) return NULL; + + lh = ldaphost_new(uri); + if (lh == NULL) { + OSSL_STORE_LOADER_CTX_free(ctx); + return NULL; + } + ctx->lh = lh; + + ctx->result = ssh_ldap_bind_s(lh->ld); + if (ctx->result != LDAP_OPT_SUCCESS) { + OSSL_STORE_LOADER_CTX_free(ctx); + return NULL; + } + + return ctx; +} + + +static int +ldap_store_search_iterator(OSSL_STORE_LOADER_CTX *ctx, char *filter, char **attrs) { + ldaphost *lh = ctx->lh; + + ctx->result = ssh_ldap_search_s(lh->ld, lh->ldapurl->lud_dn, + LDAP_SCOPE_SUBTREE, filter, attrs, 0, &ctx->res); + + if (ctx->result != LDAP_SUCCESS) { +TRACE_BY_LDAP(__func__, "ldap_search_s() url=\"%s://%s:%d\" ldaperror=0x%x(%.256s)" +, lh->ldapurl->lud_scheme, lh->ldapurl->lud_host, lh->ldapurl->lud_port +, ctx->result, ldap_err2string(ctx->result)); + return 0; + } + + ctx->it = ldapsearch_iterator(lh->ld, ctx->res); + return ctx->it != NULL; +} + + +static int +ldap_store_expect(OSSL_STORE_LOADER_CTX *ctx, int expected) { + + switch (expected) { + case OSSL_STORE_INFO_CERT: + case OSSL_STORE_INFO_CRL: break; + default: return 0; + } + + ctx->expected = expected; + return 1; +} + + +static int +ldap_store_find( + OSSL_STORE_LOADER_CTX *ctx, + STORE_FIND_CRITERION_CONST OSSL_STORE_SEARCH *criterion +) { + int type; + + type = OSSL_STORE_SEARCH_get_type(criterion); +TRACE_BY_LDAP(__func__, "type=%d, ctx=%p", type, (void*)ctx); + if (type != OSSL_STORE_SEARCH_BY_NAME) return 0; + if (ctx == NULL) return 1; + + ctx->name = X509_NAME_dup(OSSL_STORE_SEARCH_get0_name(criterion)); + return (ctx->name != NULL); +} + + +static OSSL_STORE_INFO* +ldap_store_load( + OSSL_STORE_LOADER_CTX *ctx, + const UI_METHOD *ui_method, void *ui_data +) { + static char *ATTR_CACERT = "cACertificate"; + static char *ATTR_CACRL = "certificateRevocationList"; + ldapsearch_result *it; + BIO *mbio = NULL; + OSSL_STORE_INFO *ret = NULL; + +TRACE_BY_LDAP(__func__, "ctx=%p, ui_method=%p, ui_data=%p" +, (void*)ctx, (void*)ui_method, ui_data); + + if (ctx == NULL) return NULL; + it = ctx->it; + if (it == NULL) { + char *attrs[2] = { NULL, NULL }; + char *filter = NULL; + + if (ctx->name == NULL) return NULL; + + switch(ctx->expected) { + case OSSL_STORE_INFO_CERT: attrs[0] = ATTR_CACERT; break; + case OSSL_STORE_INFO_CRL: attrs[0] = ATTR_CACRL; break; + } + + filter = X509_NAME_ldapfilter(ctx->name, attrs[0]); +TRACE_BY_LDAP(__func__, "filter: '%s'", filter); + if (filter == NULL) return NULL; + + ldap_store_search_iterator(ctx, filter, attrs); + OPENSSL_free(filter); + it = ctx->it; + } + if (it == NULL) return NULL; + + while (ldapsearch_advance(it)) { + struct berval *q = *it->p; + + mbio = BIO_new_mem_buf(q->bv_val, q->bv_len); + if (mbio == NULL) return NULL; + + if (strncmp(it->attr, ATTR_CACERT, strlen(ATTR_CACERT)) == 0) { + X509 *x509; + + if ((ctx->expected >= 0) && (ctx->expected != OSSL_STORE_INFO_CERT)) + continue; + + x509 = d2i_X509_bio(mbio, NULL); + if (x509 == NULL) goto exit; + + ret = OSSL_STORE_INFO_new_CERT(x509); + break; + } + + if (strncmp(it->attr, ATTR_CACRL, strlen(ATTR_CACRL)) == 0) { + X509_CRL *crl; + + if ((ctx->expected >= 0) && (ctx->expected != OSSL_STORE_INFO_CRL)) + continue; + + crl = d2i_X509_CRL_bio(mbio, NULL); + if (crl == NULL) goto exit; + + ret = OSSL_STORE_INFO_new_CRL(crl); + break; + } + } + +exit: + BIO_free_all(mbio); +TRACE_BY_LDAP(__func__, "return %p", (void*)ret); + return ret; +} + + +static int +ldap_store_eof(OSSL_STORE_LOADER_CTX *ctx) { +TRACE_BY_LDAP(__func__, "ctx=%p, res=%p, it=%p" +, (void*)ctx, (void*)(ctx ? ctx->res: NULL), (void*)(ctx ? ctx->it: NULL)); + + if (ctx->res == NULL) return 0; +{ ldapsearch_result *it = ctx->it; + if (it != NULL) + return it->entry == NULL; +} + +TRACE_BY_LDAP(__func__, "return: %ld != %ld" +, (long)ctx->result, (long)LDAP_SUCCESS); + return ctx->result != LDAP_SUCCESS; +} + + +static int +ldap_store_error(OSSL_STORE_LOADER_CTX *ctx) { +TRACE_BY_LDAP(__func__, "ctx=%p", (void*)ctx); + +TRACE_BY_LDAP(__func__, "return: %ld != %ld" +, (long)ctx->result, (long)LDAP_SUCCESS); + return ctx->result != LDAP_SUCCESS; +} + + +static int +ldap_store_close(OSSL_STORE_LOADER_CTX *ctx) { +TRACE_BY_LDAP(__func__, "ctx=%p", (void*)ctx); + + OSSL_STORE_LOADER_CTX_free(ctx); + return 1; +} + + +static int/*bool*/ +bind_ldap_store(ENGINE *e) { + OSSL_STORE_LOADER *loader = OSSL_STORE_LOADER_new(e, ldap_store_scheme); + +TRACE_BY_LDAP(__func__, "e=%p", (void*)e); + if (loader == NULL) return 0; + + if (!OSSL_STORE_LOADER_set_open(loader, ldap_store_open) + || !OSSL_STORE_LOADER_set_expect(loader, ldap_store_expect) + || !OSSL_STORE_LOADER_set_find(loader, ldap_store_find) + || !OSSL_STORE_LOADER_set_load(loader, ldap_store_load) + || !OSSL_STORE_LOADER_set_eof(loader, ldap_store_eof) + || !OSSL_STORE_LOADER_set_error(loader, ldap_store_error) + || !OSSL_STORE_LOADER_set_close(loader, ldap_store_close) + || !OSSL_STORE_register_loader(loader) + ) + goto err; + + return 1; +err: + OSSL_STORE_LOADER_free(loader); + return 0; +} + + +static void +destroy_ldap_store(ENGINE *e) { + OSSL_STORE_LOADER *loader; + +TRACE_BY_LDAP(__func__, "e=%p", (void*)e); + loader = OSSL_STORE_unregister_loader(ldap_store_scheme); + + OSSL_STORE_LOADER_free(loader); +} + + +/* engine */ +static const char *e_ldap_id = "e_ldap"; +static const char *e_ldap_name = "LDAP engine"; + + +static int/*bool*/ +e_ldap_init(ENGINE *e) { +TRACE_BY_LDAP(__func__, "e=%p", (void*)e); + + return 1; +} + + +static int +e_ldap_finish(ENGINE *e) { +TRACE_BY_LDAP(__func__, "e=%p", (void*)e); + + return 1; +} + + +static int +e_ldap_destroy(ENGINE *e) { +TRACE_BY_LDAP(__func__, "e=%p", (void*)e); + + destroy_ldap_store(e); + +#if 0 + ERR_unload_LDAP_strings(); +#endif + + return 1; +} + + +static int/*bool*/ +bind_ldap(ENGINE *e) { +TRACE_BY_LDAP(__func__, "e=%p", (void*)e); + + if (!ENGINE_set_id(e, e_ldap_id) + || !ENGINE_set_name(e, e_ldap_name) + || !ENGINE_set_flags(e, ENGINE_FLAGS_NO_REGISTER_ALL) + || !ENGINE_set_init_function(e, e_ldap_init) + || !ENGINE_set_finish_function(e, e_ldap_finish) + || !ENGINE_set_destroy_function(e, e_ldap_destroy) + ) + return 0; + + if (!bind_ldap_store(e)) + return 0; + +#if 0 + /* ensure the engine error handling is set up */ + ERR_load_LDAP_strings(); +#endif + + return 1; +} + + +static ENGINE* +engine_ldap(void) { + ENGINE *e; + +TRACE_BY_LDAP(__func__, ""); + + e = ENGINE_new(); + if (e == NULL) return NULL; + + if (!bind_ldap(e)) { + ENGINE_free(e); + return NULL; + } + return e; +} + + +void +ENGINE_load_ldap(void) { + ENGINE *e; + +TRACE_BY_LDAP(__func__, ""); + + e = engine_ldap(); + if (e == NULL) return; + + ERR_set_mark(); + ENGINE_add(e); + ENGINE_free(e); + ERR_pop_to_mark(); +} + +#else /*def USE_LDAP_STORE*/ + +typedef int e_ldap_empty_translation_unit; + +#endif diff -ruN openssh-9.4p1/entropy.c openssh-9.4p1+x509-14.2.1/entropy.c --- openssh-9.4p1/entropy.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/entropy.c 2023-08-20 10:07:01.000000000 +0300 @@ -1,5 +1,6 @@ /* * Copyright (c) 2001 Damien Miller. All rights reserved. + * Copyright (c) 2018-2023 Roumen Petrov. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -31,7 +32,6 @@ #include #include -#include #include #include #include @@ -40,8 +40,6 @@ #include #include -#include "openbsd-compat/openssl-compat.h" - #include "ssh.h" #include "misc.h" #include "xmalloc.h" @@ -49,7 +47,8 @@ #include "pathnames.h" #include "log.h" #include "sshbuf.h" -#include "ssherr.h" + +extern int ssh_compatible_openssl(long headerver, long libver); /* * Portable OpenSSH PRNG seeding: @@ -57,20 +56,25 @@ * /dev/random), then collect RANDOM_SEED_SIZE bytes of randomness from * PRNGd. */ +#ifndef OPENSSL_PRNG_ONLY +extern int seed_from_prngd(unsigned char *, size_t); +#endif /* OPENSSL_PRNG_ONLY */ void seed_rng(void) { unsigned char buf[RANDOM_SEED_SIZE]; - /* Initialise libcrypto */ - ssh_libcrypto_init(); +{ +#ifndef HAVE_OPENSSL_INIT_CRYPTO /* OpenSSL < 1.1 */ +# define OpenSSL_version_num SSLeay +#endif + unsigned long ver_num = OpenSSL_version_num(); - if (!ssh_compatible_openssl(OPENSSL_VERSION_NUMBER, - OpenSSL_version_num())) + if (!ssh_compatible_openssl(OPENSSL_VERSION_NUMBER, ver_num)) fatal("OpenSSL version mismatch. Built against %lx, you " - "have %lx", (u_long)OPENSSL_VERSION_NUMBER, - OpenSSL_version_num()); + "have %lx", (u_long)OPENSSL_VERSION_NUMBER, ver_num); +} #ifndef OPENSSL_PRNG_ONLY if (RAND_status() == 1) diff -ruN openssh-9.4p1/evp-compat.h openssh-9.4p1+x509-14.2.1/evp-compat.h --- openssh-9.4p1/evp-compat.h 1970-01-01 02:00:00.000000000 +0200 +++ openssh-9.4p1+x509-14.2.1/evp-compat.h 2023-08-20 10:07:00.000000000 +0300 @@ -0,0 +1,124 @@ +#ifndef EVP_COMPAT_H +#define EVP_COMPAT_H +/* + * Copyright (c) 2011-2022 Roumen Petrov. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "includes.h" + +#ifdef WITH_OPENSSL +# include +# include +# ifdef HAVE_OPENSSL_EC_H +# include +# else +# define EC_GROUP void +# define EC_POINT void +# endif +# if defined(OPENSSL_HAS_ECC) +# include +# if defined(OPENSSL_VERSION_NUMBER) && (OPENSSL_VERSION_NUMBER < 0x00908000L) + /* before OpenSSL 0.9.8 */ +# define EC_KEY void +# endif +# else /* OPENSSL_HAS_ECC */ +# define EC_KEY void +# endif /* OPENSSL_HAS_ECC */ +#else /* WITH_OPENSSL */ +# define BIGNUM void +# define EVP_PKEY void +# define RSA void +# define DSA void +# define EC_KEY void +# define EC_GROUP void +# define EC_POINT void +#endif /* WITH_OPENSSL */ + +#ifdef WITH_OPENSSL +#include "openbsd-compat/openssl-compat.h" + + +#ifndef HAVE_EVP_MD_CTX_NEW /* OpenSSL < 1.1 */ +static inline EVP_MD_CTX* +EVP_MD_CTX_new(void) { + EVP_MD_CTX *ctx; + + ctx = OPENSSL_malloc(sizeof(EVP_MD_CTX)); + if (ctx != NULL) { + EVP_MD_CTX_init(ctx); + } + return(ctx); +} + + +static inline void +EVP_MD_CTX_free(EVP_MD_CTX *ctx) { + EVP_MD_CTX_cleanup(ctx); + OPENSSL_free(ctx); +} +#endif/* ndef HAVE_EVP_MD_CTX_NEW OpenSSL < 1.1 */ + + +#ifndef HAVE_EVP_MD_FLAGS /* OpenSSL < 1.0 */ +# ifdef HAVE_EVP_MD_GET_FLAGS /* OpenSSL >= 3.0 */ +/* EVP_MD_flags is define to EVP_MD_get_flags */ +/* TODO use EVP_MD_get_flags? :( */ +# else +static inline unsigned long +EVP_MD_flags(const EVP_MD *md) { + return md->flags; +} +# endif +#endif /* ndef HAVE_EVP_MD_FLAGS OpenSSL < 1.0 */ + + +#ifndef HAVE_EVP_PKEY_BASE_ID /* OpenSSL < 1.0 */ +# ifdef HAVE_EVP_PKEY_GET_BASE_ID /* OpenSSL >= 3.0 */ +/* EVP_PKEY_base_id is define to EVP_PKEY_get_base_id */ +/* TODO use EVP_PKEY_get_base_id? :( */ +# else +static inline int +EVP_PKEY_id(const EVP_PKEY *pkey) { + return pkey->type; +} + +static inline int +EVP_PKEY_base_id(const EVP_PKEY *pkey) { + return(EVP_PKEY_type(EVP_PKEY_id(pkey))); +} +# endif +#endif /*ndef HAVE_EVP_PKEY_BASE_ID */ + + +int ssh_EVP_PKEY_eq(const EVP_PKEY *a, const EVP_PKEY *b); + + +#if !HAVE_DECL_UTF8_GETC +/* hidden in some OpenSSL compatible libraries */ +int UTF8_getc(const unsigned char *str, int len, unsigned long *val); +int UTF8_putc(unsigned char *str, int len, unsigned long value); +#endif + +#endif /*def WITH_OPENSSL */ + +#endif /* ndef EVP_COMPAT_H*/ diff -ruN openssh-9.4p1/fatal.c openssh-9.4p1+x509-14.2.1/fatal.c --- openssh-9.4p1/fatal.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/fatal.c 2023-08-20 10:07:01.000000000 +0300 @@ -1,6 +1,7 @@ /* $OpenBSD: fatal.c,v 1.11 2020/10/19 08:07:08 djm Exp $ */ /* * Copyright (c) 2002 Markus Friedl. All rights reserved. + * Copyright (c) 2020 Roumen Petrov. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -34,13 +35,50 @@ /* Fatal messages. This function never returns. */ void -sshfatal(const char *file, const char *func, int line, int showfunc, - LogLevel level, const char *suffix, const char *fmt, ...) +sshfatal(const char *file, const char *func, int line, + const char *fmt, ...) { va_list args; va_start(args, fmt); - sshlogv(file, func, line, showfunc, level, suffix, fmt, args); + sshlogv(file, func, line, SYSLOG_LEVEL_FATAL, fmt, args); + va_end(args); + cleanup_exit(255); +} + +void +sshfatal_f(const char *file, const char *func, int line, + const char *fmt, ...) +{ + va_list args; + + va_start(args, fmt); + sshlogv_f(file, func, line, SYSLOG_LEVEL_FATAL, fmt, args); + va_end(args); + cleanup_exit(255); +} + + +void +sshfatal_r(const char *file, const char *func, int line, + int errcode, const char *fmt, ...) +{ + va_list args; + + va_start(args, fmt); + sshlogv_r(file, func, line, errcode, SYSLOG_LEVEL_FATAL, fmt, args); + va_end(args); + cleanup_exit(255); +} + +void +sshfatal_fr(const char *file, const char *func, int line, + int errcode, const char *fmt, ...) +{ + va_list args; + + va_start(args, fmt); + sshlogv_fr(file, func, line, errcode, SYSLOG_LEVEL_FATAL, fmt, args); va_end(args); cleanup_exit(255); } diff -ruN openssh-9.4p1/fixalgorithms openssh-9.4p1+x509-14.2.1/fixalgorithms --- openssh-9.4p1/fixalgorithms 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/fixalgorithms 2023-08-20 10:07:00.000000000 +0300 @@ -1,7 +1,7 @@ #!/bin/sh # # fixciphers - remove unsupported ciphers from man pages. -# Usage: fixpaths /path/to/sed cipher1 [cipher2] outfile +# Usage: fixpaths /path/to/sed cipher1 [cipher2] outfile # # Author: Darren Tucker (dtucker at zip com.au). Placed in the public domain. diff -ruN openssh-9.4p1/.git_allowed_signers openssh-9.4p1+x509-14.2.1/.git_allowed_signers --- openssh-9.4p1/.git_allowed_signers 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/.git_allowed_signers 1970-01-01 02:00:00.000000000 +0200 @@ -1,5 +0,0 @@ -dtucker@dtucker.net ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKecyjh9aNmD4rb8WblA8v91JjRb0Cd2JtkzqxcggGeG -djm@mindrot.org sk-ecdsa-sha2-nistp256@openssh.com AAAAInNrLWVjZHNhLXNoYTItbmlzdHAyNTZAb3BlbnNzaC5jb20AAAAIbmlzdHAyNTYAAABBBLnJo3ZVDENYZGXm5uO9lU7b0iDFq5gHpTu1MaHPWTEfPdvw+AjFQQ/q5YizuMJkXGsMdYmblJEJZYHpm9IS7ZkAAAAEc3NoOg== -djm@mindrot.org sk-ecdsa-sha2-nistp256@openssh.com AAAAInNrLWVjZHNhLXNoYTItbmlzdHAyNTZAb3BlbnNzaC5jb20AAAAIbmlzdHAyNTYAAABBBJoAXBTQalfg+kC5wy1vE7HkIHtVnmV6AUuuIo9KQ1P+70juHwvsFKpsGaqQbrHJkTVgYDGVP02XHj8+Fb18yBIAAAAEc3NoOg== -djm@mindrot.org sk-ecdsa-sha2-nistp256@openssh.com AAAAInNrLWVjZHNhLXNoYTItbmlzdHAyNTZAb3BlbnNzaC5jb20AAAAIbmlzdHAyNTYAAABBBH+z1I48s6ydOhP5SJmI02zVCLf0K15B+UMHgoTIKVfUIv5oDoVX7e9f+7QiRmTeEOdZfQydiaVqsfi7qPSve+0AAAAEc3NoOg== -djm@mindrot.org sk-ecdsa-sha2-nistp256@openssh.com AAAAInNrLWVjZHNhLXNoYTItbmlzdHAyNTZAb3BlbnNzaC5jb20AAAAIbmlzdHAyNTYAAABBBPM4BmUg/fMnsl42JwktTekk/mB8Be3M+yK2ayg6lqYsqEri8yhRx84gey51OHKVk1TwlGbJjcMHI4URreDBEMQAAAAEc3NoOg== diff -ruN openssh-9.4p1/.git_allowed_signers.asc openssh-9.4p1+x509-14.2.1/.git_allowed_signers.asc --- openssh-9.4p1/.git_allowed_signers.asc 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/.git_allowed_signers.asc 1970-01-01 02:00:00.000000000 +0200 @@ -1,16 +0,0 @@ ------BEGIN PGP SIGNATURE----- - -iQIzBAABCgAdFiEEcWi5g4FaXu9ZpK39Kj9BTnNgYLoFAmMMMiIACgkQKj9BTnNg -YLpyGhAAhZ1RxmD62JnT0gnor1aD0inq1fGPRadaFvXH2OScPcxXMIZWx+otnyZ/ -H9s0bIti42dPHqurgh92KS2mDGVIW8Y8MvxFUr678+hdem1U7Xvjoo0uaveNhJhe -GxuQDOvXKRmmfL2c6w3wnFChFA1o3K+JNshjCHhWz7u6+UmY0Q9yIxqbSi+vmEPP -NfWPfGdu4h8r7q11UgTxRSUQkfZXMqpBtb367B9BLduGuKRFKEJNyi6WpjBrqy38 -BvEbAaL52KX8hEp3TKMjo38RbOK+veSoPV5zlLui0WlEwwasgljal3f4RkqCAJob -hqpFJRogM5XNnA2e68TDTf3buJ3wRRjuK39/CusOJz5v4i6+VCdte+BET1Y4gD6y -v8KV4pRyumcdbN3khFUkmaQsjo+fyQjWNrgOvv60J2xUWZdchn8lxHOxrfRVKnOi -BD4bdks7tPQY/XsS5GNJIp21Ji9HGyBajjHo0BlesLodw7FEOf6YE18A3n9qzosR -RliuP4Hs/Z4sCUuDTbpKtQiUVs40kBbkhEL8kS8FsXz3VO89hAWaUqNUYom8AkKv -nfDjrZDBLXuVj1Mi8qNPXxqrB/1Cza2/W4U7SK4TlMFXfoXXWxxhefN5vIdMhAJB -u9Mdz1pY9mowKbd0c0dR+3fauvjM133dzKuyeDHMqDa5JPyd59o= -=kgnS ------END PGP SIGNATURE----- diff -ruN openssh-9.4p1/.github/ci-status.md openssh-9.4p1+x509-14.2.1/.github/ci-status.md --- openssh-9.4p1/.github/ci-status.md 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/.github/ci-status.md 1970-01-01 02:00:00.000000000 +0200 @@ -1,11 +0,0 @@ -master : -[![C/C++ CI](https://github.com/openssh/openssh-portable/actions/workflows/c-cpp.yml/badge.svg)](https://github.com/openssh/openssh-portable/actions/workflows/c-cpp.yml?query=branch:master) -[![C/C++ CI self-hosted](https://github.com/openssh/openssh-portable-selfhosted/actions/workflows/selfhosted.yml/badge.svg)](https://github.com/openssh/openssh-portable-selfhosted/actions/workflows/selfhosted.yml?query=branch:master) -[![Upstream self-hosted](https://github.com/openssh/openssh-portable-selfhosted/actions/workflows/upstream.yml/badge.svg)](https://github.com/openssh/openssh-portable-selfhosted/actions/workflows/upstream.yml?query=branch:master) -[![CIFuzz](https://github.com/openssh/openssh-portable/actions/workflows/cifuzz.yml/badge.svg)](https://github.com/openssh/openssh-portable/actions/workflows/cifuzz.yml) -[![Fuzzing Status](https://oss-fuzz-build-logs.storage.googleapis.com/badges/openssh.svg)](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:openssh) -[![Coverity Status](https://scan.coverity.com/projects/21341/badge.svg)](https://scan.coverity.com/projects/openssh-portable) - -9.3 : -[![C/C++ CI](https://github.com/openssh/openssh-portable/actions/workflows/c-cpp.yml/badge.svg?branch=V_9_3)](https://github.com/openssh/openssh-portable/actions/workflows/c-cpp.yml?query=branch:V_9_3) -[![C/C++ CI self-hosted](https://github.com/openssh/openssh-portable-selfhosted/actions/workflows/selfhosted.yml/badge.svg?branch=V_9_3)](https://github.com/openssh/openssh-portable-selfhosted/actions/workflows/selfhosted.yml?query=branch:V_9_3) diff -ruN openssh-9.4p1/.github/configs openssh-9.4p1+x509-14.2.1/.github/configs --- openssh-9.4p1/.github/configs 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/.github/configs 1970-01-01 02:00:00.000000000 +0200 @@ -1,340 +0,0 @@ -#!/bin/sh -# -# usage: configs vmname test_config (or '' for default) -# -# Sets the following variables: -# CONFIGFLAGS options to ./configure -# SSHD_CONFOPTS sshd_config options -# TEST_TARGET make target used when testing. defaults to "tests". -# LTESTS - -config=$1 -if [ "$config" = "" ]; then - config="default" -fi - -unset CC CFLAGS CPPFLAGS LDFLAGS LTESTS SUDO - -TEST_TARGET="tests compat-tests" -LTESTS="" -SKIP_LTESTS="" -SUDO=sudo # run with sudo by default -TEST_SSH_UNSAFE_PERMISSIONS=1 -# Stop on first test failure to minimize logs -TEST_SSH_FAIL_FATAL=yes - -CONFIGFLAGS="" -LIBCRYPTOFLAGS="" - -case "$config" in - default|sol64) - ;; - c89) - CC="gcc" - CFLAGS="-Wall -std=c89 -pedantic -Werror=vla" - CONFIGFLAGS="--without-zlib" - LIBCRYPTOFLAGS="--without-openssl" - TEST_TARGET=t-exec - ;; - cygwin-release) - # See https://cygwin.com/git/?p=git/cygwin-packages/openssh.git;a=blob;f=openssh.cygport;hb=HEAD - CONFIGFLAGS="--with-xauth=/usr/bin/xauth --with-security-key-builtin" - CONFIGFLAGS="$CONFIGFLAGS --with-kerberos5=/usr --with-libedit --disable-strip" - ;; - clang-12-Werror) - CC="clang-12" - # clang's implicit-fallthrough requires that the code be annotated with - # __attribute__((fallthrough)) and does not understand /* FALLTHROUGH */ - CFLAGS="-Wall -Wextra -O2 -Wno-error=implicit-fallthrough -Wno-error=unused-parameter" - CONFIGFLAGS="--with-pam --with-Werror" - ;; - *-sanitize-*) - case "$config" in - gcc-*) - CC=gcc - ;; - clang-*) - # Find the newest available version of clang - for i in `seq 10 99`; do - clang="`which clang-$i 2>/dev/null`" - [ -x "$clang" ] && CC="$clang" - done - ;; - esac - # Put Sanitizer logs in regress dir. - SANLOGS=`pwd`/regress - # - We replace chroot with chdir so that the sanitizer in the preauth - # privsep process can read /proc. - # - clang does not recognizes explicit_bzero so we use bzero - # (see https://github.com/google/sanitizers/issues/1507 - # - openssl and zlib trip ASAN. - # - sp_pwdp returned by getspnam trips ASAN, hence disabling shadow. - case "$config" in - *-sanitize-address) - CFLAGS="-fsanitize=address -fno-omit-frame-pointer" - LDFLAGS="-fsanitize=address" - CPPFLAGS='-Dchroot=chdir -Dexplicit_bzero=bzero -D_FORTIFY_SOURCE=0 -DASAN_OPTIONS=\"detect_leaks=0:log_path='$SANLOGS'/asan.log\"' - CONFIGFLAGS="" - TEST_TARGET="t-exec" - ;; - clang-sanitize-memory) - CFLAGS="-fsanitize=memory -fsanitize-memory-track-origins -fno-omit-frame-pointer" - LDFLAGS="-fsanitize=memory" - CPPFLAGS='-Dchroot=chdir -Dexplicit_bzero=bzero -DMSAN_OPTIONS=\"log_path='$SANLOGS'/msan.log\"' - CONFIGFLAGS="--without-zlib --without-shadow" - LIBCRYPTOFLAGS="--without-openssl" - TEST_TARGET="t-exec" - ;; - *-sanitize-undefined) - CFLAGS="-fsanitize=undefined" - LDFLAGS="-fsanitize=undefined" - ;; - *) - echo unknown sanitize option; - exit 1;; - esac - features="--disable-security-key --disable-pkcs11" - hardening="--without-sandbox --without-hardening --without-stackprotect" - privsep="--with-privsep-user=root" - CONFIGFLAGS="$CONFIGFLAGS $features $hardening $privsep" - # Because we hobble chroot we can't test it. - SKIP_LTESTS=sftp-chroot - ;; - gcc-11-Werror) - CC="gcc" - # -Wnoformat-truncation in gcc 7.3.1 20180130 fails on fmt_scaled - CFLAGS="-Wall -Wextra -O2 -Wno-format-truncation -Wimplicit-fallthrough=4 -Wno-unused-parameter" - CONFIGFLAGS="--with-pam --with-Werror" - ;; - clang*|gcc*) - CC="$config" - ;; - kitchensink) - CONFIGFLAGS="--with-kerberos5 --with-libedit --with-pam" - CONFIGFLAGS="${CONFIGFLAGS} --with-security-key-builtin --with-selinux" - CFLAGS="-DSK_DEBUG -DSANDBOX_SECCOMP_FILTER_DEBUG" - ;; - hardenedmalloc) - CONFIGFLAGS="--with-ldflags=-lhardened_malloc" - ;; - tcmalloc) - CONFIGFLAGS="--with-ldflags=-ltcmalloc" - ;; - krb5|heimdal) - CONFIGFLAGS="--with-kerberos5" - ;; - libedit) - CONFIGFLAGS="--with-libedit" - ;; - musl) - CC="musl-gcc" - CONFIGFLAGS="--without-zlib" - LIBCRYPTOFLAGS="--without-openssl" - TEST_TARGET="t-exec" - ;; - pam-krb5) - CONFIGFLAGS="--with-pam --with-kerberos5" - SSHD_CONFOPTS="UsePam yes" - ;; - *pam) - CONFIGFLAGS="--with-pam" - SSHD_CONFOPTS="UsePam yes" - ;; - boringssl) - CONFIGFLAGS="--disable-pkcs11" - LIBCRYPTOFLAGS="--with-ssl-dir=/opt/boringssl --with-rpath=-Wl,-rpath," - ;; - libressl-*) - LIBCRYPTOFLAGS="--with-ssl-dir=/opt/libressl --with-rpath=-Wl,-rpath," - ;; - openssl-*) - LIBCRYPTOFLAGS="--with-ssl-dir=/opt/openssl --with-rpath=-Wl,-rpath," - # OpenSSL 1.1.1 specifically has a bug in its RNG that breaks reexec - # fallback. See https://bugzilla.mindrot.org/show_bug.cgi?id=3483 - if [ "$config" = "openssl-1.1.1" ]; then - SKIP_LTESTS="reexec" - fi - ;; - selinux) - CONFIGFLAGS="--with-selinux" - ;; - sk) - CONFIGFLAGS="--with-security-key-builtin" - ;; - without-openssl) - LIBCRYPTOFLAGS="--without-openssl" - TEST_TARGET=t-exec - ;; - valgrind-[1-5]|valgrind-unit) - # rlimit sandbox and FORTIFY_SOURCE confuse Valgrind. - CONFIGFLAGS="--without-sandbox --without-hardening" - CONFIGFLAGS="$CONFIGFLAGS --with-cppflags=-D_FORTIFY_SOURCE=0" - TEST_TARGET="t-exec USE_VALGRIND=1" - TEST_SSH_ELAPSED_TIMES=1 - export TEST_SSH_ELAPSED_TIMES - # Valgrind slows things down enough that the agent timeout test - # won't reliably pass, and the unit tests run longer than allowed - # by github so split into separate tests. - tests2="integrity try-ciphers" - tests3="krl forward-control sshsig agent-restrict kextype sftp" - tests4="cert-userkey cert-hostkey kextype sftp-perm keygen-comment percent" - tests5="rekey" - case "$config" in - valgrind-1) - # All tests except agent-timeout (which is flaky under valgrind), - # connection-timeout (which doesn't work since it's so slow) - # and hostbased (since valgrind won't let ssh exec keysign). - # Slow ones are run separately to increase parallelism. - SKIP_LTESTS="agent-timeout connection-timeout hostbased" - SKIP_LTESTS="$SKIP_LTESTS ${tests2} ${tests3} ${tests4} ${tests5}" - ;; - valgrind-2) - LTESTS="${tests2}" - ;; - valgrind-3) - LTESTS="${tests3}" - ;; - valgrind-4) - LTESTS="${tests4}" - ;; - valgrind-5) - LTESTS="${tests5}" - ;; - valgrind-unit) - TEST_TARGET="unit USE_VALGRIND=1" - ;; - esac - ;; - *) - echo "Unknown configuration $config" - exit 1 - ;; -esac - -# The Solaris 64bit targets are special since they need a non-flag arg. -case "$config" in - sol64*) - CONFIGFLAGS="--target=x86_64 --with-cflags=-m64 --with-ldflags=-m64 ${CONFIGFLAGS}" - LIBCRYPTOFLAGS="--with-ssl-dir=/usr/local/ssl64 --with-rpath=-Wl,-rpath," - ;; -esac - -case "${TARGET_HOST}" in - aix*) - CONFIGFLAGS="--disable-security-key" - LIBCRYPTOFLAGS="--without-openssl" - # These are slow real or virtual machines so skip the slowest tests - # (which tend to be thw ones that transfer lots of data) so that the - # test run does not time out. - # The agent-restrict test fails due to some quoting issue when run - # with sh or ksh so specify bash for now. - TEST_TARGET="t-exec unit TEST_SHELL=bash" - SKIP_LTESTS="rekey sftp" - ;; - debian-riscv64) - # This machine is fairly slow, so skip the unit tests. - TEST_TARGET="t-exec" - ;; - dfly58*|dfly60*) - # scp 3-way connection hangs on these so skip until sorted. - SKIP_LTESTS=scp3 - ;; - fbsd6) - # Native linker is not great with PIC so OpenSSL is built w/out. - CONFIGFLAGS="${CONFIGFLAGS} --disable-security-key" - ;; - hurd) - SKIP_LTESTS="forwarding multiplex proxy-connect hostkey-agent agent-ptrace" - ;; - minix3) - CONFIGFLAGS="${CONFIGFLAGS} --disable-security-key" - LIBCRYPTOFLAGS="--without-openssl" - # Minix does not have a loopback interface so we have to skip any - # test that relies on one. - # Also, Minix seems to be very limited in the number of select() - # calls that can be operating concurrently, so prune additional tests for that. - T="addrmatch agent-restrict brokenkeys cfgmatch cfgmatchlisten cfgparse - connect connect-uri exit-status forwarding hostkey-agent - key-options keyscan knownhosts-command login-timeout - reconfigure reexec rekey scp scp-uri scp3 sftp sftp-badcmds - sftp-batch sftp-cmds sftp-glob sftp-perm sftp-uri stderr-data - transfer" - # Unix domain sockets don't work quite like we expect, so also skip any tests - # that use multiplexing. - T="$T connection-timeout dynamic-forward forward-control multiplex" - SKIP_LTESTS="$(echo $T)" - TEST_TARGET=t-exec - SUDO="" - ;; - nbsd4) - # System compiler will ICE on some files with fstack-protector - # SHA256 functions in sha2.h conflict with OpenSSL's breaking sk-dummy - CONFIGFLAGS="${CONFIGFLAGS} --without-hardening --disable-security-key" - ;; - openwrt-*) - CONFIGFLAGS="${CONFIGFLAGS} --without-zlib" - LIBCRYPTOFLAGS="--without-openssl" - TEST_TARGET="t-exec" - ;; - sol10|sol11) - # sol10 VM is 32bit and the unit tests are slow. - # sol11 has 4 test configs so skip unit tests to speed up. - TEST_TARGET="tests SKIP_UNIT=1" - ;; - win10) - # No sudo on Windows. - SUDO="" - ;; -esac - -host=`./config.guess` -case "$host" in -*cygwin) - SUDO="" - # Don't run compat tests on cygwin as they don't currently compile. - TEST_TARGET="tests" - ;; -*-darwin*) - # Unless specified otherwise, build without OpenSSL on Mac OS since - # modern versions don't ship with libcrypto. - LIBCRYPTOFLAGS="--without-openssl" - TEST_TARGET=t-exec - case "$host" in - *-darwin22.*) - # sudo -S nobody doesn't work on macos 13 for some reason. - SKIP_LTESTS="agent-getpeereid" ;; - esac - ;; -esac - -# Unless specifically configured, search for a suitable version of OpenSSL, -# otherwise build without it. -if [ -z "${LIBCRYPTOFLAGS}" ]; then - LIBCRYPTOFLAGS="--without-openssl" - # last-match - for i in /usr /usr/local /usr/local/ssl /usr/local/opt/openssl; do - ver="none" - if [ -x ${i}/bin/openssl ]; then - ver="$(${i}/bin/openssl version)" - fi - case "$ver" in - none) ;; - "OpenSSL 0."*|"OpenSSL 1.0."*|"OpenSSL 1.1.0"*) ;; - "LibreSSL 2."*|"LibreSSL 3.0."*) ;; - *) LIBCRYPTOFLAGS="--with-ssl-dir=${i}" ;; - esac - done - if [ "${LIBCRYPTOFLAGS}" = "--without-openssl" ]; then - TEST_TARGET="t-exec" - fi -fi - -CONFIGFLAGS="${CONFIGFLAGS} ${LIBCRYPTOFLAGS}" - -if [ -x "$(which plink 2>/dev/null)" ]; then - REGRESS_INTEROP_PUTTY=yes - export REGRESS_INTEROP_PUTTY -fi - -export CC CFLAGS CPPFLAGS LDFLAGS LTESTS SUDO -export TEST_TARGET TEST_SSH_UNSAFE_PERMISSIONS TEST_SSH_FAIL_FATAL diff -ruN openssh-9.4p1/.github/configure.sh openssh-9.4p1+x509-14.2.1/.github/configure.sh --- openssh-9.4p1/.github/configure.sh 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/.github/configure.sh 1970-01-01 02:00:00.000000000 +0200 @@ -1,21 +0,0 @@ -#!/bin/sh - -. .github/configs $1 - -printf "$ " - -if [ "x$CC" != "x" ]; then - printf "CC='$CC' " -fi -if [ "x$CFLAGS" != "x" ]; then - printf "CFLAGS='$CFLAGS' " -fi -if [ "x$CPPFLAGS" != "x" ]; then - printf "CPPFLAGS='$CPPFLAGS' " -fi -if [ "x$LDFLAGS" != "x" ]; then - printf "LDFLAGS='$LDFLAGS' " -fi - -echo ./configure ${CONFIGFLAGS} -./configure ${CONFIGFLAGS} 2>&1 diff -ruN openssh-9.4p1/.github/run_test.sh openssh-9.4p1+x509-14.2.1/.github/run_test.sh --- openssh-9.4p1/.github/run_test.sh 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/.github/run_test.sh 1970-01-01 02:00:00.000000000 +0200 @@ -1,48 +0,0 @@ -#!/bin/sh - -. .github/configs $1 - -[ -z "${SUDO}" ] || ${SUDO} mkdir -p /var/empty - -set -ex - -# If we want to test hostbased auth, set up the host for it. -if [ ! -z "$SUDO" ] && [ ! -z "$TEST_SSH_HOSTBASED_AUTH" ]; then - sshconf=/usr/local/etc - hostname | $SUDO tee $sshconf/shosts.equiv >/dev/null - echo "EnableSSHKeysign yes" | $SUDO tee $sshconf/ssh_config >/dev/null - $SUDO mkdir -p $sshconf - $SUDO cp -p /etc/ssh/ssh_host*key* $sshconf - $SUDO make install - for key in $sshconf/ssh_host*key*.pub; do - echo `hostname` `cat $key` | \ - $SUDO tee -a $sshconf/ssh_known_hosts >/dev/null - done -fi - -output_failed_logs() { - for i in regress/failed*.log; do - if [ -f "$i" ]; then - echo ------------------------------------------------------------------------- - echo LOGFILE $i - cat $i - echo ------------------------------------------------------------------------- - fi - done -} -trap output_failed_logs 0 - -if [ -z "${LTESTS}" ]; then - make ${TEST_TARGET} SKIP_LTESTS="${SKIP_LTESTS}" -else - make ${TEST_TARGET} SKIP_LTESTS="${SKIP_LTESTS}" LTESTS="${LTESTS}" -fi - -if [ ! -z "${SSHD_CONFOPTS}" ]; then - echo "rerunning t-exec with TEST_SSH_SSHD_CONFOPTS='${SSHD_CONFOPTS}'" - if [ -z "${LTESTS}" ]; then - make t-exec SKIP_LTESTS="${SKIP_LTESTS}" TEST_SSH_SSHD_CONFOPTS="${SSHD_CONFOPTS}" - else - make t-exec SKIP_LTESTS="${SKIP_LTESTS}" LTESTS="${LTESTS}" TEST_SSH_SSHD_CONFOPTS="${SSHD_CONFOPTS}" - fi -fi diff -ruN openssh-9.4p1/.github/setup_ci.sh openssh-9.4p1+x509-14.2.1/.github/setup_ci.sh --- openssh-9.4p1/.github/setup_ci.sh 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/.github/setup_ci.sh 1970-01-01 02:00:00.000000000 +0200 @@ -1,216 +0,0 @@ -#!/bin/sh - -PACKAGES="" - - . .github/configs $@ - -host=`./config.guess` -echo "config.guess: $host" -case "$host" in -*cygwin) - PACKAGER=setup - echo Setting CYGWIN system environment variable. - setx CYGWIN "binmode" - echo Removing extended ACLs so umask works as expected. - setfacl -b . regress - PACKAGES="$PACKAGES,autoconf,automake,cygwin-devel,gcc-core" - PACKAGES="$PACKAGES,make,openssl-devel,zlib-devel" - ;; -*-darwin*) - PACKAGER=brew - brew install automake - exit 0 - ;; -*) - PACKAGER=apt -esac - -TARGETS=$@ - -INSTALL_FIDO_PPA="no" -export DEBIAN_FRONTEND=noninteractive - -#echo "Setting up for '$TARGETS'" - -set -ex - -if [ -x "`which lsb_release 2>&1`" ]; then - lsb_release -a -fi - -# Ubuntu 22.04 defaults to private home dirs which prevent the -# agent-getpeerid test from running ssh-add as nobody. See -# https://github.com/actions/runner-images/issues/6106 -if [ ! -z "$SUDO" ] && ! "$SUDO" -u nobody test -x ~; then - echo ~ is not executable by nobody, adding perms. - chmod go+x ~ -fi - -if [ "${TARGETS}" = "kitchensink" ]; then - TARGETS="krb5 libedit pam sk selinux" -fi - -for flag in $CONFIGFLAGS; do - case "$flag" in - --with-pam) TARGETS="${TARGETS} pam" ;; - --with-libedit) TARGETS="${TARGETS} libedit" ;; - esac -done - -for TARGET in $TARGETS; do - case $TARGET in - default|without-openssl|without-zlib|c89) - # nothing to do - ;; - clang-sanitize*) - PACKAGES="$PACKAGES clang-12" - ;; - cygwin-release) - PACKAGES="$PACKAGES libcrypt-devel libfido2-devel libkrb5-devel" - ;; - gcc-sanitize*) - ;; - clang-*|gcc-*) - compiler=$(echo $TARGET | sed 's/-Werror//') - PACKAGES="$PACKAGES $compiler" - ;; - krb5) - PACKAGES="$PACKAGES libkrb5-dev" - ;; - heimdal) - PACKAGES="$PACKAGES heimdal-dev" - ;; - libedit) - case "$PACKAGER" in - setup) PACKAGES="$PACKAGES libedit-devel" ;; - apt) PACKAGES="$PACKAGES libedit-dev" ;; - esac - ;; - *pam) - PACKAGES="$PACKAGES libpam0g-dev" - ;; - sk) - INSTALL_FIDO_PPA="yes" - PACKAGES="$PACKAGES libfido2-dev libu2f-host-dev libcbor-dev" - ;; - selinux) - PACKAGES="$PACKAGES libselinux1-dev selinux-policy-dev" - ;; - hardenedmalloc) - INSTALL_HARDENED_MALLOC=yes - ;; - musl) - PACKAGES="$PACKAGES musl-tools" - ;; - tcmalloc) - PACKAGES="$PACKAGES libgoogle-perftools-dev" - ;; - openssl-noec) - INSTALL_OPENSSL=OpenSSL_1_1_1k - SSLCONFOPTS="no-ec" - ;; - openssl-*) - INSTALL_OPENSSL=$(echo ${TARGET} | cut -f2 -d-) - case ${INSTALL_OPENSSL} in - 1.1.1_stable) INSTALL_OPENSSL="OpenSSL_1_1_1-stable" ;; - 1.*) INSTALL_OPENSSL="OpenSSL_$(echo ${INSTALL_OPENSSL} | tr . _)" ;; - 3.*) INSTALL_OPENSSL="openssl-${INSTALL_OPENSSL}" ;; - esac - PACKAGES="${PACKAGES} putty-tools" - ;; - libressl-*) - INSTALL_LIBRESSL=$(echo ${TARGET} | cut -f2 -d-) - case ${INSTALL_LIBRESSL} in - master) ;; - *) INSTALL_LIBRESSL="$(echo ${TARGET} | cut -f2 -d-)" ;; - esac - PACKAGES="${PACKAGES} putty-tools" - ;; - boringssl) - INSTALL_BORINGSSL=1 - PACKAGES="${PACKAGES} cmake ninja-build" - ;; - valgrind*) - PACKAGES="$PACKAGES valgrind" - ;; - *) echo "Invalid option '${TARGET}'" - exit 1 - ;; - esac -done - -if [ "yes" = "$INSTALL_FIDO_PPA" ]; then - sudo apt update -qq - sudo apt install -qy software-properties-common - sudo apt-add-repository -y ppa:yubico/stable -fi - -tries=3 -while [ ! -z "$PACKAGES" ] && [ "$tries" -gt "0" ]; do - case "$PACKAGER" in - apt) - sudo apt update -qq - if sudo apt install -qy $PACKAGES; then - PACKAGES="" - fi - ;; - setup) - if /cygdrive/c/setup.exe -q -P `echo "$PACKAGES" | tr ' ' ,`; then - PACKAGES="" - fi - ;; - esac - if [ ! -z "$PACKAGES" ]; then - sleep 90 - fi - tries=$(($tries - 1)) -done -if [ ! -z "$PACKAGES" ]; then - echo "Package installation failed." - exit 1 -fi - -if [ "${INSTALL_HARDENED_MALLOC}" = "yes" ]; then - (cd ${HOME} && - git clone https://github.com/GrapheneOS/hardened_malloc.git && - cd ${HOME}/hardened_malloc && - make -j2 && sudo cp out/libhardened_malloc.so /usr/lib/) -fi - -if [ ! -z "${INSTALL_OPENSSL}" ]; then - (cd ${HOME} && - git clone https://github.com/openssl/openssl.git && - cd ${HOME}/openssl && - git checkout ${INSTALL_OPENSSL} && - ./config no-threads shared ${SSLCONFOPTS} \ - --prefix=/opt/openssl && - make && sudo make install_sw) -fi - -if [ ! -z "${INSTALL_LIBRESSL}" ]; then - if [ "${INSTALL_LIBRESSL}" = "master" ]; then - (mkdir -p ${HOME}/libressl && cd ${HOME}/libressl && - git clone https://github.com/libressl-portable/portable.git && - cd ${HOME}/libressl/portable && - git checkout ${INSTALL_LIBRESSL} && - sh update.sh && sh autogen.sh && - ./configure --prefix=/opt/libressl && - make -j2 && sudo make install) - else - LIBRESSL_URLBASE=https://cdn.openbsd.org/pub/OpenBSD/LibreSSL - (cd ${HOME} && - wget ${LIBRESSL_URLBASE}/libressl-${INSTALL_LIBRESSL}.tar.gz && - tar xfz libressl-${INSTALL_LIBRESSL}.tar.gz && - cd libressl-${INSTALL_LIBRESSL} && - ./configure --prefix=/opt/libressl && make -j2 && sudo make install) - fi -fi - -if [ ! -z "${INSTALL_BORINGSSL}" ]; then - (cd ${HOME} && git clone https://boringssl.googlesource.com/boringssl && - cd ${HOME}/boringssl && mkdir build && cd build && - cmake -GNinja -DCMAKE_POSITION_INDEPENDENT_CODE=ON .. && ninja && - mkdir -p /opt/boringssl/lib && - cp ${HOME}/boringssl/build/crypto/libcrypto.a /opt/boringssl/lib && - cp -r ${HOME}/boringssl/include /opt/boringssl) -fi diff -ruN openssh-9.4p1/.github/workflows/c-cpp.yml openssh-9.4p1+x509-14.2.1/.github/workflows/c-cpp.yml --- openssh-9.4p1/.github/workflows/c-cpp.yml 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/.github/workflows/c-cpp.yml 1970-01-01 02:00:00.000000000 +0200 @@ -1,128 +0,0 @@ -name: C/C++ CI - -on: - push: - paths: [ '**.c', '**.h', '**.m4', '**.sh', '.github/**', '**/Makefile.in', 'configure.ac' ] - pull_request: - paths: [ '**.c', '**.h', '**.m4', '**.sh', '.github/**', '**/Makefile.in', 'configure.ac' ] - -jobs: - ci: - if: github.repository != 'openssh/openssh-portable-selfhosted' - strategy: - fail-fast: false - matrix: - # First we test all OSes in the default configuration. - target: - - ubuntu-20.04 - - ubuntu-22.04 - - macos-11 - - macos-12 - - macos-13 - - windows-2019 - - windows-2022 - config: [default] - # Then we include any extra configs we want to test for specific VMs. - # Valgrind slows things down quite a bit, so start them first. - include: - - { target: windows-2019, config: cygwin-release } - - { target: windows-2022, config: cygwin-release } - - { target: ubuntu-20.04, config: valgrind-1 } - - { target: ubuntu-20.04, config: valgrind-2 } - - { target: ubuntu-20.04, config: valgrind-3 } - - { target: ubuntu-20.04, config: valgrind-4 } - - { target: ubuntu-20.04, config: valgrind-5 } - - { target: ubuntu-20.04, config: valgrind-unit } - - { target: ubuntu-20.04, config: c89 } - - { target: ubuntu-20.04, config: clang-6.0 } - - { target: ubuntu-20.04, config: clang-8 } - - { target: ubuntu-20.04, config: clang-9 } - - { target: ubuntu-20.04, config: clang-10 } - - { target: ubuntu-20.04, config: clang-11 } - - { target: ubuntu-20.04, config: clang-12-Werror } - - { target: ubuntu-20.04, config: clang-sanitize-address } - - { target: ubuntu-20.04, config: clang-sanitize-undefined } - - { target: ubuntu-20.04, config: gcc-sanitize-address } - - { target: ubuntu-20.04, config: gcc-sanitize-undefined } - - { target: ubuntu-20.04, config: gcc-7 } - - { target: ubuntu-20.04, config: gcc-8 } - - { target: ubuntu-20.04, config: gcc-10 } - - { target: ubuntu-20.04, config: gcc-11-Werror } - - { target: ubuntu-20.04, config: pam } - - { target: ubuntu-20.04, config: kitchensink } - - { target: ubuntu-22.04, config: hardenedmalloc } - - { target: ubuntu-20.04, config: tcmalloc } - - { target: ubuntu-20.04, config: musl } - - { target: ubuntu-latest, config: boringssl } - - { target: ubuntu-latest, config: libressl-master } - - { target: ubuntu-latest, config: libressl-3.2.6 } - - { target: ubuntu-latest, config: libressl-3.3.6 } - - { target: ubuntu-latest, config: libressl-3.4.3 } - - { target: ubuntu-latest, config: libressl-3.5.3 } - - { target: ubuntu-latest, config: libressl-3.6.1 } - - { target: ubuntu-latest, config: libressl-3.7.2 } - - { target: ubuntu-latest, config: openssl-master } - - { target: ubuntu-latest, config: openssl-noec } - - { target: ubuntu-latest, config: openssl-1.1.1 } - - { target: ubuntu-latest, config: openssl-1.1.1k } - - { target: ubuntu-latest, config: openssl-1.1.1n } - - { target: ubuntu-latest, config: openssl-1.1.1q } - - { target: ubuntu-latest, config: openssl-1.1.1t } - - { target: ubuntu-latest, config: openssl-3.0.0 } - - { target: ubuntu-latest, config: openssl-3.0.7 } - - { target: ubuntu-latest, config: openssl-3.1.0 } - - { target: ubuntu-latest, config: openssl-1.1.1_stable } - - { target: ubuntu-latest, config: openssl-3.0 } # stable branch - - { target: ubuntu-22.04, config: pam } - - { target: ubuntu-22.04, config: krb5 } - - { target: ubuntu-22.04, config: heimdal } - - { target: ubuntu-22.04, config: libedit } - - { target: ubuntu-22.04, config: sk } - - { target: ubuntu-22.04, config: selinux } - - { target: ubuntu-22.04, config: kitchensink } - - { target: ubuntu-22.04, config: without-openssl } - - { target: macos-11, config: pam } - - { target: macos-12, config: pam } - - { target: macos-13, config: pam } - runs-on: ${{ matrix.target }} - steps: - - name: set cygwin git params - if: ${{ startsWith(matrix.target, 'windows') }} - run: git config --global core.autocrlf input - - name: install cygwin - if: ${{ startsWith(matrix.target, 'windows') }} - uses: cygwin/cygwin-install-action@master - - uses: actions/checkout@main - - name: setup CI system - run: sh ./.github/setup_ci.sh ${{ matrix.config }} - - name: autoreconf - run: sh -c autoreconf - - name: configure - run: sh ./.github/configure.sh ${{ matrix.config }} - - name: save config - uses: actions/upload-artifact@main - with: - name: ${{ matrix.target }}-${{ matrix.config }}-config - path: config.h - - name: make clean - run: make clean - - name: make - run: make -j2 - - name: make tests - run: sh ./.github/run_test.sh ${{ matrix.config }} - env: - TEST_SSH_UNSAFE_PERMISSIONS: 1 - TEST_SSH_HOSTBASED_AUTH: yes - - name: save logs - if: failure() - uses: actions/upload-artifact@main - with: - name: ${{ matrix.target }}-${{ matrix.config }}-logs - path: | - config.h - config.log - regress/*.log - regress/valgrind-out/ - regress/asan.log.* - regress/msan.log.* - regress/log/* diff -ruN openssh-9.4p1/.github/workflows/cifuzz.yml openssh-9.4p1+x509-14.2.1/.github/workflows/cifuzz.yml --- openssh-9.4p1/.github/workflows/cifuzz.yml 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/.github/workflows/cifuzz.yml 1970-01-01 02:00:00.000000000 +0200 @@ -1,32 +0,0 @@ -name: CIFuzz -on: - push: - paths: [ '**.c', '**.h', '**.m4', '**.sh', '.github/**', '**/Makefile.in', 'configure.ac' ] - pull_request: - paths: [ '**.c', '**.h', '**.m4', '**.sh', '.github/**', '**/Makefile.in', 'configure.ac' ] - -jobs: - Fuzzing: - if: github.repository != 'openssh/openssh-portable-selfhosted' - runs-on: ubuntu-latest - steps: - - name: Build Fuzzers - id: build - uses: google/oss-fuzz/infra/cifuzz/actions/build_fuzzers@master - with: - oss-fuzz-project-name: 'openssh' - dry-run: false - language: c++ - - name: Run Fuzzers - uses: google/oss-fuzz/infra/cifuzz/actions/run_fuzzers@master - with: - oss-fuzz-project-name: 'openssh' - fuzz-seconds: 600 - dry-run: false - language: c++ - - name: Upload Crash - uses: actions/upload-artifact@main - if: failure() && steps.build.outcome == 'success' - with: - name: artifacts - path: ./out/artifacts diff -ruN openssh-9.4p1/.github/workflows/selfhosted.yml openssh-9.4p1+x509-14.2.1/.github/workflows/selfhosted.yml --- openssh-9.4p1/.github/workflows/selfhosted.yml 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/.github/workflows/selfhosted.yml 1970-01-01 02:00:00.000000000 +0200 @@ -1,119 +0,0 @@ -name: C/C++ CI self-hosted - -on: - push: - paths: [ '**.c', '**.h', '**.m4', '**.sh', '.github/**', '**/Makefile.in', 'configure.ac' ] - -jobs: - selfhosted: - if: github.repository == 'openssh/openssh-portable-selfhosted' - runs-on: ${{ matrix.host }} - timeout-minutes: 600 - env: - HOST: ${{ matrix.host }} - TARGET_HOST: ${{ matrix.target }} - TARGET_CONFIG: ${{ matrix.config }} - strategy: - fail-fast: false - # We use a matrix in two parts: firstly all of the VMs are tested with the - # default config. "target" corresponds to a label associated with the - # worker. The default is an ephemeral VM running under libvirt. - matrix: - target: - - alpine - - centos7 - - debian-i386 - - dfly30 - - dfly48 - - dfly60 - - dfly62 - - dfly64 - - fbsd10 - - fbsd12 - - fbsd13 - - minix3 - - nbsd3 - - nbsd4 - - nbsd8 - - nbsd9 - - obsd51 - - obsd67 - - obsd69 - - obsd70 - - obsdsnap - - obsdsnap-i386 - - openindiana - - sol10 - - sol11 - config: - - default - host: - - libvirt - include: - # Then we include extra libvirt test configs. - - { target: aix51, config: default, host: libvirt } - - { target: centos7, config: pam, host: libvirt } - - { target: debian-i386, config: pam, host: libvirt } - - { target: dfly30, config: without-openssl, host: libvirt} - - { target: dfly48, config: pam ,host: libvirt } - - { target: dfly58, config: pam, host: libvirt } - - { target: dfly60, config: pam, host: libvirt } - - { target: dfly62, config: pam, host: libvirt } - - { target: fbsd10, config: pam, host: libvirt } - - { target: fbsd12, config: pam, host: libvirt } - - { target: fbsd13, config: pam, host: libvirt } - - { target: nbsd8, config: pam, host: libvirt } - - { target: nbsd9, config: pam, host: libvirt } - - { target: openindiana, config: pam, host: libvirt } - - { target: sol10, config: pam, host: libvirt } - - { target: sol11, config: pam-krb5, host: libvirt } - - { target: sol11, config: sol64, host: libvirt } - # VMs with persistent disks that have their own runner. - - { target: win10, config: default, host: win10 } - - { target: win10, config: cygwin-release, host: win10 } - # Physical hosts, with either native runners or remote via ssh. - - { target: ARM, config: default, host: ARM } - - { target: ARM64, config: default, host: ARM64 } - - { target: ARM64, config: pam, host: ARM64 } - - { target: debian-riscv64, config: default, host: debian-riscv64 } - - { target: openwrt-mips, config: default, host: openwrt-mips } - - { target: openwrt-mipsel, config: default, host: openwrt-mipsel } - steps: - - name: shutdown VM if running - run: vmshutdown - working-directory: ${{ runner.temp }} - - uses: actions/checkout@main - - name: autoreconf - run: autoreconf - - name: startup VM - run: vmstartup - working-directory: ${{ runner.temp }} - - name: configure - run: vmrun ./.github/configure.sh ${{ matrix.config }} - - name: save config - uses: actions/upload-artifact@main - with: - name: ${{ matrix.target }}-${{ matrix.config }}-config - path: config.h - - name: make clean - run: vmrun make clean - - name: make - run: vmrun make - - name: make tests - run: vmrun ./.github/run_test.sh ${{ matrix.config }} - timeout-minutes: 600 - - name: save logs - if: failure() - uses: actions/upload-artifact@main - with: - name: ${{ matrix.target }}-${{ matrix.config }}-logs - path: | - config.h - config.log - regress/*.log - regress/log/* - regress/valgrind-out/ - - name: shutdown VM - if: always() - run: vmshutdown - working-directory: ${{ runner.temp }} diff -ruN openssh-9.4p1/.github/workflows/upstream.yml openssh-9.4p1+x509-14.2.1/.github/workflows/upstream.yml --- openssh-9.4p1/.github/workflows/upstream.yml 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/.github/workflows/upstream.yml 1970-01-01 02:00:00.000000000 +0200 @@ -1,53 +0,0 @@ -name: Upstream self-hosted - -on: - push: - branches: [ master ] - paths: [ '**.c', '**.h', '.github/**' ] - -jobs: - selfhosted: - if: github.repository == 'openssh/openssh-portable-selfhosted' - runs-on: 'libvirt' - env: - HOST: 'libvirt' - TARGET_HOST: ${{ matrix.target }} - TARGET_CONFIG: ${{ matrix.config }} - strategy: - fail-fast: false - matrix: - target: [ obsdsnap, obsdsnap-i386 ] - config: [ default, without-openssl, ubsan ] - steps: - - name: shutdown VM if running - run: vmshutdown - working-directory: ${{ runner.temp }} - - uses: actions/checkout@main - - name: startup VM - run: vmstartup - working-directory: ${{ runner.temp }} - - name: update source - run: vmrun "cd /usr/src && cvs up -dPA usr.bin/ssh regress/usr.bin/ssh" - - name: make clean - run: vmrun "cd /usr/src/usr.bin/ssh && make obj && make clean && cd /usr/src/regress/usr.bin/ssh && make obj && make clean && sudo chmod -R g-w /usr/src /usr/obj" - - name: make - run: vmrun "cd /usr/src/usr.bin/ssh && case ${{ matrix.config }} in without-openssl) make OPENSSL=no;; ubsan) make DEBUG='-fsanitize-minimal-runtime -fsanitize=undefined';; *) make; esac" - - name: make install - run: vmrun "cd /usr/src/usr.bin/ssh && sudo make install" - - name: make tests` - run: vmrun "cd /usr/src/regress/usr.bin/ssh && case ${{ matrix.config }} in without-openssl) make OPENSSL=no;; ubsan) make DEBUG='-fsanitize-minimal-runtime -fsanitize=undefined';; *) make; esac" - env: - SUDO: sudo - timeout-minutes: 300 - - name: save logs - if: failure() - uses: actions/upload-artifact@main - with: - name: ${{ matrix.target }}-${{ matrix.config }}-logs - path: | - /usr/obj/regress/usr.bin/ssh/obj/*.log - /usr/obj/regress/usr.bin/ssh/obj/log/* - - name: shutdown VM - if: always() - run: vmshutdown - working-directory: ${{ runner.temp }} diff -ruN openssh-9.4p1/.gitignore openssh-9.4p1+x509-14.2.1/.gitignore --- openssh-9.4p1/.gitignore 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/.gitignore 1970-01-01 02:00:00.000000000 +0200 @@ -1,36 +0,0 @@ -Makefile -buildpkg.sh -config.h -config.h.in -config.h.in~ -config.log -config.status -configure -aclocal.m4 -openbsd-compat/Makefile -openbsd-compat/regress/Makefile -openssh.xml -opensshd.init -survey.sh -**/*.0 -**/*.o -**/*.lo -**/*.so -**/*.out -**/*.a -autom4te.cache/ -scp -sftp -sftp-server -ssh -ssh-add -ssh-agent -ssh-keygen -ssh-keyscan -ssh-keysign -ssh-pkcs11-helper -ssh-sk-helper -sshd -!regress/misc/fuzz-harness/Makefile -!regress/unittests/sshsig/Makefile -tags diff -ruN openssh-9.4p1/gss-genr.c openssh-9.4p1+x509-14.2.1/gss-genr.c --- openssh-9.4p1/gss-genr.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/gss-genr.c 2023-08-20 10:07:01.000000000 +0300 @@ -1,5 +1,4 @@ /* $OpenBSD: gss-genr.c,v 1.28 2021/01/27 10:05:28 djm Exp $ */ - /* * Copyright (c) 2001-2007 Simon Wilkinson. All rights reserved. * @@ -38,7 +37,6 @@ #include #include "xmalloc.h" -#include "ssherr.h" #include "sshbuf.h" #include "log.h" #include "ssh2.h" @@ -278,7 +276,7 @@ gss_OID_desc spnego_oid = {6, (void *)"\x2B\x06\x01\x05\x05\x02"}; /* RFC 4462 says we MUST NOT do SPNEGO */ - if (oid->length == spnego_oid.length && + if (oid->length == spnego_oid.length && (memcmp(oid->elements, spnego_oid.elements, oid->length) == 0)) return 0; /* false */ @@ -286,7 +284,7 @@ ssh_gssapi_set_oid(*ctx, oid); major = ssh_gssapi_import_name(*ctx, host); if (!GSS_ERROR(major)) { - major = ssh_gssapi_init_ctx(*ctx, 0, GSS_C_NO_BUFFER, &token, + major = ssh_gssapi_init_ctx(*ctx, 0, GSS_C_NO_BUFFER, &token, NULL); gss_release_buffer(&minor, &token); if ((*ctx)->context != GSS_C_NO_CONTEXT) @@ -294,7 +292,7 @@ GSS_C_NO_BUFFER); } - if (GSS_ERROR(major)) + if (GSS_ERROR(major)) ssh_gssapi_delete_ctx(ctx); return (!GSS_ERROR(major)); diff -ruN openssh-9.4p1/gss-serv.c openssh-9.4p1+x509-14.2.1/gss-serv.c --- openssh-9.4p1/gss-serv.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/gss-serv.c 2023-08-20 10:07:01.000000000 +0300 @@ -36,7 +36,6 @@ #include "openbsd-compat/sys-queue.h" #include "xmalloc.h" -#include "sshkey.h" #include "hostfile.h" #include "auth.h" #include "log.h" @@ -105,7 +104,7 @@ gss_create_empty_oid_set(&status, &oidset); gss_add_oid_set_member(&status, ctx->oid, &oidset); - if (gethostname(lname, HOST_NAME_MAX)) { + if (gethostname(lname, sizeof(lname)) == -1) { gss_release_oid_set(&status, &oidset); return (-1); } @@ -334,7 +333,7 @@ if (gssapi_client.mech && gssapi_client.mech->storecreds) { (*gssapi_client.mech->storecreds)(&gssapi_client); } else - debug("ssh_gssapi_storecreds: Not a GSSAPI mechanism"); + debug_f("Not a GSSAPI mechanism"); } /* This allows GSSAPI methods to do things to the child's environment based @@ -378,7 +377,7 @@ return 0; } else - debug("ssh_gssapi_userok: Unknown GSSAPI mechanism"); + debug_f("unknown GSSAPI mechanism"); return (0); } diff -ruN openssh-9.4p1/gss-serv-krb5.c openssh-9.4p1+x509-14.2.1/gss-serv-krb5.c --- openssh-9.4p1/gss-serv-krb5.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/gss-serv-krb5.c 2023-08-20 10:07:01.000000000 +0300 @@ -35,7 +35,6 @@ #include #include "xmalloc.h" -#include "sshkey.h" #include "hostfile.h" #include "auth.h" #include "log.h" diff -ruN openssh-9.4p1/hash.c openssh-9.4p1+x509-14.2.1/hash.c --- openssh-9.4p1/hash.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/hash.c 2023-08-20 10:07:01.000000000 +0300 @@ -2,30 +2,29 @@ /* * Public domain. Author: Christian Weisgerber * API compatible reimplementation of function from nacl + * + * Adapted for PKIX-SSH by Roumen Petrov. */ -#include "includes.h" - #include "crypto_api.h" -#include - -#ifdef WITH_OPENSSL -#include +#if defined(HAVE_EVP_SHA512) /* OpenSSL 0.9.8+ */ +# include int crypto_hash_sha512(unsigned char *out, const unsigned char *in, unsigned long long inlen) { - if (!EVP_Digest(in, inlen, out, NULL, EVP_sha512(), NULL)) return -1; return 0; } -#else +#elif defined(HAVE_SHA512UPDATE) # ifdef HAVE_SHA2_H # include +# else +# include "openbsd-compat/sha2.h" # endif int @@ -40,4 +39,81 @@ SHA512Final(out, &ctx); return 0; } -#endif /* WITH_OPENSSL */ + +#else + +/* Copied from nacl-20110221/crypto_hash/sha512/ref/hash.c */ + +/* +20080913 +D. J. Bernstein +Public domain. +*/ + +int crypto_hashblocks_sha512(unsigned char *, const unsigned char *, + unsigned long long); + +#define blocks crypto_hashblocks_sha512 + +static const unsigned char iv[64] = { + 0x6a,0x09,0xe6,0x67,0xf3,0xbc,0xc9,0x08, + 0xbb,0x67,0xae,0x85,0x84,0xca,0xa7,0x3b, + 0x3c,0x6e,0xf3,0x72,0xfe,0x94,0xf8,0x2b, + 0xa5,0x4f,0xf5,0x3a,0x5f,0x1d,0x36,0xf1, + 0x51,0x0e,0x52,0x7f,0xad,0xe6,0x82,0xd1, + 0x9b,0x05,0x68,0x8c,0x2b,0x3e,0x6c,0x1f, + 0x1f,0x83,0xd9,0xab,0xfb,0x41,0xbd,0x6b, + 0x5b,0xe0,0xcd,0x19,0x13,0x7e,0x21,0x79 +} ; + +typedef unsigned long long uint64; + +int crypto_hash_sha512(unsigned char *out,const unsigned char *in,unsigned long long inlen) +{ + unsigned char h[64]; + unsigned char padded[256]; + unsigned int i; + unsigned long long bytes = inlen; + + for (i = 0;i < 64;++i) h[i] = iv[i]; + + blocks(h,in,inlen); + in += inlen; + inlen &= 127; + in -= inlen; + + for (i = 0;i < inlen;++i) padded[i] = in[i]; + padded[inlen] = 0x80; + + if (inlen < 112) { + for (i = inlen + 1;i < 119;++i) padded[i] = 0; + padded[119] = bytes >> 61; + padded[120] = bytes >> 53; + padded[121] = bytes >> 45; + padded[122] = bytes >> 37; + padded[123] = bytes >> 29; + padded[124] = bytes >> 21; + padded[125] = bytes >> 13; + padded[126] = bytes >> 5; + padded[127] = bytes << 3; + blocks(h,padded,128); + } else { + for (i = inlen + 1;i < 247;++i) padded[i] = 0; + padded[247] = bytes >> 61; + padded[248] = bytes >> 53; + padded[249] = bytes >> 45; + padded[250] = bytes >> 37; + padded[251] = bytes >> 29; + padded[252] = bytes >> 21; + padded[253] = bytes >> 13; + padded[254] = bytes >> 5; + padded[255] = bytes << 3; + blocks(h,padded,256); + } + + for (i = 0;i < 64;++i) out[i] = h[i]; + + return 0; +} + +#endif diff -ruN openssh-9.4p1/hmac.c openssh-9.4p1+x509-14.2.1/hmac.c --- openssh-9.4p1/hmac.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/hmac.c 2023-08-20 10:07:01.000000000 +0300 @@ -127,10 +127,8 @@ ssh_digest_free(ctx->ictx); ssh_digest_free(ctx->octx); ssh_digest_free(ctx->digest); - if (ctx->buf) { - explicit_bzero(ctx->buf, ctx->buf_len); - free(ctx->buf); - } + if (ctx->buf) + freezero(ctx->buf, ctx->buf_len); freezero(ctx, sizeof(*ctx)); } } diff -ruN openssh-9.4p1/hostfile.c openssh-9.4p1+x509-14.2.1/hostfile.c --- openssh-9.4p1/hostfile.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/hostfile.c 2023-08-20 10:07:01.000000000 +0300 @@ -14,6 +14,7 @@ * * Copyright (c) 1999, 2000 Markus Friedl. All rights reserved. * Copyright (c) 1999 Niels Provos. All rights reserved. + * Copyright (c) 2002-2023 Roumen Petrov. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -61,7 +62,17 @@ #include "ssherr.h" #include "digest.h" #include "hmac.h" -#include "sshbuf.h" +#include "ssh-x509.h" + +#undef CHPUT +#undef CHNL +#define CHPUT(v) ((int)(unsigned char)v) +#define CHNL CHPUT('\n') + +struct hostkeys { + struct hostkey_entry *entries; + u_int num_entries; +}; /* XXX hmac is too easy to dictionary attack; use bcrypt? */ @@ -73,24 +84,24 @@ int ret; if (l < sizeof(HASH_MAGIC) - 1) { - debug2("extract_salt: string too short"); + debug2_f("string too short"); return (-1); } if (strncmp(s, HASH_MAGIC, sizeof(HASH_MAGIC) - 1) != 0) { - debug2("extract_salt: invalid magic identifier"); + debug2_f("invalid magic identifier"); return (-1); } s += sizeof(HASH_MAGIC) - 1; l -= sizeof(HASH_MAGIC) - 1; if ((p = memchr(s, HASH_DELIM, l)) == NULL) { - debug2("extract_salt: missing salt termination character"); + debug2_f("missing salt termination character"); return (-1); } b64len = p - s; /* Sanity check */ if (b64len == 0 || b64len > 1024) { - debug2("extract_salt: bad encoded salt length %u", b64len); + debug2_f("bad encoded salt length %u", b64len); return (-1); } b64salt = xmalloc(1 + b64len); @@ -100,11 +111,11 @@ ret = __b64_pton(b64salt, salt, salt_len); free(b64salt); if (ret == -1) { - debug2("extract_salt: salt decode error"); + debug2_f("salt decode error"); return (-1); } if (ret != (int)ssh_hmac_bytes(SSH_DIGEST_SHA1)) { - debug2("extract_salt: expected salt len %zd, got %d", + debug2_f("expected salt len %zu, got %d", ssh_hmac_bytes(SSH_DIGEST_SHA1), ret); return (-1); } @@ -143,6 +154,7 @@ if (__b64_ntop(salt, len, uu_salt, sizeof(uu_salt)) == -1 || __b64_ntop(result, len, uu_result, sizeof(uu_result)) == -1) fatal_f("__b64_ntop failed"); + xasprintf(&encoded, "%s%s%c%s", HASH_MAGIC, uu_salt, HASH_DELIM, uu_result); @@ -172,8 +184,15 @@ /* Return results. */ *cpp = cp; - if (bitsp != NULL) - *bitsp = sshkey_size(ret); + if (bitsp != NULL) { + if ((*bitsp = sshkey_size(ret)) <= 0) { + /* Note key may contain only X.509 distinguished name. + * Return 1 in this case. */ + if (sshkey_is_x509(ret)) + return 1; + return 0; + } + } return 1; } @@ -276,15 +295,15 @@ if ((r = hostkeys_foreach_file(path, f, record_hostkey, &ctx, host, NULL, HKF_WANT_MATCH|HKF_WANT_PARSE_KEY, note)) != 0) { if (r != SSH_ERR_SYSTEM_ERROR && errno != ENOENT) - debug_fr(r, "hostkeys_foreach failed for %s", path); + error_fr(r, "hostkeys_foreach failed for %s", path); } if (ctx.num_loaded != 0) debug3_f("loaded %lu keys from %s", ctx.num_loaded, host); } void -load_hostkeys(struct hostkeys *hostkeys, const char *host, const char *path, - u_int note) +load_hostkeys(struct hostkeys *hostkeys, const char *host, + const char *path, u_int note) { FILE *f; @@ -323,7 +342,7 @@ continue; if (sshkey_equal_public(k, hostkeys->entries[i].key)) return -1; - if (is_cert && k != NULL && + if (is_cert && sshkey_equal_public(k->cert->signature_key, hostkeys->entries[i].key)) return -1; @@ -331,6 +350,14 @@ return 0; } +int/*bool*/ +hostkey_match(const struct sshkey *key, const struct sshkey *found) { + if (sshkey_is_x509(key) || sshkey_is_x509(found)) + return(sshkey_equal_public(key, found)); + + return(sshkey_equal(key, found)); +} + /* * Match keys against a specified key, or look one up by key type. * @@ -347,8 +374,8 @@ * Finally, check any found key is not revoked. */ static HostStatus -check_hostkeys_by_key_or_type(struct hostkeys *hostkeys, - struct sshkey *k, int keytype, int nid, const struct hostkey_entry **found) +check_hostkeys_by_key_or_types(struct hostkeys *hostkeys, + struct sshkey *k, int keytype, int subtype, const struct hostkey_entry **found) { u_int i; HostStatus end_return = HOST_NEW; @@ -357,6 +384,8 @@ if (found != NULL) *found = NULL; + if (k != NULL) + subtype = k->ecdsa_nid; for (i = 0; i < hostkeys->num_entries; i++) { if (hostkeys->entries[i].marker != want_marker) @@ -364,9 +393,8 @@ if (k == NULL) { if (hostkeys->entries[i].key->type != keytype) continue; - if (nid != -1 && - sshkey_type_plain(keytype) == KEY_ECDSA && - hostkeys->entries[i].key->ecdsa_nid != nid) + /* NOTE ecdsa_nid is -1 for non ECC keys */ + if (subtype != -1 && subtype != hostkeys->entries[i].key->ecdsa_nid) continue; end_return = HOST_FOUND; if (found != NULL) @@ -384,7 +412,7 @@ break; } } else { - if (sshkey_equal(k, hostkeys->entries[i].key)) { + if (hostkey_match(k, hostkeys->entries[i].key)) { end_return = HOST_OK; if (found != NULL) *found = hostkeys->entries + i; @@ -396,7 +424,7 @@ *found = hostkeys->entries + i; } } - if (check_key_not_revoked(hostkeys, k) != 0) { + if (k != NULL && check_key_not_revoked(hostkeys, k) != 0) { end_return = HOST_REVOKED; if (found != NULL) *found = NULL; @@ -410,14 +438,14 @@ { if (key == NULL) fatal("no key to look up"); - return check_hostkeys_by_key_or_type(hostkeys, key, 0, -1, found); + return check_hostkeys_by_key_or_types(hostkeys, key, 0, -1, found); } int -lookup_key_in_hostkeys_by_type(struct hostkeys *hostkeys, int keytype, int nid, +lookup_key_in_hostkeys_by_types(struct hostkeys *hostkeys, int keytype, int subtype, const struct hostkey_entry **found) { - return (check_hostkeys_by_key_or_type(hostkeys, NULL, keytype, nid, + return (check_hostkeys_by_key_or_types(hostkeys, NULL, keytype, subtype, found) == HOST_FOUND); } @@ -450,18 +478,25 @@ return 0; } fprintf(f, "%s ", hashed_host); + free(hashed_host); } else if (ip != NULL) fprintf(f, "%s,%s ", lhost, ip); else { fprintf(f, "%s ", lhost); } - free(hashed_host); free(lhost); - if ((r = sshkey_write(key, f)) == 0) + if (sshkey_is_x509(key)) { + /* key_write prints x509 certificate in blob format :-( */ + r = Xkey_write_subject(NULL, key, f) + ? SSH_ERR_SUCCESS + : SSH_ERR_INTERNAL_ERROR; + } else + r = sshkey_write(key, f); + if (r == 0) success = 1; else error_fr(r, "sshkey_write"); - fputc('\n', f); + fputc(CHNL, f); /* If hashing is enabled, the IP address needs to go on its own line */ if (success && store_hash && ip != NULL) success = write_host_entry(f, ip, NULL, key, 1); @@ -477,24 +512,27 @@ { char *dotsshdir = NULL, *p; size_t len; - struct stat st; if ((p = strrchr(filename, '/')) == NULL) return; + len = p - filename; + dotsshdir = tilde_expand_filename("~/" _PATH_SSH_USER_DIR, getuid()); if (strlen(dotsshdir) > len || strncmp(filename, dotsshdir, len) != 0) goto out; /* not ~/.ssh prefixed */ - if (stat(dotsshdir, &st) == 0) +{ struct stat st; + if (stat(dotsshdir, &st) != -1) goto out; /* dir already exists */ - else if (errno != ENOENT) - error("Could not stat %s: %s", dotsshdir, strerror(errno)); +} + if (errno != ENOENT) + error("could not stat %s: %s", dotsshdir, strerror(errno)); else { #ifdef WITH_SELINUX ssh_selinux_setfscreatecon(dotsshdir); #endif if (mkdir(dotsshdir, 0700) == -1) - error("Could not create directory '%.200s' (%s).", + error("could not create directory '%s' (%s).", dotsshdir, strerror(errno)); else if (notify) logit("Created directory '%s'.", dotsshdir); @@ -520,13 +558,18 @@ if (key == NULL) return 1; /* XXX ? */ hostfile_create_user_ssh_dir(filename, 0); - f = fopen(filename, "a+"); + + /* try to find new-line at end of file if exist */ + f = fopen(filename, "r"); + if (f != NULL) { + addnl = (fseek(f, -1L, SEEK_END) != -1) && (fgetc(f) != CHNL); + fclose(f); + } + + f = fopen(filename, "a"); if (!f) return 0; - /* Make sure we have a terminating newline. */ - if (fseek(f, -1L, SEEK_END) == 0 && fgetc(f) != '\n') - addnl = 1; - if (fseek(f, 0L, SEEK_END) != 0 || (addnl && fputc('\n', f) != '\n')) { + if (addnl &&(fputc(CHNL, f) != CHNL)) { error("Failed to add terminating newline to %s: %s", filename, strerror(errno)); fclose(f); @@ -539,7 +582,6 @@ struct host_delete_ctx { FILE *out; - int quiet; const char *host, *ip; u_int *match_keys; /* mask of HKF_MATCH_* for this key */ struct sshkey * const *keys; @@ -551,7 +593,6 @@ host_delete(struct hostkey_foreach_line *l, void *_ctx) { struct host_delete_ctx *ctx = (struct host_delete_ctx *)_ctx; - int loglevel = ctx->quiet ? SYSLOG_LEVEL_DEBUG1 : SYSLOG_LEVEL_VERBOSE; size_t i; /* Don't remove CA and revocation lines */ @@ -575,16 +616,14 @@ * Hostname matches and has no CA/revoke marker, delete it * by *not* writing the line to ctx->out. */ - do_log2(loglevel, "%s%s%s:%ld: Removed %s key for host %s", - ctx->quiet ? __func__ : "", ctx->quiet ? ": " : "", - l->path, l->linenum, sshkey_type(l->key), ctx->host); + verbose("Removed %s key for host %s - %s:%ld", + sshkey_type(l->key), ctx->host, l->path, l->linenum); ctx->modified = 1; return 0; } /* Retain non-matching hosts and invalid lines when deleting */ if (l->status == HKF_STATUS_INVALID) { - do_log2(loglevel, "%s%s%s:%ld: invalid known_hosts entry", - ctx->quiet ? __func__ : "", ctx->quiet ? ": " : "", + verbose("Invalid known_hosts entry - %s:%ld", l->path, l->linenum); } fprintf(ctx->out, "%s\n", l->line); @@ -593,10 +632,9 @@ int hostfile_replace_entries(const char *filename, const char *host, const char *ip, - struct sshkey **keys, size_t nkeys, int store_hash, int quiet, int hash_alg) + struct sshkey **keys, size_t nkeys, int store_hash, int hash_alg) { int r, fd, oerrno = 0; - int loglevel = quiet ? SYSLOG_LEVEL_DEBUG1 : SYSLOG_LEVEL_VERBOSE; struct host_delete_ctx ctx; char *fp, *temp = NULL, *back = NULL; const char *what; @@ -609,7 +647,6 @@ memset(&ctx, 0, sizeof(ctx)); ctx.host = host; ctx.ip = ip; - ctx.quiet = quiet; if ((ctx.match_keys = calloc(nkeys, sizeof(*ctx.match_keys))) == NULL) return SSH_ERR_ALLOC_FAIL; @@ -620,8 +657,8 @@ /* * Prepare temporary file for in-place deletion. */ - if ((r = asprintf(&temp, "%s.XXXXXXXXXXX", filename)) == -1 || - (r = asprintf(&back, "%s.old", filename)) == -1) { + if ((r = asprintf(&temp, "%s.XXXXXXXXXX", filename)) < 0 || + (r = asprintf(&back, "%s.old", filename)) < 0) { r = SSH_ERR_ALLOC_FAIL; goto fail; } @@ -653,8 +690,11 @@ for (i = 0; i < nkeys; i++) { if (keys[i] == NULL || (want & ctx.match_keys[i]) == want) continue; - if ((fp = sshkey_fingerprint(keys[i], hash_alg, - SSH_FP_DEFAULT)) == NULL) { + if (sshkey_is_x509(keys[i])) + fp = x509key_subject(keys[i]); + else + fp = sshkey_fingerprint(keys[i], hash_alg, SSH_FP_DEFAULT); + if (fp == NULL) { r = SSH_ERR_ALLOC_FAIL; goto fail; } @@ -682,8 +722,7 @@ goto fail; } } - do_log2(loglevel, "%s%s%s for %s%s%s to %s: %s %s", - quiet ? __func__ : "", quiet ? ": " : "", what, + verbose("%s for %s%s%s to %s: %s %s", what, host, ip == NULL ? "" : ",", ip == NULL ? "" : ip, filename, sshkey_ssh_name(keys[i]), fp); free(fp); @@ -700,9 +739,9 @@ r = SSH_ERR_SYSTEM_ERROR; goto fail; } - if (link(filename, back) == -1) { + if (xrename(filename, back) == -1) { oerrno = errno; - error_f("link %.100s to %.100s: %s", filename, + error_f("xrename %.100s to %.100s: %s", filename, back, strerror(errno)); r = SSH_ERR_SYSTEM_ERROR; goto fail; @@ -740,7 +779,7 @@ match_maybe_hashed(const char *host, const char *names, int *was_hashed) { int hashed = *names == HASH_DELIM, ret; - char *hashed_host = NULL; + char *hashed_host; size_t nlen = strlen(names); if (was_hashed != NULL) @@ -801,7 +840,7 @@ } if ((lineinfo.marker = check_markers(&cp)) == MRK_ERROR) { - verbose_f("invalid marker at %s:%lu", path, linenum); + debug_f("invalid marker at %s:%lu", path, linenum); if ((options & HKF_WANT_MATCH) == 0) goto bad; continue; @@ -931,7 +970,7 @@ const char *host, const char *ip, u_int options, u_int note) { FILE *f; - int r, oerrno; + int r; if ((f = fopen(path, "r")) == NULL) return SSH_ERR_SYSTEM_ERROR; @@ -939,8 +978,9 @@ debug3_f("reading file \"%s\"", path); r = hostkeys_foreach_file(path, f, callback, ctx, host, ip, options, note); - oerrno = errno; +{ int oerrno = errno; fclose(f); errno = oerrno; +} return r; } diff -ruN openssh-9.4p1/hostfile.h openssh-9.4p1+x509-14.2.1/hostfile.h --- openssh-9.4p1/hostfile.h 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/hostfile.h 2023-08-20 10:07:00.000000000 +0300 @@ -30,21 +30,21 @@ HostkeyMarker marker; u_int note; /* caller-specific note/flag */ }; -struct hostkeys { - struct hostkey_entry *entries; - u_int num_entries; -}; +struct hostkeys; struct hostkeys *init_hostkeys(void); void load_hostkeys(struct hostkeys *, const char *, const char *, u_int); void load_hostkeys_file(struct hostkeys *, const char *, - const char *, FILE *, u_int note); + const char *, FILE *, u_int); void free_hostkeys(struct hostkeys *); +int/*bool*/ +hostkey_match(const struct sshkey *key, const struct sshkey *found); + HostStatus check_key_in_hostkeys(struct hostkeys *, struct sshkey *, const struct hostkey_entry **); -int lookup_key_in_hostkeys_by_type(struct hostkeys *, int, int, +int lookup_key_in_hostkeys_by_types(struct hostkeys *, int /*keytype*/, int /*subtype*/, const struct hostkey_entry **); int lookup_marker_in_hostkeys(struct hostkeys *, int); @@ -54,7 +54,7 @@ int hostfile_replace_entries(const char *filename, const char *host, const char *ip, struct sshkey **keys, size_t nkeys, - int store_hash, int quiet, int hash_alg); + int store_hash, int hash_alg); #define HASH_MAGIC "|1|" #define HASH_DELIM '|' @@ -84,7 +84,7 @@ /* XXX HKF_MATCH_KEY_TYPE? */ /* - * The callback function receives this as an argument for each matching + * The callback function receives this as an argument for each matching * hostkey line. The callback may "steal" the 'key' field by setting it to NULL. * If a parse error occurred, then "hosts" and subsequent options may be NULL. */ diff -ruN openssh-9.4p1/includes.h openssh-9.4p1+x509-14.2.1/includes.h --- openssh-9.4p1/includes.h 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/includes.h 2023-08-20 10:07:00.000000000 +0300 @@ -23,6 +23,7 @@ #endif #include +#include #include /* For CMSG_* */ #ifdef HAVE_LIMITS_H @@ -93,7 +94,7 @@ # include /* For MIN, MAX, etc */ #endif #ifdef HAVE_SYS_TIME_H -# include /* for timespeccmp if present */ +# include /* for struct timeval if present */ #endif #ifdef HAVE_SYS_MMAN_H #include /* for MAP_ANONYMOUS */ @@ -165,6 +166,12 @@ #ifdef WITH_OPENSSL #include /* For OPENSSL_VERSION_NUMBER */ +#include /* For all OpenSSL defines and types */ +#endif + +#ifndef WITH_OPENSSL +/* PKCS#11 required OpenSSL */ +# undef ENABLE_PKCS11 #endif #include "defines.h" diff -ruN openssh-9.4p1/INSTALL openssh-9.4p1+x509-14.2.1/INSTALL --- openssh-9.4p1/INSTALL 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/INSTALL 2023-08-20 10:07:00.000000000 +0300 @@ -1,81 +1,93 @@ 1. Prerequisites ---------------- -A C compiler. Any C89 or better compiler that supports variadic macros -should work. Where supported, configure will attempt to enable the -compiler's run-time integrity checking options. Some notes about -specific compilers: +A C compiler. Any C99 or better compiler should work. Where supported, +configure will attempt to enable the compiler's run-time integrity checking +options. Some notes about specific compilers: - clang: -ftrapv and -sanitize=integer require the compiler-rt runtime (CC=clang LDFLAGS=--rtlib=compiler-rt ./configure) +Remark: If compiler is C89 and GCC compatible configure script may set +language standard to gnu99 (-std=gnu99). -To support Privilege Separation (which is now required) you will need -to create the user, group and directory used by sshd for privilege -separation. See README.privsep for details. +You will need working installations of libcrypto (OpenSSL +or compatible) +libcrypto (OpenSSL or compatible) +OpenSSL https://www.openssl.org/ ; or +LibreSSL http://www.libressl.org/ + +libcrypto should be compiled as a position-independent library +(i.e. with -fPIC) otherwise PKIX-SSH will not be able to link with it. +If you must use a non-position-independent libcrypto, then you may need +to configure PKIX-SSH --without-pie. + +NB. If you operating system supports /dev/*random, you should configure +libcrypto to use it. PKIX-SSH relies on libcrypto's +direct support of /dev/*random, or failing that, either prngd or egd The remaining items are optional. +ZLIB: + A working installation of zlib: Zlib 1.1.4 or 1.2.1.2 or greater (earlier 1.2.x versions have problems): https://zlib.net/ -libcrypto from either of LibreSSL or OpenSSL. Building without libcrypto -is supported but severely restricts the available ciphers and algorithms. - - LibreSSL (https://www.libressl.org/) 3.1.0 or greater - - OpenSSL (https://www.openssl.org) 1.1.1 or greater - -LibreSSL/OpenSSL should be compiled as a position-independent library -(i.e. -fPIC, eg by configuring OpenSSL as "./config [options] -fPIC" -or LibreSSL as "CFLAGS=-fPIC ./configure") otherwise OpenSSH will not -be able to link with it. If you must use a non-position-independent -libcrypto, then you may need to configure OpenSSH --without-pie. - -If you build either from source, running the OpenSSL self-test ("make -tests") or the LibreSSL equivalent ("make check") and ensuring that all -tests pass is strongly recommended. - -NB. If you operating system supports /dev/random, you should configure -libcrypto (LibreSSL/OpenSSL) to use it. OpenSSH relies on libcrypto's -direct support of /dev/random, or failing that, either prngd or egd. - PRNGD: If your system lacks kernel-based random collection, the use of Lutz -Jaenicke's PRNGd is recommended. It requires that libcrypto be configured -to support it. +Jaenicke's PRNGd is recommended. http://prngd.sourceforge.net/ EGD: The Entropy Gathering Daemon (EGD) supports the same interface as prngd. -It also supported only if libcrypto is configured to support it. http://egd.sourceforge.net/ PAM: -OpenSSH can utilise Pluggable Authentication Modules (PAM) if your +PKIX-SSH can utilise Pluggable Authentication Modules (PAM) if your system supports it. PAM is standard most Linux distributions, Solaris, HP-UX 11, AIX >= 5.2, FreeBSD, NetBSD and Mac OS X. Information about the various PAM implementations are available: -Solaris PAM: http://www.sun.com/software/solaris/pam/ -Linux PAM: http://www.kernel.org/pub/linux/libs/pam/ -OpenPAM: http://www.openpam.org/ +Solaris PAM: https://web.archive.org/web/20061230054046/http://www.sun.com:80/software/solaris/pam/ +Linux PAM: https://www.kernel.org/pub/linux/libs/pam/ +OpenPAM: https://www.openpam.org/ + +ASKPASS: + +You could use a number of X Window "dialog"-like programs for +passphrase requester. For instance in sub-directory contrib you could +found born shell script that wraps KDialog. + +Also you may use KDE alternative which stores key password in KWallet: +ksshaskpass: https://github.com/KDE/ksshaskpass -If you wish to build the GNOME passphrase requester, you will need the GNOME -libraries and headers. +Git projects distributes Tcl/Tk based alternative: git-gui--askpass. +Mirror: https://github.com/git/git -GNOME: -http://www.gnome.org/ +Seahorse GNOME project distributes another alternative: seahorse-ssh-askpass. +Mirror: https://github.com/GNOME/seahorse -Alternatively, Jim Knoble has written an excellent X11 -passphrase requester. This is maintained separately at: +If you wish to build the GNOME or GTK+ passphrase requester, you will need +the GNOME or GTK+2 or GTK+3 libraries and headers. + +GNOME: https://www.gnome.org/ +GTK+: https://www.gtk.org/ + +Alternatively, Jim Knoble has written an X11 +passphrase requester. It was maintained separately at: http://www.jmknoble.net/software/x11-ssh-askpass/ +Remarks: obsolete since 2011, does not work with UTF-8. +A mirror could be found here: +https://github.com/sigmavirus24/x11-ssh-askpass + LibEdit: sftp supports command-line editing via NetBSD's libedit. If your platform @@ -83,23 +95,23 @@ these multi-platform ports: http://www.thrysoee.dk/editline/ -http://sourceforge.net/projects/libedit/ +https://sourceforge.net/projects/libedit/ LDNS: LDNS is a DNS BSD-licensed resolver library which supports DNSSEC. -http://nlnetlabs.nl/projects/ldns/ +https://nlnetlabs.nl/projects/ldns/ Autoconf: If you modify configure.ac or configure doesn't exist (eg if you checked -the code out of git yourself) then you will need autoconf-2.69 and -automake-1.16.1 to rebuild the automatically generated files by running -"autoreconf". Earlier versions may also work but this is not guaranteed. +the code out of git yourself) then you will need autoconf (2.60+) and +aclocal (from automake) to rebuild the automatically generated files by +running "autoreconf". -http://www.gnu.org/software/autoconf/ -http://www.gnu.org/software/automake/ +https://www.gnu.org/software/autoconf/ +https://www.gnu.org/software/automake/ Basic Security Module (BSM): @@ -107,34 +119,16 @@ FreeBSD 6.1 and OS X. Alternatively, you may use the OpenBSM implementation (http://www.openbsm.org). -makedepend: - -https://www.x.org/archive/individual/util/ - -If you are making significant changes to the code you may need to rebuild -the dependency (.depend) file using "make depend", which requires the -"makedepend" tool from the X11 distribution. - -libfido2: - -libfido2 allows the use of hardware security keys over USB. libfido2 -in turn depends on libcbor. libfido2 >= 1.5.0 is strongly recommended. -Limited functionality is possible with earlier libfido2 versions. - -https://github.com/Yubico/libfido2 -https://github.com/pjk/libcbor - - 2. Building / Installation -------------------------- -To install OpenSSH with default options: +To install PKIX-SSH with default options: ./configure make make install -This will install the OpenSSH binaries in /usr/local/bin, configuration files +This will install the PKIX-SSH binaries in /usr/local/bin, configuration files in /usr/local/etc, the server in /usr/local/sbin, etc. To specify a different installation prefix, use the --prefix option to configure: @@ -142,7 +136,7 @@ make make install -Will install OpenSSH in /opt/{bin,etc,lib,sbin}. You can also override +Will install PKIX-SSH in /opt/{bin,etc,lib,sbin}. You can also override specific paths, for example: ./configure --prefix=/opt --sysconfdir=/etc/ssh @@ -152,6 +146,10 @@ This will install the binaries in /opt/{bin,lib,sbin}, but will place the configuration files in /etc/ssh. +If you are using Privilege Separation (which is enabled by default) +then you will also need to create the user, group and directory used by +sshd for privilege separation. See README.privsep for details. + If you are using PAM, you may need to manually install a PAM control file as "/etc/pam.d/sshd" (or wherever your system prefers to keep them). Note that the service name used to start PAM is __progname, @@ -194,6 +192,11 @@ --with-osfsia, --without-osfsia will enable or disable OSF1's Security Integration Architecture. The default for OSF1 machines is enable. +--with-md5-passwords will enable the use of MD5 passwords. Enable this +if your operating system uses MD5 passwords and the system crypt() does +not support them directly (see the crypt(3/3c) man page). If enabled, the +resulting binary will support both MD5 and traditional crypt passwords. + --with-utmpx enables utmpx support. utmpx support is automatic for some platforms. @@ -210,19 +213,22 @@ --with-xauth=PATH specifies the location of the xauth binary ---with-ssl-dir=DIR allows you to specify where your Libre/OpenSSL -libraries are installed. +--without-openssl compatibility option. OpenSSL cryptographic +library is required. ---with-ssl-engine enables Libre/OpenSSL's (hardware) ENGINE support +--with-ssl-dir=DIR allows you to specify where your OpenSSL +libraries are installed. ---without-openssl builds without using OpenSSL. Only a subset of ciphers -and algorithms are supported in this configuration. +--with-ssl-engine enables OpenSSL's (hardware) ENGINE support --without-zlib builds without zlib. This disables the Compression option. --with-4in6 Check for IPv4 in IPv6 mapped addresses and convert them to real (AF_INET) IPv4 addresses. Works around some quirks on Linux. +--with-sshca-dir=PATH allows you to specify location of ssh CA root +used by ssh "X.509 store" to verify certificates. + If you need to pass special options to the compiler or linker, you can specify these as environment variables before running ./configure. For example: @@ -243,18 +249,19 @@ ssh-keygen -t [type] -f /etc/ssh/ssh_host_key -N "" -for each of the types you wish to generate (rsa, dsa or ecdsa) or +for each of the types you wish to generate (rsa, ecdsa, ed25519 or dsa) or ssh-keygen -A -to generate keys for all supported types. +to generate keys for default types. Replacing /etc/ssh with the correct path to the configuration directory. (${prefix}/etc or whatever you specified with --sysconfdir during -configuration). +configuration) -If you have configured OpenSSH with EGD/prngd support, ensure that EGD or -prngd is running and has collected some entropy first. +If you have configured PKIX-SSH with "prngd", ensure that EGD or PRNGD +is running and has collected some entropy. +Note functionality is usable only if OpenSSL does not seed internally. For more information on configuration, please refer to the manual pages for sshd, ssh and ssh-agent. @@ -270,12 +277,12 @@ This will send configuration information for the currently configured host to a survey address. This will help determine which configurations are actually in use, and what valid combinations of configure options -exist. The raw data is available only to the OpenSSH developers, however +exist. The raw data is available only to the PKIX-SSH developers, however summary data may be published. 5. Problems? ------------ -If you experience problems compiling, installing or running OpenSSH, -please refer to the "reporting bugs" section of the webpage at -https://www.openssh.com/ +If you experience problems compiling, installing or running PKIX-SSH, +please refer to the "Support" section of the webpage at +https://roumenpetrov.info/secsh/#support diff -ruN openssh-9.4p1/kex.c openssh-9.4p1+x509-14.2.1/kex.c --- openssh-9.4p1/kex.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/kex.c 2023-08-20 10:07:01.000000000 +0300 @@ -1,6 +1,7 @@ -/* $OpenBSD: kex.c,v 1.178 2023/03/12 10:40:39 dtucker Exp $ */ +/* $OpenBSD: kex.c,v 1.179 2023/08/18 01:37:41 djm Exp $ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. + * Copyright (c) 2014-2021 Roumen Petrov. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -33,19 +34,16 @@ #include #include #include -#ifdef HAVE_POLL_H -#include -#endif #ifdef WITH_OPENSSL #include #include #endif +#include "xmalloc.h" #include "ssh.h" #include "ssh2.h" #include "atomicio.h" -#include "version.h" #include "packet.h" #include "compat.h" #include "cipher.h" @@ -57,12 +55,13 @@ #include "misc.h" #include "dispatch.h" #include "monitor.h" -#include "myproposal.h" #include "ssherr.h" #include "sshbuf.h" #include "digest.h" -#include "xmalloc.h" + +const char *srv_extinfo_pkalgs = "publickey-algorithms@roumenpetrov.info"; +char *server_pkalgs = NULL; /* prototype */ static int kex_choose_conf(struct ssh *); @@ -82,41 +81,52 @@ }; struct kexalg { - char *name; + const char *name; u_int type; int ec_nid; int hash_alg; }; static const struct kexalg kexalgs[] = { #ifdef WITH_OPENSSL - { KEX_DH1, KEX_DH_GRP1_SHA1, 0, SSH_DIGEST_SHA1 }, - { KEX_DH14_SHA1, KEX_DH_GRP14_SHA1, 0, SSH_DIGEST_SHA1 }, - { KEX_DH14_SHA256, KEX_DH_GRP14_SHA256, 0, SSH_DIGEST_SHA256 }, - { KEX_DH16_SHA512, KEX_DH_GRP16_SHA512, 0, SSH_DIGEST_SHA512 }, - { KEX_DH18_SHA512, KEX_DH_GRP18_SHA512, 0, SSH_DIGEST_SHA512 }, - { KEX_DHGEX_SHA1, KEX_DH_GEX_SHA1, 0, SSH_DIGEST_SHA1 }, + { "diffie-hellman-group1-sha1", + KEX_DH_GRP1_SHA1, 0, SSH_DIGEST_SHA1 }, + { "diffie-hellman-group14-sha1", + KEX_DH_GRP14_SHA1, 0, SSH_DIGEST_SHA1 }, +#ifdef HAVE_EVP_SHA256 + { "diffie-hellman-group14-sha256", + KEX_DH_GRP14_SHA256, 0, SSH_DIGEST_SHA256 }, + { "diffie-hellman-group16-sha512", + KEX_DH_GRP16_SHA512, 0, SSH_DIGEST_SHA512 }, + { "diffie-hellman-group18-sha512", + KEX_DH_GRP18_SHA512, 0, SSH_DIGEST_SHA512 }, +#endif /* HAVE_EVP_SHA256 */ + { "diffie-hellman-group-exchange-sha1", + KEX_DH_GEX_SHA1, 0, SSH_DIGEST_SHA1 }, #ifdef HAVE_EVP_SHA256 - { KEX_DHGEX_SHA256, KEX_DH_GEX_SHA256, 0, SSH_DIGEST_SHA256 }, + { "diffie-hellman-group-exchange-sha256", + KEX_DH_GEX_SHA256, 0, SSH_DIGEST_SHA256 }, #endif /* HAVE_EVP_SHA256 */ #ifdef OPENSSL_HAS_ECC - { KEX_ECDH_SHA2_NISTP256, KEX_ECDH_SHA2, - NID_X9_62_prime256v1, SSH_DIGEST_SHA256 }, - { KEX_ECDH_SHA2_NISTP384, KEX_ECDH_SHA2, NID_secp384r1, - SSH_DIGEST_SHA384 }, + { "ecdh-sha2-nistp256", + KEX_ECDH_SHA2, NID_X9_62_prime256v1, SSH_DIGEST_SHA256 }, + { "ecdh-sha2-nistp384", + KEX_ECDH_SHA2, NID_secp384r1, SSH_DIGEST_SHA384 }, # ifdef OPENSSL_HAS_NISTP521 - { KEX_ECDH_SHA2_NISTP521, KEX_ECDH_SHA2, NID_secp521r1, - SSH_DIGEST_SHA512 }, + { "ecdh-sha2-nistp521", + KEX_ECDH_SHA2, NID_secp521r1, SSH_DIGEST_SHA512 }, # endif /* OPENSSL_HAS_NISTP521 */ #endif /* OPENSSL_HAS_ECC */ #endif /* WITH_OPENSSL */ #if defined(HAVE_EVP_SHA256) || !defined(WITH_OPENSSL) - { KEX_CURVE25519_SHA256, KEX_C25519_SHA256, 0, SSH_DIGEST_SHA256 }, - { KEX_CURVE25519_SHA256_OLD, KEX_C25519_SHA256, 0, SSH_DIGEST_SHA256 }, -#ifdef USE_SNTRUP761X25519 - { KEX_SNTRUP761X25519_SHA512, KEX_KEM_SNTRUP761X25519_SHA512, 0, - SSH_DIGEST_SHA512 }, -#endif + { "curve25519-sha256", + KEX_C25519_SHA256, 0, SSH_DIGEST_SHA256 }, + { "curve25519-sha256@libssh.org", + KEX_C25519_SHA256, 0, SSH_DIGEST_SHA256 }, #endif /* HAVE_EVP_SHA256 || !WITH_OPENSSL */ +#ifdef ENABLE_KEX_SNTRUP761X25519 + { "sntrup761x25519-sha512@openssh.com", + KEX_KEM_SNTRUP761X25519_SHA512, 0, SSH_DIGEST_SHA512 }, +#endif { NULL, 0, -1, -1}, }; @@ -319,61 +329,6 @@ return r; } -/* - * Fill out a proposal array with dynamically allocated values, which may - * be modified as required for compatibility reasons. - * Any of the options may be NULL, in which case the default is used. - * Array contents must be freed by calling kex_proposal_free_entries. - */ -void -kex_proposal_populate_entries(struct ssh *ssh, char *prop[PROPOSAL_MAX], - const char *kexalgos, const char *ciphers, const char *macs, - const char *comp, const char *hkalgs) -{ - const char *defpropserver[PROPOSAL_MAX] = { KEX_SERVER }; - const char *defpropclient[PROPOSAL_MAX] = { KEX_CLIENT }; - const char **defprop = ssh->kex->server ? defpropserver : defpropclient; - u_int i; - - if (prop == NULL) - fatal_f("proposal missing"); - - for (i = 0; i < PROPOSAL_MAX; i++) { - switch(i) { - case PROPOSAL_KEX_ALGS: - prop[i] = compat_kex_proposal(ssh, - kexalgos ? kexalgos : defprop[i]); - break; - case PROPOSAL_ENC_ALGS_CTOS: - case PROPOSAL_ENC_ALGS_STOC: - prop[i] = xstrdup(ciphers ? ciphers : defprop[i]); - break; - case PROPOSAL_MAC_ALGS_CTOS: - case PROPOSAL_MAC_ALGS_STOC: - prop[i] = xstrdup(macs ? macs : defprop[i]); - break; - case PROPOSAL_COMP_ALGS_CTOS: - case PROPOSAL_COMP_ALGS_STOC: - prop[i] = xstrdup(comp ? comp : defprop[i]); - break; - case PROPOSAL_SERVER_HOST_KEY_ALGS: - prop[i] = xstrdup(hkalgs ? hkalgs : defprop[i]); - break; - default: - prop[i] = xstrdup(defprop[i]); - } - } -} - -void -kex_proposal_free_entries(char *prop[PROPOSAL_MAX]) -{ - u_int i; - - for (i = 0; i < PROPOSAL_MAX; i++) - free(prop[i]); -} - /* put algorithm proposal into buffer */ int kex_prop2buf(struct sshbuf *b, char *proposal[PROPOSAL_MAX]) @@ -485,27 +440,24 @@ kex_send_ext_info(struct ssh *ssh) { int r; - char *algs; debug("Sending SSH2_MSG_EXT_INFO"); - if ((algs = sshkey_alg_list(0, 1, 1, ',')) == NULL) - return SSH_ERR_ALLOC_FAIL; - /* XXX filter algs list by allowed pubkey/hostbased types */ - if ((r = sshpkt_start(ssh, SSH2_MSG_EXT_INFO)) != 0 || + if (server_pkalgs == NULL) return 0; + + if ( + (r = sshpkt_start(ssh, SSH2_MSG_EXT_INFO)) != 0 || (r = sshpkt_put_u32(ssh, 2)) != 0 || + (r = sshpkt_put_cstring(ssh, srv_extinfo_pkalgs)) != 0 || + (r = sshpkt_put_cstring(ssh, server_pkalgs)) != 0 || (r = sshpkt_put_cstring(ssh, "server-sig-algs")) != 0 || - (r = sshpkt_put_cstring(ssh, algs)) != 0 || - (r = sshpkt_put_cstring(ssh, - "publickey-hostbound@openssh.com")) != 0 || - (r = sshpkt_put_cstring(ssh, "0")) != 0 || - (r = sshpkt_send(ssh)) != 0) { + (r = sshpkt_put_cstring(ssh, server_pkalgs)) != 0) { error_fr(r, "compose"); goto out; } - /* success */ - r = 0; - out: - free(algs); + + r = sshpkt_send(ssh); + +out: return r; } @@ -519,14 +471,53 @@ (r = sshpkt_send(ssh)) != 0) return r; debug("SSH2_MSG_NEWKEYS sent"); + + debug("expecting SSH2_MSG_NEWKEYS"); ssh_dispatch_set(ssh, SSH2_MSG_NEWKEYS, &kex_input_newkeys); + if (ssh->kex->ext_info_c && (ssh->kex->flags & KEX_INITIAL) != 0) - if ((r = kex_send_ext_info(ssh)) != 0) - return r; - debug("expecting SSH2_MSG_NEWKEYS"); + return kex_send_ext_info(ssh); + return 0; } +static void +preset_pkalgs(struct kex *kex, char *pkalgs) { + size_t n = 0; + + free(kex->pkalgs); + kex->pkalgs = NULL; + + if (pkalgs == NULL) return; + +{ char *alg, *q = pkalgs, *new_pkalgs = NULL; + + for (alg = strsep(&q, ","); alg != NULL; alg = strsep(&q, ",")) { + size_t len; + int type = sshkey_type_from_name(alg); + + if (type == KEY_UNSPEC) { + debug3_f("unsupported public-key algorithm"); + continue; + } + + len = strlen(alg); + new_pkalgs = realloc(new_pkalgs, n + len + 1); + if (new_pkalgs == NULL) goto done; + + memmove(new_pkalgs + n, alg, len); + n += len; + new_pkalgs[n++] = ','; + } + if (new_pkalgs != NULL) + new_pkalgs[--n] = '\0'; + + kex->pkalgs = new_pkalgs; +done: + free(pkalgs); +} +} + int kex_input_ext_info(int type, u_int32_t seq, struct ssh *ssh) { @@ -535,10 +526,15 @@ char *name; u_char *val; size_t vlen; + char *pkalgs = NULL, *sigalgs = NULL; int r; + UNUSED(type); + UNUSED(seq); + debug("SSH2_MSG_EXT_INFO received"); ssh_dispatch_set(ssh, SSH2_MSG_EXT_INFO, &kex_protocol_error); + if ((r = sshpkt_get_u32(ssh, &ninfo)) != 0) return r; if (ninfo >= 1024) { @@ -553,35 +549,46 @@ free(name); return r; } - if (strcmp(name, "server-sig-algs") == 0) { + if (strcmp(name, srv_extinfo_pkalgs) == 0) { /* Ensure no \0 lurking in value */ if (memchr(val, '\0', vlen) != NULL) { error_f("nul byte in %s", name); return SSH_ERR_INVALID_FORMAT; } debug_f("%s=<%s>", name, val); - kex->server_sig_algs = val; - val = NULL; - } else if (strcmp(name, - "publickey-hostbound@openssh.com") == 0) { - /* XXX refactor */ + pkalgs = val; + free(name); + continue; + } + if (strcmp(name, "server-sig-algs") == 0) { /* Ensure no \0 lurking in value */ if (memchr(val, '\0', vlen) != NULL) { error_f("nul byte in %s", name); return SSH_ERR_INVALID_FORMAT; } debug_f("%s=<%s>", name, val); - if (strcmp(val, "0") == 0) - kex->flags |= KEX_HAS_PUBKEY_HOSTBOUND; - else { - debug_f("unsupported version of %s extension", - name); - } - } else - debug_f("%s (unrecognised)", name); + sigalgs = val; + free(name); + continue; + } + debug3_f("%s (unsupported)", name); free(name); free(val); } + if (pkalgs != NULL) { + free(sigalgs); + preset_pkalgs(kex, pkalgs); + } else { + if (ssh_compat_extra(ssh, SSHX_OPENSSH_BROKEN_ALGO_INFO)) { + free(sigalgs); + /* use list as is properly announced in OpenSSH 7.5 */ + sigalgs = strdup( + "ssh-ed25519,ssh-rsa,rsa-sha2-256,rsa-sha2-512,ssh-dss," + "ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521"); + } + preset_pkalgs(kex, sigalgs); + } + return sshpkt_get_end(ssh); } @@ -591,9 +598,13 @@ struct kex *kex = ssh->kex; int r; + UNUSED(type); + UNUSED(seq); + debug("SSH2_MSG_NEWKEYS received"); ssh_dispatch_set(ssh, SSH2_MSG_NEWKEYS, &kex_protocol_error); ssh_dispatch_set(ssh, SSH2_MSG_KEXINIT, &kex_input_kexinit); + if ((r = sshpkt_get_end(ssh)) != 0) return r; if ((r = ssh_set_newkeys(ssh, MODE_IN)) != 0) @@ -603,6 +614,12 @@ sshbuf_reset(kex->peer); /* sshbuf_reset(kex->my); */ kex->flags &= ~KEX_INIT_SENT; + +#if 0 /* keep for later use */ + free(kex->hostkey_alg); + kex->hostkey_alg = NULL; +#endif + free(kex->name); kex->name = NULL; return 0; @@ -655,12 +672,16 @@ size_t dlen; int r; + UNUSED(type); + UNUSED(seq); + debug("SSH2_MSG_KEXINIT received"); if (kex == NULL) { error_f("no kex"); return SSH_ERR_INTERNAL_ERROR; } ssh_dispatch_set(ssh, SSH2_MSG_KEXINIT, NULL); + ptr = sshpkt_ptr(ssh, &dlen); if ((r = sshbuf_put(kex->peer, ptr, dlen)) != 0) return r; @@ -729,13 +750,11 @@ if (newkeys == NULL) return; if (newkeys->enc.key) { - explicit_bzero(newkeys->enc.key, newkeys->enc.key_len); - free(newkeys->enc.key); + freezero(newkeys->enc.key, newkeys->enc.key_len); newkeys->enc.key = NULL; } if (newkeys->enc.iv) { - explicit_bzero(newkeys->enc.iv, newkeys->enc.iv_len); - free(newkeys->enc.iv); + freezero(newkeys->enc.iv, newkeys->enc.iv_len); newkeys->enc.iv = NULL; } free(newkeys->enc.name); @@ -744,8 +763,7 @@ explicit_bzero(&newkeys->comp, sizeof(newkeys->comp)); mac_clear(&newkeys->mac); if (newkeys->mac.key) { - explicit_bzero(newkeys->mac.key, newkeys->mac.key_len); - free(newkeys->mac.key); + freezero(newkeys->mac.key, newkeys->mac.key_len); newkeys->mac.key = NULL; } free(newkeys->mac.name); @@ -758,14 +776,10 @@ { u_int mode; - if (kex == NULL) - return; + if (kex == NULL) return; #ifdef WITH_OPENSSL - DH_free(kex->dh); -#ifdef OPENSSL_HAS_ECC - EC_KEY_free(kex->ec_client_key); -#endif /* OPENSSL_HAS_ECC */ + kex_reset_crypto_keys(kex); #endif /* WITH_OPENSSL */ for (mode = 0; mode < MODE_MAX; mode++) { kex_free_newkeys(kex->newkeys[mode]); @@ -775,12 +789,11 @@ sshbuf_free(kex->my); sshbuf_free(kex->client_version); sshbuf_free(kex->server_version); - sshbuf_free(kex->client_pub); sshbuf_free(kex->session_id); - sshbuf_free(kex->initial_sig); - sshkey_free(kex->initial_hostkey); + sshbuf_free(kex->client_pub); free(kex->failed_choice); free(kex->hostkey_alg); + free(kex->pkalgs); free(kex->name); free(kex); } @@ -790,6 +803,8 @@ { int r; + if (ssh->kex == NULL) return SSH_ERR_INTERNAL_ERROR; + if ((r = kex_prop2buf(ssh->kex->my, proposal)) != 0) return r; ssh->kex->flags = KEX_INITIAL; @@ -859,6 +874,7 @@ { char *name = match_list(client, server, NULL); + UNUSED(ssh); if (name == NULL) return SSH_ERR_NO_MAC_ALG_MATCH; if (mac_setup(mac, name) < 0) { @@ -927,12 +943,10 @@ k->hostkey_alg ? k->hostkey_alg : "(no match)"); if (k->hostkey_alg == NULL) return SSH_ERR_NO_HOSTKEY_ALG_MATCH; - k->hostkey_type = sshkey_type_from_name(k->hostkey_alg); - if (k->hostkey_type == KEY_UNSPEC) { + if (sshkey_type_from_name(k->hostkey_alg) == KEY_UNSPEC) { error_f("unsupported hostkey algorithm %s", k->hostkey_alg); return SSH_ERR_INTERNAL_ERROR; } - k->hostkey_nid = sshkey_ecdsa_nid_from_name(k->hostkey_alg); return 0; } @@ -961,13 +975,11 @@ } /* returns non-zero if proposal contains any algorithm from algs */ -static int +static inline int has_any_alg(const char *proposal, const char *algs) { - char *cp; - - if ((cp = match_list(proposal, algs, NULL)) == NULL) - return 0; + char *cp = match_list(proposal, algs, NULL); + if (cp == NULL) return 0; free(cp); return 1; } @@ -981,7 +993,7 @@ char **cprop, **sprop; int nenc, nmac, ncomp; u_int mode, ctos, need, dh_need, authlen; - int r, first_kex_follows; + int r, first_kex_follows = 0; debug2("local %s KEXINIT proposal", kex->server ? "server" : "client"); if ((r = kex_buf2prop(kex->my, NULL, &my)) != 0) @@ -1083,12 +1095,12 @@ /* XXX need runden? */ kex->we_need = need; kex->dh_need = dh_need; + r = 0; + out: /* ignore the next message if the proposals do not match */ if (first_kex_follows && !proposals_match(my, peer)) ssh->dispatch_skip_packets = 1; - r = 0; - out: kex_prop_free(my); kex_prop_free(peer); return r; @@ -1169,16 +1181,9 @@ int r; /* save initial hash as session id */ - if ((kex->flags & KEX_INITIAL) != 0) { - if (sshbuf_len(kex->session_id) != 0) { - error_f("already have session ID at kex"); - return SSH_ERR_INTERNAL_ERROR; - } - if ((r = sshbuf_put(kex->session_id, hash, hashlen)) != 0) - return r; - } else if (sshbuf_len(kex->session_id) == 0) { - error_f("no session ID in rekex"); - return SSH_ERR_INTERNAL_ERROR; + if (sshbuf_len(kex->session_id) == 0) { + r = sshbuf_put(kex->session_id, hash, hashlen); + if (r != 0) return r; } for (i = 0; i < NKEYS; i++) { if ((r = derive_key(ssh, 'A'+i, kex->we_need, hash, hashlen, @@ -1199,24 +1204,33 @@ } int -kex_load_hostkey(struct ssh *ssh, struct sshkey **prvp, struct sshkey **pubp) -{ +kex_load_host_keys(struct ssh *ssh, struct sshkey **hostpub, struct sshkey **hostpriv) { struct kex *kex = ssh->kex; + int r; - *pubp = NULL; - *prvp = NULL; - if (kex->load_host_public_key == NULL || - kex->load_host_private_key == NULL) { - error_f("missing hostkey loader"); - return SSH_ERR_INVALID_ARGUMENT; + if (hostpub == NULL || hostpriv == NULL) { + r = SSH_ERR_INVALID_ARGUMENT; + goto done; } - *pubp = kex->load_host_public_key(kex->hostkey_type, - kex->hostkey_nid, ssh); - *prvp = kex->load_host_private_key(kex->hostkey_type, - kex->hostkey_nid, ssh); - if (*pubp == NULL) - return SSH_ERR_NO_HOSTKEY_LOADED; - return 0; + + if (kex->find_host_public_key == NULL || + kex->find_host_private_key == NULL) { + error_f("missing hostkey find callback"); + r = SSH_ERR_INVALID_ARGUMENT; + goto done; + } + + *hostpub = kex->find_host_public_key(kex->hostkey_alg, ssh); + *hostpriv = kex->find_host_private_key(kex->hostkey_alg, ssh); + + /* Only public part is required, private is optional and + * caller is responsible to check private part + */ + r = (*hostpub != NULL) + ? SSH_ERR_SUCCESS + : SSH_ERR_NO_HOSTKEY_LOADED; +done: + return r; } int @@ -1225,12 +1239,10 @@ struct kex *kex = ssh->kex; if (kex->verify_host_key == NULL) { - error_f("missing hostkey verifier"); + error_f("missing hostkey verify callback"); return SSH_ERR_INVALID_ARGUMENT; } - if (server_host_key->type != kex->hostkey_type || - (kex->hostkey_type == KEY_ECDSA && - server_host_key->ecdsa_nid != kex->hostkey_nid)) + if (!sshkey_match_pkalg(server_host_key, kex->hostkey_alg)) return SSH_ERR_KEY_TYPE_MISMATCH; if (kex->verify_host_key(server_host_key, ssh) == -1) return SSH_ERR_SIGNATURE_INVALID; @@ -1239,11 +1251,18 @@ #if defined(DEBUG_KEX) || defined(DEBUG_KEXDH) || defined(DEBUG_KEXECDH) void -dump_digest(const char *msg, const u_char *digest, int len) +dump_digest(const char *msg, const u_char *digest, size_t len) { fprintf(stderr, "%s\n", msg); sshbuf_dump_data(digest, len, stderr); } + +void +dump_digestb(const char *msg, const struct sshbuf *digest) +{ + fprintf(stderr, "%s\n", msg); + sshbuf_dump_data(sshbuf_ptr(digest), sshbuf_len(digest), stderr); +} #endif /* @@ -1271,33 +1290,28 @@ * Returns on 0 success or a ssherr.h code on failure. */ int -kex_exchange_identification(struct ssh *ssh, int timeout_ms, - const char *version_addendum) +kex_exchange_identification(struct ssh *ssh, int timeout_ms) { + int is_server = ssh->kex->server; int remote_major, remote_minor, mismatch, oerrno = 0; - size_t len, n; + size_t len; + int n, found_cr; int r, expect_nl; u_char c; - struct sshbuf *our_version = ssh->kex->server ? - ssh->kex->server_version : ssh->kex->client_version; - struct sshbuf *peer_version = ssh->kex->server ? - ssh->kex->client_version : ssh->kex->server_version; + struct sshbuf *our_version; + struct sshbuf *peer_version; char *our_version_string = NULL, *peer_version_string = NULL; char *cp, *remote_version = NULL; - /* Prepare and send our banner */ - sshbuf_reset(our_version); - if (version_addendum != NULL && *version_addendum == '\0') - version_addendum = NULL; - if ((r = sshbuf_putf(our_version, "SSH-%d.%d-%.100s%s%s\r\n", - PROTOCOL_MAJOR_2, PROTOCOL_MINOR_2, SSH_VERSION, - version_addendum == NULL ? "" : " ", - version_addendum == NULL ? "" : version_addendum)) != 0) { - oerrno = errno; - error_fr(r, "sshbuf_putf"); - goto out; + if (is_server) { + our_version = ssh->kex->server_version; + peer_version = ssh->kex->client_version; + } else { + our_version = ssh->kex->client_version; + peer_version = ssh->kex->server_version; } + /* Send our banner */ if (atomicio(vwrite, ssh_packet_get_connection_out(ssh), sshbuf_mutable_ptr(our_version), sshbuf_len(our_version)) != sshbuf_len(our_version)) { @@ -1331,10 +1345,11 @@ } sshbuf_reset(peer_version); expect_nl = 0; - for (;;) { + found_cr = 0; + while (1) { if (timeout_ms > 0) { r = waitrfd(ssh_packet_get_connection_in(ssh), - &timeout_ms); + &timeout_ms, NULL); if (r == -1 && errno == ETIMEDOUT) { send_error(ssh, "Timed out waiting " "for SSH identification string."); @@ -1353,7 +1368,7 @@ len = atomicio(read, ssh_packet_get_connection_in(ssh), &c, 1); if (len != 1 && errno == EPIPE) { - error_f("Connection closed by remote host"); + error_f("connection closed by remote host"); r = SSH_ERR_CONN_CLOSED; goto out; } else if (len != 1) { @@ -1363,11 +1378,16 @@ goto out; } if (c == '\r') { + found_cr = 1; expect_nl = 1; continue; } - if (c == '\n') + if (c == '\n') { + if (!found_cr) + error("protocol identification string" + " lack carriage return"); break; + } if (c == '\0' || expect_nl) { error_f("banner line contains invalid " "characters"); @@ -1394,13 +1414,13 @@ goto out; } /* Do not accept lines before the SSH ident from a client */ - if (ssh->kex->server) { + if (is_server) { error_f("client sent invalid protocol identifier " "\"%.256s\"", cp); free(cp); goto invalid; } - debug_f("banner line %zu: %s", n, cp); + debug_f("banner line %d: %.256s", n, cp); free(cp); } peer_version_string = sshbuf_dup_string(peer_version); @@ -1428,7 +1448,8 @@ } debug("Remote protocol version %d.%d, remote software version %.100s", remote_major, remote_minor, remote_version); - compat_banner(ssh, remote_version); + + ssh_set_compatibility(ssh, remote_version); mismatch = 0; switch (remote_major) { @@ -1450,14 +1471,14 @@ goto out; } - if (ssh->kex->server && (ssh->compat & SSH_BUG_PROBE) != 0) { + if (is_server && ssh_compat_fellows(ssh, SSH_BUG_PROBE)) { logit("probed from %s port %d with %s. Don't panic.", ssh_remote_ipaddr(ssh), ssh_remote_port(ssh), peer_version_string); r = SSH_ERR_CONN_CLOSED; /* XXX */ goto out; } - if (ssh->kex->server && (ssh->compat & SSH_BUG_SCANNER) != 0) { + if (is_server && ssh_compat_fellows(ssh, SSH_BUG_SCANNER)) { logit("scanned from %s port %d with %s. Don't panic.", ssh_remote_ipaddr(ssh), ssh_remote_port(ssh), peer_version_string); @@ -1474,4 +1495,3 @@ errno = oerrno; return r; } - diff -ruN openssh-9.4p1/kexc25519.c openssh-9.4p1+x509-14.2.1/kexc25519.c --- openssh-9.4p1/kexc25519.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/kexc25519.c 2023-08-20 10:07:01.000000000 +0300 @@ -82,13 +82,6 @@ } int -kexc25519_shared_key(const u_char key[CURVE25519_SIZE], - const u_char pub[CURVE25519_SIZE], struct sshbuf *out) -{ - return kexc25519_shared_key_ext(key, pub, out, 0); -} - -int kex_c25519_keypair(struct kex *kex) { struct sshbuf *buf = NULL; @@ -121,6 +114,7 @@ u_char server_key[CURVE25519_SIZE]; int r; + UNUSED(kex); *server_blobp = NULL; *shared_secretp = NULL; @@ -149,7 +143,7 @@ goto out; #ifdef DEBUG_KEXECDH dump_digest("server public key 25519:", server_pub, CURVE25519_SIZE); - dump_digest("encoded shared secret:", sshbuf_ptr(buf), sshbuf_len(buf)); + dump_digestb("encoded shared secret:", buf); #endif *server_blobp = server_blob; *shared_secretp = buf; @@ -189,7 +183,7 @@ buf, 0)) < 0) goto out; #ifdef DEBUG_KEXECDH - dump_digest("encoded shared secret:", sshbuf_ptr(buf), sshbuf_len(buf)); + dump_digestb("encoded shared secret:", buf); #endif *shared_secretp = buf; buf = NULL; diff -ruN openssh-9.4p1/kex-crypto.c openssh-9.4p1+x509-14.2.1/kex-crypto.c --- openssh-9.4p1/kex-crypto.c 1970-01-01 02:00:00.000000000 +0200 +++ openssh-9.4p1+x509-14.2.1/kex-crypto.c 2023-08-20 10:07:01.000000000 +0300 @@ -0,0 +1,545 @@ +/* + * Copyright (c) 2021-2023 Roumen Petrov. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifndef USE_OPENSSL_PROVIDER +/* TODO: implement OpenSSL 4.0 API, as OpenSSL 3.* is quite nonfunctional */ +# define OPENSSL_SUPPRESS_DEPRECATED +#endif + +#define SSHKEY_INTERNAL +#include "includes.h" + +#ifdef WITH_OPENSSL +#include "evp-compat.h" + +#include "kex.h" +#include "dh.h" +#include "ssherr.h" +#include "misc.h" +#include "log.h" + +#ifndef HAVE_BN_IS_NEGATIVE /*macro before OpenSSL 1.1*/ +# ifndef BN_is_negative /*not defined before OpenSSL 0.9.8*/ +# define BN_is_negative(a) ((a)->neg != 0) +# endif +#endif + +#ifndef HAVE_DH_GET0_KEY /* OpenSSL < 1.1 */ +/* Partial backport of opaque DH from OpenSSL >= 1.1, commits + * "Make DH opaque", "RSA, DSA, DH: Allow some given input to be NULL + * on already initialised keys" and etc. + */ +static inline void +DH_get0_key(const DH *dh, const BIGNUM **pub_key, const BIGNUM **priv_key) { + if (pub_key != NULL) *pub_key = dh->pub_key; + if (priv_key != NULL) *priv_key = dh->priv_key; +} + +static inline int +DH_set_length(DH *dh, long length) { + dh->length = length; + return 1; +} + +static inline void +DH_get0_pqg(const DH *dh, const BIGNUM **p, const BIGNUM **q, const BIGNUM **g) { + if (p != NULL) *p = dh->p; + if (q != NULL) *q = dh->q; + if (g != NULL) *g = dh->g; +} + +static inline int +DH_set0_pqg(DH *dh, BIGNUM *p, BIGNUM *q, BIGNUM *g) { +/* If the fields p and g in d are NULL, the corresponding input + * parameters MUST be non-NULL. q may remain NULL. + * + * It is an error to give the results from get0 on d as input + * parameters. + */ + if (p == dh->p || (dh->q != NULL && q == dh->q) || g == dh->g) + return 0; + + if (p != NULL) { BN_free(dh->p); dh->p = p; } + if (q != NULL) { BN_free(dh->q); dh->q = q; } + if (g != NULL) { BN_free(dh->g); dh->g = g; } + + if (q != NULL) + (void)DH_set_length(dh, BN_num_bits(q)); + + return 1; +} +#endif /*ndef HAVE_DH_GET0_KEY*/ + +extern DH* _dh_new_group(BIGNUM *, BIGNUM *); +extern DH* _dh_new_group_asc(const char *, const char *); +extern DH* _dh_new_group_num(int); + + +/* + * This just returns the group, we still need to generate the exchange + * value. + */ +DH* +_dh_new_group(BIGNUM *modulus, BIGNUM *gen) +{ + DH *dh; + + dh = DH_new(); + if (dh == NULL) return NULL; + + if (!DH_set0_pqg(dh, modulus, NULL, gen)) { + DH_free(dh); + return NULL; + } + + return dh; +} + +DH* +_dh_new_group_asc(const char *gen, const char *modulus) +{ + BIGNUM *p = NULL, *g = NULL; + + if (BN_hex2bn(&p, modulus) == 0 || + BN_hex2bn(&g, gen) == 0) + goto err; + + return _dh_new_group(p, g); + +err: + BN_clear_free(p); + BN_clear_free(g); + return NULL; +} + + +static int +_dh_pub_is_valid(const DH *dh, const BIGNUM *dh_pub) +{ + int i; + int n = BN_num_bits(dh_pub); + int bits_set = 0; + BIGNUM *tmp; + const BIGNUM *dh_p; + + DH_get0_pqg(dh, &dh_p, NULL, NULL); + + if (BN_is_negative(dh_pub)) { + error("invalid public DH value: negative"); + return 0; + } + if (BN_cmp(dh_pub, BN_value_one()) != 1) { /* pub_exp <= 1 */ + error("invalid public DH value: <= 1"); + return 0; + } + + if ((tmp = BN_new()) == NULL) { + error_f("BN_new failed"); + return 0; + } + if (!BN_sub(tmp, dh_p, BN_value_one()) || + BN_cmp(dh_pub, tmp) != -1) { /* pub_exp > p-2 */ + BN_clear_free(tmp); + error("invalid public DH value: >= p-1"); + return 0; + } + BN_clear_free(tmp); + + for (i = 0; i <= n; i++) + if (BN_is_bit_set(dh_pub, i)) + bits_set++; + + /* used in dhgex regression test */ + debug2("bits set: %d/%d", bits_set, BN_num_bits(dh_p)); + + /* + * if g==2 and bits_set==1 then computing log_g(dh_pub) is trivial + */ + if (bits_set < 4) { + error("invalid public DH value (%d/%d)", + bits_set, BN_num_bits(dh_p)); + return 0; + } + return 1; +} + +int +kex_key_validate_public_dh(struct kex *kex, const BIGNUM *pub_key) { + int r; + DH *dh; + + if (kex->pk == NULL) + return SSH_ERR_INVALID_ARGUMENT; + + dh = EVP_PKEY_get1_DH(kex->pk); + if (dh == NULL) + return SSH_ERR_INVALID_ARGUMENT; + + r = _dh_pub_is_valid(dh, pub_key) + ? 0 : SSH_ERR_INVALID_ARGUMENT; + + DH_free(dh); + return r; +} + + +int +kex_key_gen_dh(struct kex *kex) +{ + int r, need, pbits; + DH *dh; + + if (kex->pk == NULL) + return SSH_ERR_INVALID_ARGUMENT; + + need = kex->we_need * 8; /*may overflow*/ + if (need < 0) + return SSH_ERR_INVALID_ARGUMENT; + + dh = EVP_PKEY_get1_DH(kex->pk); + if (dh == NULL) + return SSH_ERR_INVALID_ARGUMENT; + +{ const BIGNUM *dh_p; + DH_get0_pqg(dh, &dh_p, NULL, NULL); + if (dh_p == NULL) { + r = SSH_ERR_INVALID_ARGUMENT; + goto done; + } + pbits = BN_num_bits(dh_p); +} + + if (pbits <= 0 || need > INT_MAX / 2 || (2 * need) > pbits) { + r = SSH_ERR_INVALID_ARGUMENT; + goto done; + } + + if (need < 256) need = 256; + /* + * Pollard Rho, Big step/Little Step attacks are O(sqrt(n)), + * so double requested need here. + */ + if (!DH_set_length(dh, MINIMUM(need * 2, pbits - 1))) { + r = SSH_ERR_LIBCRYPTO_ERROR; + goto done; + } + + if (DH_generate_key(dh) == 0) { + r = SSH_ERR_LIBCRYPTO_ERROR; + goto done; + } + +{ const BIGNUM *pub_key; + DH_get0_key(dh, &pub_key, NULL); + if (kex_key_validate_public_dh(kex, pub_key) < 0) { + r = SSH_ERR_INVALID_FORMAT; + goto done; + } +} + + /* success */ + r = 0; + +done: + DH_free(dh); + return r; +} + + +int +kex_key_init_dh(struct kex *kex) { + DH *dh; + + switch (kex->kex_type) { + case KEX_DH_GRP1_SHA1: + dh = _dh_new_group_num(1); + break; + case KEX_DH_GRP14_SHA1: + case KEX_DH_GRP14_SHA256: + dh = _dh_new_group_num(14); + break; + case KEX_DH_GRP16_SHA512: + dh = _dh_new_group_num(16); + break; + case KEX_DH_GRP18_SHA512: + dh = _dh_new_group_num(18); + break; + default: + return SSH_ERR_INVALID_ARGUMENT; + } + if (dh == NULL) return SSH_ERR_ALLOC_FAIL; + +{ EVP_PKEY *pk = EVP_PKEY_new(); + if (pk == NULL) { + DH_free(dh); + return SSH_ERR_ALLOC_FAIL; + } + if (!EVP_PKEY_set1_DH(pk, dh)) { + DH_free(dh); + EVP_PKEY_free(pk); + return SSH_ERR_ALLOC_FAIL; + } + kex->pk = pk; +} + + return 0; +} + + +void +kex_reset_crypto_keys(struct kex *kex) { + EVP_PKEY_free(kex->pk); + kex->pk = NULL; +} + + +/* TODO: internal */ +extern DH* _choose_dh(int, int, int); + +EVP_PKEY* +kex_new_dh_group_bits(int min, int wantbits, int max) { + EVP_PKEY *pk; + DH *dh = NULL; + + dh = _choose_dh(min, wantbits, max); + if (dh == NULL) return NULL; + + pk = EVP_PKEY_new(); + if (pk == NULL) goto done; + + if (!EVP_PKEY_set1_DH(pk, dh)) { + EVP_PKEY_free(pk); + pk = NULL; + } + +done: + DH_free(dh); + return pk; +} + +EVP_PKEY* +kex_new_dh_group(BIGNUM *modulus, BIGNUM *gen) { + EVP_PKEY *pk = NULL; + DH *dh = NULL; + + dh = DH_new(); + if (dh == NULL) return NULL; + + pk = EVP_PKEY_new(); + if (pk == NULL) + goto done; + + if (!EVP_PKEY_set1_DH(pk, dh)) + goto err; + + if (DH_set0_pqg(dh, modulus, NULL, gen)) + goto done; + +err: + EVP_PKEY_free(pk); + pk = NULL; + +done: + DH_free(dh); + return pk; +} + + +int +kex_dh_compute_key(struct kex *kex, BIGNUM *pub_key, struct sshbuf *out) +{ + DH *dh; + BIGNUM *shared_secret = NULL; + int klen; + u_char *kbuf = NULL; + int r; + +#ifdef DEBUG_KEXDH + fprintf(stderr, "dh pub: "); + BN_print_fp(stderr, pub_key); + fprintf(stderr, "\n"); + fprintf(stderr, "bits %d\n", BN_num_bits(pub_key)); +{ BIO *err = BIO_new_fp(stderr, BIO_NOCLOSE); + EVP_PKEY_print_params(err, kex->pk, 0, NULL); + BIO_free_all(err); +} +#endif + if (kex_key_validate_public_dh(kex, pub_key) < 0) + return SSH_ERR_MESSAGE_INCOMPLETE; + + dh = EVP_PKEY_get1_DH(kex->pk); + if (dh == NULL) + return SSH_ERR_INVALID_ARGUMENT; + + /* NOTE EVP_PKEY_size fail for DH key if OpenSSL < 1.0.0 */ + klen = DH_size(dh); + + kbuf = malloc(klen); + if (kbuf == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto done; + } + +{ int kout = DH_compute_key(kbuf, pub_key, dh); + if (kout < 0) { + r = SSH_ERR_LIBCRYPTO_ERROR; + goto done; + } +#ifdef DEBUG_KEXDH + dump_digest("shared secret", kbuf, kout); +#endif + shared_secret = BN_bin2bn(kbuf, kout, NULL); +} + if (shared_secret == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto done; + } + + r = sshbuf_put_bignum2(out, shared_secret); + +done: + freezero(kbuf, klen); + BN_clear_free(shared_secret); + DH_free(dh); + return r; +} + + +int +sshbuf_kex_write_dh_group(struct sshbuf *buf, EVP_PKEY *pk) { + int r; + DH *dh; + + dh = EVP_PKEY_get1_DH(pk); + if (dh == NULL) + return SSH_ERR_INVALID_ARGUMENT; + +{ const BIGNUM *p = NULL, *g = NULL; + DH_get0_pqg(dh, &p, NULL, &g); + + if ((r = sshbuf_put_bignum2(buf, p)) != 0) + goto done; + r = sshbuf_put_bignum2(buf, g); +} + +done: + DH_free(dh); + return r; +} + +int +sshbuf_kex_write_dh_pub(struct sshbuf *buf, EVP_PKEY *pk) { + int r; + DH *dh; + + dh = EVP_PKEY_get1_DH(pk); + if (dh == NULL) + return SSH_ERR_INVALID_ARGUMENT; + +{ const BIGNUM *pub_key; + DH_get0_key(dh, &pub_key, NULL); +#ifdef DEBUG_KEXDH + fprintf(stderr, "dh pub: "); + BN_print_fp(stderr, pub_key); + fprintf(stderr, "\n"); + fprintf(stderr, "bits %d\n", BN_num_bits(pub_key)); +{ BIO *err = BIO_new_fp(stderr, BIO_NOCLOSE); + EVP_PKEY_print_params(err, pk, 0, NULL); + BIO_free_all(err); +} +#endif + + r = sshbuf_put_bignum2(buf, pub_key); +} + DH_free(dh); + return r; +} + + +int +kexgex_hash_client(const struct kex *kex, + const struct sshbuf *key_blob, const BIGNUM *peer_pub, + const struct sshbuf *shared_secret, + u_char *hash, size_t *hashlen +) { + int r; + DH *dh; + const BIGNUM *my_pub, *dh_p, *dh_g; + + dh = EVP_PKEY_get1_DH(kex->pk); + if (dh == NULL) + return SSH_ERR_INVALID_ARGUMENT; + + DH_get0_key(dh, &my_pub, NULL); + DH_get0_pqg(dh, &dh_p, NULL, &dh_g); + + r = kexgex_hash(kex->hash_alg, + kex->client_version, kex->server_version, + kex->my, kex->peer, key_blob, + kex->min, kex->nbits, kex->max, + dh_p, dh_g, my_pub, peer_pub, + sshbuf_ptr(shared_secret), sshbuf_len(shared_secret), + hash, hashlen); + + DH_free(dh); + return r; +} + +int +kexgex_hash_server(const struct kex *kex, + const struct sshbuf *key_blob, const BIGNUM *peer_pub, + const struct sshbuf *shared_secret, + u_char *hash, size_t *hashlen +) { + int r; + DH *dh; + const BIGNUM *my_pub, *dh_p, *dh_g; + + dh = EVP_PKEY_get1_DH(kex->pk); + if (dh == NULL) + return SSH_ERR_INVALID_ARGUMENT; + + DH_get0_key(dh, &my_pub, NULL); + DH_get0_pqg(dh, &dh_p, NULL, &dh_g); + + r = kexgex_hash(kex->hash_alg, + kex->client_version, kex->server_version, + kex->peer, kex->my, key_blob, + kex->min, kex->nbits, kex->max, + dh_p, dh_g, peer_pub, my_pub, + sshbuf_ptr(shared_secret), sshbuf_len(shared_secret), + hash, hashlen); + + DH_free(dh); + return r; +} +#else + +typedef int kex_crypto_empty_translation_unit; + +#endif /* WITH_OPENSSL */ diff -ruN openssh-9.4p1/kexdh.c openssh-9.4p1+x509-14.2.1/kexdh.c --- openssh-9.4p1/kexdh.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/kexdh.c 2023-08-20 10:07:01.000000000 +0300 @@ -1,6 +1,7 @@ /* $OpenBSD: kexdh.c,v 1.34 2020/12/04 02:29:25 djm Exp $ */ /* * Copyright (c) 2019 Markus Friedl. All rights reserved. + * Copyright (c) 2021 Roumen Petrov. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -27,111 +28,25 @@ #ifdef WITH_OPENSSL -#include - -#include -#include -#include - -#include "openbsd-compat/openssl-compat.h" -#include - -#include "sshkey.h" #include "kex.h" -#include "sshbuf.h" -#include "digest.h" #include "ssherr.h" -#include "dh.h" -#include "log.h" - -int -kex_dh_keygen(struct kex *kex) -{ - switch (kex->kex_type) { - case KEX_DH_GRP1_SHA1: - kex->dh = dh_new_group1(); - break; - case KEX_DH_GRP14_SHA1: - case KEX_DH_GRP14_SHA256: - kex->dh = dh_new_group14(); - break; - case KEX_DH_GRP16_SHA512: - kex->dh = dh_new_group16(); - break; - case KEX_DH_GRP18_SHA512: - kex->dh = dh_new_group18(); - break; - default: - return SSH_ERR_INVALID_ARGUMENT; - } - if (kex->dh == NULL) - return SSH_ERR_ALLOC_FAIL; - return (dh_gen_key(kex->dh, kex->we_need * 8)); -} - -int -kex_dh_compute_key(struct kex *kex, BIGNUM *dh_pub, struct sshbuf *out) -{ - BIGNUM *shared_secret = NULL; - u_char *kbuf = NULL; - size_t klen = 0; - int kout, r; - -#ifdef DEBUG_KEXDH - fprintf(stderr, "dh_pub= "); - BN_print_fp(stderr, dh_pub); - fprintf(stderr, "\n"); - debug("bits %d", BN_num_bits(dh_pub)); - DHparams_print_fp(stderr, kex->dh); - fprintf(stderr, "\n"); -#endif +#include "misc.h" - if (!dh_pub_is_valid(kex->dh, dh_pub)) { - r = SSH_ERR_MESSAGE_INCOMPLETE; - goto out; - } - klen = DH_size(kex->dh); - if ((kbuf = malloc(klen)) == NULL || - (shared_secret = BN_new()) == NULL) { - r = SSH_ERR_ALLOC_FAIL; - goto out; - } - if ((kout = DH_compute_key(kbuf, dh_pub, kex->dh)) < 0 || - BN_bin2bn(kbuf, kout, shared_secret) == NULL) { - r = SSH_ERR_LIBCRYPTO_ERROR; - goto out; - } -#ifdef DEBUG_KEXDH - dump_digest("shared secret", kbuf, kout); -#endif - r = sshbuf_put_bignum2(out, shared_secret); - out: - freezero(kbuf, klen); - BN_clear_free(shared_secret); - return r; -} int kex_dh_keypair(struct kex *kex) { - const BIGNUM *pub_key; struct sshbuf *buf = NULL; int r; - if ((r = kex_dh_keygen(kex)) != 0) + if ((r = kex_key_init_dh(kex)) != 0 || + (r = kex_key_gen_dh(kex)) != 0) return r; - DH_get0_key(kex->dh, &pub_key, NULL); if ((buf = sshbuf_new()) == NULL) return SSH_ERR_ALLOC_FAIL; - if ((r = sshbuf_put_bignum2(buf, pub_key)) != 0 || + if ((r = sshbuf_kex_write_dh_pub(buf, kex->pk)) != 0 || (r = sshbuf_get_u32(buf, NULL)) != 0) goto out; -#ifdef DEBUG_KEXDH - DHparams_print_fp(stderr, kex->dh); - fprintf(stderr, "pub= "); - BN_print_fp(stderr, pub_key); - fprintf(stderr, "\n"); -#endif kex->client_pub = buf; buf = NULL; out: @@ -143,21 +58,20 @@ kex_dh_enc(struct kex *kex, const struct sshbuf *client_blob, struct sshbuf **server_blobp, struct sshbuf **shared_secretp) { - const BIGNUM *pub_key; struct sshbuf *server_blob = NULL; int r; *server_blobp = NULL; *shared_secretp = NULL; - if ((r = kex_dh_keygen(kex)) != 0) + if ((r = kex_key_init_dh(kex)) != 0 || + (r = kex_key_gen_dh(kex)) != 0) goto out; - DH_get0_key(kex->dh, &pub_key, NULL); if ((server_blob = sshbuf_new()) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } - if ((r = sshbuf_put_bignum2(server_blob, pub_key)) != 0 || + if ((r = sshbuf_kex_write_dh_pub(server_blob, kex->pk)) != 0 || (r = sshbuf_get_u32(server_blob, NULL)) != 0) goto out; if ((r = kex_dh_dec(kex, client_blob, shared_secretp)) != 0) @@ -165,8 +79,7 @@ *server_blobp = server_blob; server_blob = NULL; out: - DH_free(kex->dh); - kex->dh = NULL; + kex_reset_crypto_keys(kex); sshbuf_free(server_blob); return r; } @@ -195,8 +108,7 @@ buf = NULL; out: BN_free(dh_pub); - DH_free(kex->dh); - kex->dh = NULL; + kex_reset_crypto_keys(kex); sshbuf_free(buf); return r; } diff -ruN openssh-9.4p1/kexecdh.c openssh-9.4p1+x509-14.2.1/kexecdh.c --- openssh-9.4p1/kexecdh.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/kexecdh.c 2023-08-20 10:07:01.000000000 +0300 @@ -2,6 +2,7 @@ /* * Copyright (c) 2010 Damien Miller. All rights reserved. * Copyright (c) 2019 Markus Friedl. All rights reserved. + * Copyright (c) 2021-2023 Roumen Petrov. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -24,6 +25,15 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifndef USE_OPENSSL_PROVIDER +/* TODO: implement OpenSSL 4.0 API, as OpenSSL 3.* is quite nonfunctional */ +# define OPENSSL_SUPPRESS_DEPRECATED +#endif + #include "includes.h" #if defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC) @@ -75,11 +85,20 @@ goto out; #ifdef DEBUG_KEXECDH fputs("client private key:\n", stderr); - sshkey_dump_ec_key(client_key); + EC_KEY_print_fp(stderr, client_key, 0); #endif - kex->ec_client_key = client_key; - kex->ec_group = group; +{ EVP_PKEY *pk = EVP_PKEY_new(); + if (pk == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + if (!EVP_PKEY_set1_EC_KEY(pk, client_key)) { + r = SSH_ERR_LIBCRYPTO_ERROR; + goto out; + } client_key = NULL; /* owned by the kex */ + kex->pk = pk; +} kex->client_pub = buf; buf = NULL; out: @@ -113,7 +132,7 @@ #ifdef DEBUG_KEXECDH fputs("server private key:\n", stderr); - sshkey_dump_ec_key(server_key); + EC_KEY_print_fp(stderr, server_key, 0); #endif pub_key = EC_KEY_get0_public_key(server_key); if ((server_blob = sshbuf_new()) == NULL) { @@ -145,6 +164,7 @@ size_t klen = 0; int r; + UNUSED(kex); *shared_secretp = NULL; if ((buf = sshbuf_new()) == NULL) { @@ -162,10 +182,6 @@ } sshbuf_reset(buf); -#ifdef DEBUG_KEXECDH - fputs("public key:\n", stderr); - sshkey_dump_ec_point(group, dh_pub); -#endif if (sshkey_ec_validate_public(group, dh_pub) != 0) { r = SSH_ERR_MESSAGE_INCOMPLETE; goto out; @@ -201,39 +217,23 @@ struct sshbuf **shared_secretp) { int r; + EC_KEY *ec; - r = kex_ecdh_dec_key_group(kex, server_blob, kex->ec_client_key, - kex->ec_group, shared_secretp); - EC_KEY_free(kex->ec_client_key); - kex->ec_client_key = NULL; - return r; -} + ec = EVP_PKEY_get1_EC_KEY(kex->pk); + if (ec == NULL) return SSH_ERR_INVALID_ARGUMENT; -#else - -#include "ssherr.h" - -struct kex; -struct sshbuf; -struct sshkey; - -int -kex_ecdh_keypair(struct kex *kex) -{ - return SSH_ERR_SIGN_ALG_UNSUPPORTED; -} +{ const EC_GROUP *group = EC_KEY_get0_group(ec); + if (group == NULL) { + r = SSH_ERR_INTERNAL_ERROR; + goto done; + } -int -kex_ecdh_enc(struct kex *kex, const struct sshbuf *client_blob, - struct sshbuf **server_blobp, struct sshbuf **shared_secretp) -{ - return SSH_ERR_SIGN_ALG_UNSUPPORTED; + r = kex_ecdh_dec_key_group(kex, server_blob, ec, group, shared_secretp); + kex_reset_crypto_keys(kex); } -int -kex_ecdh_dec(struct kex *kex, const struct sshbuf *server_blob, - struct sshbuf **shared_secretp) -{ - return SSH_ERR_SIGN_ALG_UNSUPPORTED; +done: + EC_KEY_free(ec); + return r; } #endif /* defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC) */ diff -ruN openssh-9.4p1/kexgen.c openssh-9.4p1+x509-14.2.1/kexgen.c --- openssh-9.4p1/kexgen.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/kexgen.c 2023-08-20 10:07:01.000000000 +0300 @@ -1,6 +1,7 @@ -/* $OpenBSD: kexgen.c,v 1.8 2021/12/19 22:08:06 djm Exp $ */ +/* $OpenBSD: kexgen.c,v 1.7 2021/04/03 06:18:40 djm Exp $ */ /* * Copyright (c) 2019 Markus Friedl. All rights reserved. + * Copyright (c) 2019-2021 Roumen Petrov. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -32,7 +33,7 @@ #include #include -#include "sshkey.h" +#include "sshxkey.h" #include "kex.h" #include "log.h" #include "packet.h" @@ -95,7 +96,7 @@ return 0; } -int +static int kex_gen_client(struct ssh *ssh) { struct kex *kex = ssh->kex; @@ -110,16 +111,20 @@ case KEX_DH_GRP18_SHA512: r = kex_dh_keypair(kex); break; +#ifdef OPENSSL_HAS_ECC case KEX_ECDH_SHA2: r = kex_ecdh_keypair(kex); break; #endif +#endif /*def WITH_OPENSSL*/ case KEX_C25519_SHA256: r = kex_c25519_keypair(kex); break; +#ifdef ENABLE_KEX_SNTRUP761X25519 case KEX_KEM_SNTRUP761X25519_SHA512: r = kex_kem_sntrup761x25519_keypair(kex); break; +#endif default: r = SSH_ERR_INVALID_ARGUMENT; break; @@ -142,25 +147,27 @@ struct sshkey *server_host_key = NULL; struct sshbuf *shared_secret = NULL; struct sshbuf *server_blob = NULL; - struct sshbuf *tmp = NULL, *server_host_key_blob = NULL; + struct sshbuf *server_host_key_blob = NULL; u_char *signature = NULL; u_char hash[SSH_DIGEST_MAX_LENGTH]; size_t slen, hashlen; int r; + UNUSED(type); + UNUSED(seq); + debug("SSH2_MSG_KEX_ECDH_REPLY received"); ssh_dispatch_set(ssh, SSH2_MSG_KEX_ECDH_REPLY, &kex_protocol_error); /* hostkey */ - if ((r = sshpkt_getb_froms(ssh, &server_host_key_blob)) != 0) - goto out; - /* sshkey_fromb() consumes its buffer, so make a copy */ - if ((tmp = sshbuf_fromb(server_host_key_blob)) == NULL) { - r = SSH_ERR_ALLOC_FAIL; - goto out; - } - if ((r = sshkey_fromb(tmp, &server_host_key)) != 0) - goto out; + r = sshpkt_getb_froms(ssh, &server_host_key_blob); + if (r != 0) goto out; + + r = Xkey_from_blob(kex->hostkey_alg, + sshbuf_ptr(server_host_key_blob), sshbuf_len(server_host_key_blob), + &server_host_key); + if (r != SSH_ERR_SUCCESS) goto out; + if ((r = kex_verify_host_key(ssh, server_host_key)) != 0) goto out; @@ -181,17 +188,21 @@ case KEX_DH_GRP18_SHA512: r = kex_dh_dec(kex, server_blob, &shared_secret); break; +#ifdef OPENSSL_HAS_ECC case KEX_ECDH_SHA2: r = kex_ecdh_dec(kex, server_blob, &shared_secret); break; #endif +#endif /*def WITH_OPENSSL*/ case KEX_C25519_SHA256: r = kex_c25519_dec(kex, server_blob, &shared_secret); break; +#ifdef ENABLE_KEX_SNTRUP761X25519 case KEX_KEM_SNTRUP761X25519_SHA512: r = kex_kem_sntrup761x25519_dec(kex, server_blob, &shared_secret); break; +#endif default: r = SSH_ERR_INVALID_ARGUMENT; break; @@ -214,30 +225,14 @@ hash, &hashlen)) != 0) goto out; - if ((r = sshkey_verify(server_host_key, signature, slen, hash, hashlen, - kex->hostkey_alg, ssh->compat, NULL)) != 0) - goto out; +{ ssh_verify_ctx ctx = { kex->hostkey_alg, server_host_key, &ssh->compat }; - if ((r = kex_derive_keys(ssh, hash, hashlen, shared_secret)) != 0 || - (r = kex_send_newkeys(ssh)) != 0) - goto out; + r = Xkey_verify(&ctx, signature, slen, hash, hashlen); + if (r != 0) goto out; +} - /* save initial signature and hostkey */ - if ((kex->flags & KEX_INITIAL) != 0) { - if (kex->initial_hostkey != NULL || kex->initial_sig != NULL) { - r = SSH_ERR_INTERNAL_ERROR; - goto out; - } - if ((kex->initial_sig = sshbuf_new()) == NULL) { - r = SSH_ERR_ALLOC_FAIL; - goto out; - } - if ((r = sshbuf_put(kex->initial_sig, signature, slen)) != 0) - goto out; - kex->initial_hostkey = server_host_key; - server_host_key = NULL; - } - /* success */ + if ((r = kex_derive_keys(ssh, hash, hashlen, shared_secret)) == 0) + r = kex_send_newkeys(ssh); out: explicit_bzero(hash, sizeof(hash)); explicit_bzero(kex->c25519_client_key, sizeof(kex->c25519_client_key)); @@ -245,7 +240,6 @@ sizeof(kex->sntrup761_client_key)); sshbuf_free(server_host_key_blob); free(signature); - sshbuf_free(tmp); sshkey_free(server_host_key); sshbuf_free(server_blob); sshbuf_free(shared_secret); @@ -254,7 +248,7 @@ return r; } -int +static int kex_gen_server(struct ssh *ssh) { debug("expecting SSH2_MSG_KEX_ECDH_INIT"); @@ -275,11 +269,14 @@ size_t slen, hashlen; int r; + UNUSED(type); + UNUSED(seq); + debug("SSH2_MSG_KEX_ECDH_INIT received"); ssh_dispatch_set(ssh, SSH2_MSG_KEX_ECDH_INIT, &kex_protocol_error); - if ((r = kex_load_hostkey(ssh, &server_host_private, - &server_host_public)) != 0) + if ((r = kex_load_host_keys(ssh, &server_host_public, + &server_host_private)) != 0) goto out; if ((r = sshpkt_getb_froms(ssh, &client_pubkey)) != 0 || @@ -297,19 +294,23 @@ r = kex_dh_enc(kex, client_pubkey, &server_pubkey, &shared_secret); break; +#ifdef OPENSSL_HAS_ECC case KEX_ECDH_SHA2: r = kex_ecdh_enc(kex, client_pubkey, &server_pubkey, &shared_secret); break; #endif +#endif /*def WITH_OPENSSL*/ case KEX_C25519_SHA256: r = kex_c25519_enc(kex, client_pubkey, &server_pubkey, &shared_secret); break; +#ifdef ENABLE_KEX_SNTRUP761X25519 case KEX_KEM_SNTRUP761X25519_SHA512: r = kex_kem_sntrup761x25519_enc(kex, client_pubkey, &server_pubkey, &shared_secret); break; +#endif default: r = SSH_ERR_INVALID_ARGUMENT; break; @@ -322,8 +323,9 @@ r = SSH_ERR_ALLOC_FAIL; goto out; } - if ((r = sshkey_putb(server_host_public, server_host_key_blob)) != 0) - goto out; + r = Xkey_putb(kex->hostkey_alg, server_host_public, server_host_key_blob); + if (r != 0) goto out; + hashlen = sizeof(hash); if ((r = kex_gen_hash( kex->hash_alg, @@ -339,9 +341,11 @@ goto out; /* sign H */ - if ((r = kex->sign(ssh, server_host_private, server_host_public, - &signature, &slen, hash, hashlen, kex->hostkey_alg)) != 0) - goto out; +{ ssh_sign_ctx ctx = { kex->hostkey_alg, server_host_private, &ssh->compat, NULL, NULL }; + + r = kex->xsign(ssh, &ctx, server_host_public, &signature, &slen, hash, hashlen); + if (r != 0) goto out; +} /* send server hostkey, ECDH pubkey 'Q_S' and signed H */ if ((r = sshpkt_start(ssh, SSH2_MSG_KEX_ECDH_REPLY)) != 0 || @@ -351,15 +355,8 @@ (r = sshpkt_send(ssh)) != 0) goto out; - if ((r = kex_derive_keys(ssh, hash, hashlen, shared_secret)) != 0 || - (r = kex_send_newkeys(ssh)) != 0) - goto out; - /* retain copy of hostkey used at initial KEX */ - if (kex->initial_hostkey == NULL && - (r = sshkey_from_private(server_host_public, - &kex->initial_hostkey)) != 0) - goto out; - /* success */ + if ((r = kex_derive_keys(ssh, hash, hashlen, shared_secret)) == 0) + r = kex_send_newkeys(ssh); out: explicit_bzero(hash, sizeof(hash)); sshbuf_free(server_host_key_blob); @@ -369,3 +366,40 @@ sshbuf_free(server_pubkey); return r; } + + +void +kex_set_callbacks_client(struct kex *kex) { +#ifdef WITH_OPENSSL + kex->kex[KEX_DH_GRP1_SHA1] = kex_gen_client; + kex->kex[KEX_DH_GRP14_SHA1] = kex_gen_client; + kex->kex[KEX_DH_GRP14_SHA256] = kex_gen_client; + kex->kex[KEX_DH_GRP16_SHA512] = kex_gen_client; + kex->kex[KEX_DH_GRP18_SHA512] = kex_gen_client; + kex->kex[KEX_DH_GEX_SHA1] = kexgex_client; + kex->kex[KEX_DH_GEX_SHA256] = kexgex_client; +# ifdef OPENSSL_HAS_ECC + kex->kex[KEX_ECDH_SHA2] = kex_gen_client; +# endif +#endif /* WITH_OPENSSL */ + kex->kex[KEX_C25519_SHA256] = kex_gen_client; + kex->kex[KEX_KEM_SNTRUP761X25519_SHA512] = kex_gen_client; +} + +void +kex_set_callbacks_server(struct kex *kex) { +#ifdef WITH_OPENSSL + kex->kex[KEX_DH_GRP1_SHA1] = kex_gen_server; + kex->kex[KEX_DH_GRP14_SHA1] = kex_gen_server; + kex->kex[KEX_DH_GRP14_SHA256] = kex_gen_server; + kex->kex[KEX_DH_GRP16_SHA512] = kex_gen_server; + kex->kex[KEX_DH_GRP18_SHA512] = kex_gen_server; + kex->kex[KEX_DH_GEX_SHA1] = kexgex_server; + kex->kex[KEX_DH_GEX_SHA256] = kexgex_server; +# ifdef OPENSSL_HAS_ECC + kex->kex[KEX_ECDH_SHA2] = kex_gen_server; +# endif +#endif /* WITH_OPENSSL */ + kex->kex[KEX_C25519_SHA256] = kex_gen_server; + kex->kex[KEX_KEM_SNTRUP761X25519_SHA512] = kex_gen_server; +} diff -ruN openssh-9.4p1/kexgex.c openssh-9.4p1+x509-14.2.1/kexgex.c --- openssh-9.4p1/kexgex.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/kexgex.c 2023-08-20 10:07:01.000000000 +0300 @@ -2,6 +2,7 @@ /* * Copyright (c) 2000 Niels Provos. All rights reserved. * Copyright (c) 2001 Markus Friedl. All rights reserved. + * Copyright (c) 2018-2021 Roumen Petrov. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -28,15 +29,10 @@ #ifdef WITH_OPENSSL -#include - -#include #include -#include "openbsd-compat/openssl-compat.h" +#include -#include "sshkey.h" -#include "cipher.h" #include "kex.h" #include "ssh2.h" #include "ssherr.h" @@ -66,8 +62,8 @@ return SSH_ERR_INVALID_ARGUMENT; if ((b = sshbuf_new()) == NULL) return SSH_ERR_ALLOC_FAIL; - if ((r = sshbuf_put_stringb(b, client_version)) < 0 || - (r = sshbuf_put_stringb(b, server_version)) < 0 || + if ((r = sshbuf_put_stringb(b, client_version)) != 0 || + (r = sshbuf_put_stringb(b, server_version)) != 0 || /* kexinit messages: fake header: len+SSH2_MSG_KEXINIT */ (r = sshbuf_put_u32(b, sshbuf_len(client_kexinit) + 1)) != 0 || (r = sshbuf_put_u8(b, SSH2_MSG_KEXINIT)) != 0 || @@ -87,7 +83,7 @@ sshbuf_free(b); return r; } -#ifdef DEBUG_KEXDH +#ifdef DEBUG_KEX sshbuf_dump(b, stderr); #endif if (ssh_digest_buffer(hash_alg, b, hash, *hashlen) != 0) { @@ -96,7 +92,7 @@ } sshbuf_free(b); *hashlen = ssh_digest_bytes(hash_alg); -#ifdef DEBUG_KEXDH +#ifdef DEBUG_KEX dump_digest("hash", hash, *hashlen); #endif return 0; diff -ruN openssh-9.4p1/kexgexc.c openssh-9.4p1+x509-14.2.1/kexgexc.c --- openssh-9.4p1/kexgexc.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/kexgexc.c 2023-08-20 10:07:01.000000000 +0300 @@ -1,7 +1,8 @@ -/* $OpenBSD: kexgexc.c,v 1.38 2021/12/19 22:08:06 djm Exp $ */ +/* $OpenBSD: kexgexc.c,v 1.37 2021/01/31 22:55:29 djm Exp $ */ /* * Copyright (c) 2000 Niels Provos. All rights reserved. * Copyright (c) 2001 Markus Friedl. All rights reserved. + * Copyright (c) 2014-2021 Roumen Petrov. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -30,32 +31,40 @@ #include -#include - #include #include #include #include -#include "openbsd-compat/openssl-compat.h" - -#include "sshkey.h" -#include "cipher.h" -#include "digest.h" #include "kex.h" -#include "log.h" -#include "packet.h" #include "dh.h" #include "ssh2.h" -#include "compat.h" -#include "dispatch.h" +#include "packet.h" #include "ssherr.h" -#include "sshbuf.h" +#include "log.h" +#include "digest.h" #include "misc.h" static int input_kex_dh_gex_group(int, u_int32_t, struct ssh *); static int input_kex_dh_gex_reply(int, u_int32_t, struct ssh *); + +/* + * Estimates the group order for a Diffie-Hellman group that has an + * attack complexity approximately the same as O(2**bits). + * Values from NIST Special Publication 800-57: Recommendation for Key + * Management Part 1 (rev 3) limited by the recommended maximum value + * from RFC4419 section 3. + */ +static inline u_int +dh_estimate(int bits) +{ + if (bits <= 112) return 2048; + if (bits <= 128) return 3072; + if (bits <= 192) return 7680; + return 8192; +} + int kexgex_client(struct ssh *ssh) { @@ -68,7 +77,7 @@ kex->min = DH_GRP_MIN; kex->max = DH_GRP_MAX; kex->nbits = nbits; - if (ssh->compat & SSH_BUG_DHGEX_LARGE) + if (ssh_compat_fellows(ssh, SSH_BUG_DHGEX_LARGE)) kex->nbits = MINIMUM(kex->nbits, 4096); /* New GEX request */ if ((r = sshpkt_start(ssh, SSH2_MSG_KEX_DH_GEX_REQUEST)) != 0 || @@ -77,12 +86,10 @@ (r = sshpkt_put_u32(ssh, kex->max)) != 0 || (r = sshpkt_send(ssh)) != 0) goto out; - debug("SSH2_MSG_KEX_DH_GEX_REQUEST(%u<%u<%u) sent", + /* used in dhgex regression test */ + debug("SSH2_MSG_KEX_DH_GEX_REQUEST sent: %u<%u<%u", kex->min, kex->nbits, kex->max); -#ifdef DEBUG_KEXDH - fprintf(stderr, "\nmin = %d, nbits = %d, max = %d\n", - kex->min, kex->nbits, kex->max); -#endif + debug("expecting SSH2_MSG_KEX_DH_GEX_GROUP"); ssh_dispatch_set(ssh, SSH2_MSG_KEX_DH_GEX_GROUP, &input_kex_dh_gex_group); @@ -96,9 +103,11 @@ { struct kex *kex = ssh->kex; BIGNUM *p = NULL, *g = NULL; - const BIGNUM *pub_key; int r, bits; + UNUSED(type); + UNUSED(seq); + debug("SSH2_MSG_KEX_DH_GEX_GROUP received"); ssh_dispatch_set(ssh, SSH2_MSG_KEX_DH_GEX_GROUP, &kex_protocol_error); @@ -111,27 +120,21 @@ r = SSH_ERR_DH_GEX_OUT_OF_RANGE; goto out; } - if ((kex->dh = dh_new_group(g, p)) == NULL) { + kex->pk = kex_new_dh_group(p, g); + if (kex->pk == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } - p = g = NULL; /* belong to kex->dh now */ + p = g = NULL; /* belong to kex->pk[dh] now */ /* generate and send 'e', client DH public key */ - if ((r = dh_gen_key(kex->dh, kex->we_need * 8)) != 0) - goto out; - DH_get0_key(kex->dh, &pub_key, NULL); - if ((r = sshpkt_start(ssh, SSH2_MSG_KEX_DH_GEX_INIT)) != 0 || - (r = sshpkt_put_bignum2(ssh, pub_key)) != 0 || + if ((r = kex_key_gen_dh(kex)) != 0 || + (r = sshpkt_start(ssh, SSH2_MSG_KEX_DH_GEX_INIT)) != 0 || + (r = sshpkt_write_dh_pub(ssh, kex->pk)) != 0 || (r = sshpkt_send(ssh)) != 0) goto out; debug("SSH2_MSG_KEX_DH_GEX_INIT sent"); -#ifdef DEBUG_KEXDH - DHparams_print_fp(stderr, kex->dh); - fprintf(stderr, "pub= "); - BN_print_fp(stderr, pub_key); - fprintf(stderr, "\n"); -#endif + debug("expecting SSH2_MSG_KEX_DH_GEX_REPLY"); ssh_dispatch_set(ssh, SSH2_MSG_KEX_DH_GEX_REPLY, &input_kex_dh_gex_reply); r = 0; @@ -146,29 +149,32 @@ { struct kex *kex = ssh->kex; BIGNUM *dh_server_pub = NULL; - const BIGNUM *pub_key, *dh_p, *dh_g; struct sshbuf *shared_secret = NULL; - struct sshbuf *tmp = NULL, *server_host_key_blob = NULL; + struct sshbuf *server_host_key_blob = NULL; struct sshkey *server_host_key = NULL; u_char *signature = NULL; u_char hash[SSH_DIGEST_MAX_LENGTH]; size_t slen, hashlen; int r; + UNUSED(type); + UNUSED(seq); + debug("SSH2_MSG_KEX_DH_GEX_REPLY received"); ssh_dispatch_set(ssh, SSH2_MSG_KEX_DH_GEX_REPLY, &kex_protocol_error); - /* key, cert */ - if ((r = sshpkt_getb_froms(ssh, &server_host_key_blob)) != 0) - goto out; - /* sshkey_fromb() consumes its buffer, so make a copy */ - if ((tmp = sshbuf_fromb(server_host_key_blob)) == NULL) { - r = SSH_ERR_ALLOC_FAIL; - goto out; - } - if ((r = sshkey_fromb(tmp, &server_host_key)) != 0 || - (r = kex_verify_host_key(ssh, server_host_key)) != 0) + /* hostkey */ + r = sshpkt_getb_froms(ssh, &server_host_key_blob); + if (r != 0) goto out; + + r = Xkey_from_blob(kex->hostkey_alg, + sshbuf_ptr(server_host_key_blob), sshbuf_len(server_host_key_blob), + &server_host_key); + if (r != SSH_ERR_SUCCESS) goto out; + + if ((r = kex_verify_host_key(ssh, server_host_key)) != 0) goto out; + /* DH parameter f, server public DH key, signed H */ if ((r = sshpkt_get_bignum2(ssh, &dh_server_pub)) != 0 || (r = sshpkt_get_string(ssh, &signature, &slen)) != 0 || @@ -180,60 +186,29 @@ } if ((r = kex_dh_compute_key(kex, dh_server_pub, shared_secret)) != 0) goto out; - if (ssh->compat & SSH_OLD_DHGEX) + if (ssh_compat_fellows(ssh, SSH_OLD_DHGEX)) kex->min = kex->max = -1; /* calc and verify H */ - DH_get0_key(kex->dh, &pub_key, NULL); - DH_get0_pqg(kex->dh, &dh_p, NULL, &dh_g); hashlen = sizeof(hash); - if ((r = kexgex_hash( - kex->hash_alg, - kex->client_version, - kex->server_version, - kex->my, - kex->peer, - server_host_key_blob, - kex->min, kex->nbits, kex->max, - dh_p, dh_g, - pub_key, - dh_server_pub, - sshbuf_ptr(shared_secret), sshbuf_len(shared_secret), - hash, &hashlen)) != 0) - goto out; - - if ((r = sshkey_verify(server_host_key, signature, slen, hash, - hashlen, kex->hostkey_alg, ssh->compat, NULL)) != 0) - goto out; - - if ((r = kex_derive_keys(ssh, hash, hashlen, shared_secret)) != 0 || - (r = kex_send_newkeys(ssh)) != 0) - goto out; - - /* save initial signature and hostkey */ - if ((kex->flags & KEX_INITIAL) != 0) { - if (kex->initial_hostkey != NULL || kex->initial_sig != NULL) { - r = SSH_ERR_INTERNAL_ERROR; - goto out; - } - if ((kex->initial_sig = sshbuf_new()) == NULL) { - r = SSH_ERR_ALLOC_FAIL; - goto out; - } - if ((r = sshbuf_put(kex->initial_sig, signature, slen)) != 0) - goto out; - kex->initial_hostkey = server_host_key; - server_host_key = NULL; - } - /* success */ + if ((r = kexgex_hash_client(kex, server_host_key_blob, dh_server_pub, + shared_secret, hash, &hashlen)) != 0) + goto out; + +{ ssh_verify_ctx ctx = { kex->hostkey_alg, server_host_key, &ssh->compat }; + + r = Xkey_verify(&ctx, signature, slen, hash, hashlen); + if (r != 0) goto out; +} + + if ((r = kex_derive_keys(ssh, hash, hashlen, shared_secret)) == 0) + r = kex_send_newkeys(ssh); out: explicit_bzero(hash, sizeof(hash)); - DH_free(kex->dh); - kex->dh = NULL; + kex_reset_crypto_keys(kex); BN_clear_free(dh_server_pub); sshbuf_free(shared_secret); sshkey_free(server_host_key); - sshbuf_free(tmp); sshbuf_free(server_host_key_blob); free(signature); return r; diff -ruN openssh-9.4p1/kexgexs.c openssh-9.4p1+x509-14.2.1/kexgexs.c --- openssh-9.4p1/kexgexs.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/kexgexs.c 2023-08-20 10:07:01.000000000 +0300 @@ -2,6 +2,7 @@ /* * Copyright (c) 2000 Niels Provos. All rights reserved. * Copyright (c) 2001 Markus Friedl. All rights reserved. + * Copyright (c) 2014-2021 Roumen Petrov. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -28,31 +29,19 @@ #ifdef WITH_OPENSSL - #include #include #include #include -#include - -#include "openbsd-compat/openssl-compat.h" - -#include "sshkey.h" -#include "cipher.h" -#include "digest.h" #include "kex.h" -#include "log.h" -#include "packet.h" #include "dh.h" #include "ssh2.h" -#ifdef GSSAPI -#include "ssh-gss.h" -#endif -#include "monitor_wrap.h" -#include "dispatch.h" +#include "packet.h" #include "ssherr.h" -#include "sshbuf.h" +#include "log.h" +#include "monitor_wrap.h" +#include "digest.h" #include "misc.h" static int input_kex_dh_gex_request(int, u_int32_t, struct ssh *); @@ -73,8 +62,9 @@ struct kex *kex = ssh->kex; int r; u_int min = 0, max = 0, nbits = 0; - const BIGNUM *dh_p, *dh_g; + UNUSED(type); + UNUSED(seq); debug("SSH2_MSG_KEX_DH_GEX_REQUEST received"); ssh_dispatch_set(ssh, SSH2_MSG_KEX_DH_GEX_REQUEST, &kex_protocol_error); @@ -98,22 +88,21 @@ } /* Contact privileged parent */ - kex->dh = PRIVSEP(choose_dh(min, nbits, max)); - if (kex->dh == NULL) { + kex->pk = PRIVSEP(kex_new_dh_group_bits(min, nbits, max)); + if (kex->pk == NULL) { (void)sshpkt_disconnect(ssh, "no matching DH grp found"); r = SSH_ERR_ALLOC_FAIL; goto out; } - debug("SSH2_MSG_KEX_DH_GEX_GROUP sent"); - DH_get0_pqg(kex->dh, &dh_p, NULL, &dh_g); + if ((r = sshpkt_start(ssh, SSH2_MSG_KEX_DH_GEX_GROUP)) != 0 || - (r = sshpkt_put_bignum2(ssh, dh_p)) != 0 || - (r = sshpkt_put_bignum2(ssh, dh_g)) != 0 || + (r = sshpkt_write_dh_group(ssh, kex->pk)) != 0 || (r = sshpkt_send(ssh)) != 0) goto out; + debug("SSH2_MSG_KEX_DH_GEX_GROUP sent"); /* Compute our exchange value in parallel with the client */ - if ((r = dh_gen_key(kex->dh, kex->we_need * 8)) != 0) + if ((r = kex_key_gen_dh(kex)) != 0) goto out; debug("expecting SSH2_MSG_KEX_DH_GEX_INIT"); @@ -128,7 +117,6 @@ { struct kex *kex = ssh->kex; BIGNUM *dh_client_pub = NULL; - const BIGNUM *pub_key, *dh_p, *dh_g; struct sshbuf *shared_secret = NULL; struct sshbuf *server_host_key_blob = NULL; struct sshkey *server_host_public, *server_host_private; @@ -137,11 +125,14 @@ size_t slen, hashlen; int r; + UNUSED(type); + UNUSED(seq); + debug("SSH2_MSG_KEX_DH_GEX_INIT received"); ssh_dispatch_set(ssh, SSH2_MSG_KEX_DH_GEX_INIT, &kex_protocol_error); - if ((r = kex_load_hostkey(ssh, &server_host_private, - &server_host_public)) != 0) + r = kex_load_host_keys(ssh, &server_host_public, &server_host_private); + if (r != SSH_ERR_SUCCESS) goto out; /* key, cert */ @@ -154,59 +145,44 @@ } if ((r = kex_dh_compute_key(kex, dh_client_pub, shared_secret)) != 0) goto out; + if ((server_host_key_blob = sshbuf_new()) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } - if ((r = sshkey_putb(server_host_public, server_host_key_blob)) != 0) - goto out; + r = Xkey_putb(kex->hostkey_alg, server_host_public, server_host_key_blob); + if (r != SSH_ERR_SUCCESS) goto out; +#ifdef DEBUG_KEXDH + dump_digestb("server public key:", server_host_key_blob); +#endif /* calc H */ - DH_get0_key(kex->dh, &pub_key, NULL); - DH_get0_pqg(kex->dh, &dh_p, NULL, &dh_g); hashlen = sizeof(hash); - if ((r = kexgex_hash( - kex->hash_alg, - kex->client_version, - kex->server_version, - kex->peer, - kex->my, - server_host_key_blob, - kex->min, kex->nbits, kex->max, - dh_p, dh_g, - dh_client_pub, - pub_key, - sshbuf_ptr(shared_secret), sshbuf_len(shared_secret), - hash, &hashlen)) != 0) + if ((r = kexgex_hash_server(kex, server_host_key_blob, dh_client_pub, + shared_secret, hash, &hashlen )) != 0) goto out; /* sign H */ - if ((r = kex->sign(ssh, server_host_private, server_host_public, - &signature, &slen, hash, hashlen, kex->hostkey_alg)) < 0) +{ ssh_sign_ctx ctx = { kex->hostkey_alg, server_host_private, &ssh->compat, NULL, NULL }; + + r = kex->xsign(ssh, &ctx, server_host_public, &signature, &slen, hash, hashlen); + if (r != 0) goto out; +} /* send server hostkey, DH pubkey 'f' and signed H */ if ((r = sshpkt_start(ssh, SSH2_MSG_KEX_DH_GEX_REPLY)) != 0 || (r = sshpkt_put_stringb(ssh, server_host_key_blob)) != 0 || - (r = sshpkt_put_bignum2(ssh, pub_key)) != 0 || /* f */ + (r = sshpkt_write_dh_pub(ssh, kex->pk)) != 0 || (r = sshpkt_put_string(ssh, signature, slen)) != 0 || (r = sshpkt_send(ssh)) != 0) goto out; - if ((r = kex_derive_keys(ssh, hash, hashlen, shared_secret)) != 0 || - (r = kex_send_newkeys(ssh)) != 0) - goto out; - - /* retain copy of hostkey used at initial KEX */ - if (kex->initial_hostkey == NULL && - (r = sshkey_from_private(server_host_public, - &kex->initial_hostkey)) != 0) - goto out; - /* success */ + if ((r = kex_derive_keys(ssh, hash, hashlen, shared_secret)) == 0) + r = kex_send_newkeys(ssh); out: explicit_bzero(hash, sizeof(hash)); - DH_free(kex->dh); - kex->dh = NULL; + kex_reset_crypto_keys(kex); BN_clear_free(dh_client_pub); sshbuf_free(shared_secret); sshbuf_free(server_host_key_blob); diff -ruN openssh-9.4p1/kex.h openssh-9.4p1+x509-14.2.1/kex.h --- openssh-9.4p1/kex.h 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/kex.h 2023-08-20 10:07:00.000000000 +0300 @@ -1,7 +1,7 @@ -/* $OpenBSD: kex.h,v 1.118 2023/03/06 12:14:48 dtucker Exp $ */ - +/* $OpenBSD: kex.h,v 1.117 2022/01/06 21:55:23 djm Exp $ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. + * Copyright (c) 2014-2021 Roumen Petrov. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -26,44 +26,17 @@ #ifndef KEX_H #define KEX_H +#include /* for sig_atomic_t */ + +#include "evp-compat.h" + #include "mac.h" #include "crypto_api.h" +#include "sshxkey.h" -#ifdef WITH_OPENSSL -# include -# include -# include -# ifdef OPENSSL_HAS_ECC -# include -# else /* OPENSSL_HAS_ECC */ -# define EC_KEY void -# define EC_GROUP void -# define EC_POINT void -# endif /* OPENSSL_HAS_ECC */ -#else /* WITH_OPENSSL */ -# define DH void -# define BIGNUM void -# define EC_KEY void -# define EC_GROUP void -# define EC_POINT void -#endif /* WITH_OPENSSL */ #define KEX_COOKIE_LEN 16 -#define KEX_DH1 "diffie-hellman-group1-sha1" -#define KEX_DH14_SHA1 "diffie-hellman-group14-sha1" -#define KEX_DH14_SHA256 "diffie-hellman-group14-sha256" -#define KEX_DH16_SHA512 "diffie-hellman-group16-sha512" -#define KEX_DH18_SHA512 "diffie-hellman-group18-sha512" -#define KEX_DHGEX_SHA1 "diffie-hellman-group-exchange-sha1" -#define KEX_DHGEX_SHA256 "diffie-hellman-group-exchange-sha256" -#define KEX_ECDH_SHA2_NISTP256 "ecdh-sha2-nistp256" -#define KEX_ECDH_SHA2_NISTP384 "ecdh-sha2-nistp384" -#define KEX_ECDH_SHA2_NISTP521 "ecdh-sha2-nistp521" -#define KEX_CURVE25519_SHA256 "curve25519-sha256" -#define KEX_CURVE25519_SHA256_OLD "curve25519-sha256@libssh.org" -#define KEX_SNTRUP761X25519_SHA512 "sntrup761x25519-sha512@openssh.com" - #define COMP_NONE 0 /* pre-auth compression (COMP_ZLIB) is only supported in the client */ #define COMP_ZLIB 1 @@ -108,7 +81,6 @@ /* kex->flags */ #define KEX_INIT_SENT 0x0001 #define KEX_INITIAL 0x0002 -#define KEX_HAS_PUBKEY_HOSTBOUND 0x0004 #define KEX_RSA_SHA2_256_SUPPORTED 0x0008 /* only set in server for now */ #define KEX_RSA_SHA2_512_SUPPORTED 0x0010 /* only set in server for now */ @@ -134,7 +106,6 @@ }; struct ssh; -struct sshbuf; struct kex { struct newkeys *newkeys[MODE_MAX]; @@ -143,35 +114,29 @@ int server; char *name; char *hostkey_alg; - int hostkey_type; - int hostkey_nid; u_int kex_type; - char *server_sig_algs; + char *pkalgs; int ext_info_c; struct sshbuf *my; struct sshbuf *peer; struct sshbuf *client_version; struct sshbuf *server_version; struct sshbuf *session_id; - struct sshbuf *initial_sig; - struct sshkey *initial_hostkey; sig_atomic_t done; u_int flags; int hash_alg; int ec_nid; char *failed_choice; int (*verify_host_key)(struct sshkey *, struct ssh *); - struct sshkey *(*load_host_public_key)(int, int, struct ssh *); - struct sshkey *(*load_host_private_key)(int, int, struct ssh *); + struct sshkey *(*find_host_public_key)(const char* pkalg, struct ssh *); + struct sshkey *(*find_host_private_key)(const char* pkalg, struct ssh *); int (*host_key_index)(struct sshkey *, int, struct ssh *); - int (*sign)(struct ssh *, struct sshkey *, struct sshkey *, - u_char **, size_t *, const u_char *, size_t, const char *); + int (*xsign)(struct ssh *ssh, ssh_sign_ctx *ctx, struct sshkey *pub, + u_char **sigp, size_t *lenp, const u_char *data, size_t datalen); int (*kex[KEX_MAX])(struct ssh *); /* kex specific state */ - DH *dh; /* DH */ + EVP_PKEY *pk; u_int min, max, nbits; /* GEX */ - EC_KEY *ec_client_key; /* ECDH */ - const EC_GROUP *ec_group; /* ECDH */ u_char c25519_client_key[CURVE25519_SIZE]; /* 25519 + KEM */ u_char c25519_client_pubkey[CURVE25519_SIZE]; /* 25519 */ u_char sntrup761_client_key[crypto_kem_sntrup761_SECRETKEYBYTES]; /* KEM */ @@ -182,23 +147,21 @@ char *kex_alg_list(char); char *kex_names_cat(const char *, const char *); int kex_assemble_names(char **, const char *, const char *); -void kex_proposal_populate_entries(struct ssh *, char *prop[PROPOSAL_MAX], - const char *, const char *, const char *, const char *, const char *); -void kex_proposal_free_entries(char *prop[PROPOSAL_MAX]); -int kex_exchange_identification(struct ssh *, int, const char *); +int kex_exchange_identification(struct ssh *, int); struct kex *kex_new(void); +void kex_set_callbacks_client(struct kex *); +void kex_set_callbacks_server(struct kex *); int kex_ready(struct ssh *, char *[PROPOSAL_MAX]); int kex_setup(struct ssh *, char *[PROPOSAL_MAX]); void kex_free_newkeys(struct newkeys *); void kex_free(struct kex *); +void kex_reset_crypto_keys(struct kex *); int kex_buf2prop(struct sshbuf *, int *, char ***); int kex_prop2buf(struct sshbuf *, char *proposal[PROPOSAL_MAX]); void kex_prop_free(char **); -int kex_load_hostkey(struct ssh *, struct sshkey **, struct sshkey **); -int kex_verify_host_key(struct ssh *, struct sshkey *); int kex_send_kexinit(struct ssh *); int kex_input_kexinit(int, u_int32_t, struct ssh *); @@ -208,10 +171,12 @@ int kex_send_newkeys(struct ssh *); int kex_start_rekex(struct ssh *); +int kex_load_host_keys(struct ssh *ssh, struct sshkey **hostpub, struct sshkey **hostpriv); +int kex_verify_host_key(struct ssh *ssh, struct sshkey *key); + + int kexgex_client(struct ssh *); int kexgex_server(struct ssh *); -int kex_gen_client(struct ssh *); -int kex_gen_server(struct ssh *); int kex_dh_keypair(struct kex *); int kex_dh_enc(struct kex *, const struct sshbuf *, struct sshbuf **, @@ -234,7 +199,9 @@ int kex_kem_sntrup761x25519_dec(struct kex *, const struct sshbuf *, struct sshbuf **); -int kex_dh_keygen(struct kex *); +int kex_key_init_dh(struct kex *); +int kex_key_gen_dh(struct kex *); +int kex_key_validate_public_dh(struct kex *, const BIGNUM *); int kex_dh_compute_key(struct kex *, BIGNUM *, struct sshbuf *); int kexgex_hash(int, const struct sshbuf *, const struct sshbuf *, @@ -244,26 +211,35 @@ const BIGNUM *, const u_char *, size_t, u_char *, size_t *); +int kexgex_hash_client(const struct kex *kex, + const struct sshbuf *key_blob, const BIGNUM *peer_pub, + const struct sshbuf *shared_secret, + u_char *hash, size_t *hashlen); + +int kexgex_hash_server(const struct kex *kex, + const struct sshbuf *key_blob, const BIGNUM *peer_pub, + const struct sshbuf *shared_secret, + u_char *hash, size_t *hashlen); + void kexc25519_keygen(u_char key[CURVE25519_SIZE], u_char pub[CURVE25519_SIZE]) __attribute__((__bounded__(__minbytes__, 1, CURVE25519_SIZE))) __attribute__((__bounded__(__minbytes__, 2, CURVE25519_SIZE))); -int kexc25519_shared_key(const u_char key[CURVE25519_SIZE], - const u_char pub[CURVE25519_SIZE], struct sshbuf *out) - __attribute__((__bounded__(__minbytes__, 1, CURVE25519_SIZE))) - __attribute__((__bounded__(__minbytes__, 2, CURVE25519_SIZE))); int kexc25519_shared_key_ext(const u_char key[CURVE25519_SIZE], const u_char pub[CURVE25519_SIZE], struct sshbuf *out, int) __attribute__((__bounded__(__minbytes__, 1, CURVE25519_SIZE))) __attribute__((__bounded__(__minbytes__, 2, CURVE25519_SIZE))); -#if defined(DEBUG_KEX) || defined(DEBUG_KEXDH) || defined(DEBUG_KEXECDH) -void dump_digest(const char *, const u_char *, int); -#endif -#if !defined(WITH_OPENSSL) || !defined(OPENSSL_HAS_ECC) -# undef EC_KEY -# undef EC_GROUP -# undef EC_POINT +EVP_PKEY* kex_new_dh_group_bits(int min, int wantbits, int max); +EVP_PKEY* kex_new_dh_group(BIGNUM *modulus, BIGNUM *gen); + +int sshbuf_kex_write_dh_group(struct sshbuf *buf, EVP_PKEY *pk); +int sshbuf_kex_write_dh_pub(struct sshbuf *buf, EVP_PKEY *pk); + + +#if defined(DEBUG_KEX) || defined(DEBUG_KEXDH) || defined(DEBUG_KEXECDH) +void dump_digest(const char *, const u_char *, size_t); +void dump_digestb(const char *, const struct sshbuf *); #endif #endif diff -ruN openssh-9.4p1/kexsntrup761x25519.c openssh-9.4p1+x509-14.2.1/kexsntrup761x25519.c --- openssh-9.4p1/kexsntrup761x25519.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/kexsntrup761x25519.c 2023-08-20 10:07:01.000000000 +0300 @@ -1,4 +1,4 @@ -/* $OpenBSD: kexsntrup761x25519.c,v 1.2 2021/12/05 12:28:27 jsg Exp $ */ +/* $OpenBSD: kexsntrup761x25519.c,v 1.1 2020/12/29 00:59:15 djm Exp $ */ /* * Copyright (c) 2019 Markus Friedl. All rights reserved. * @@ -24,8 +24,7 @@ */ #include "includes.h" - -#ifdef USE_SNTRUP761X25519 +#ifdef ENABLE_KEX_SNTRUP761X25519 #include @@ -133,8 +132,7 @@ dump_digest("server cipher text:", ciphertext, crypto_kem_sntrup761_CIPHERTEXTBYTES); dump_digest("server kem key:", kem_key, crypto_kem_sntrup761_BYTES); - dump_digest("concatenation of KEM key and ECDH shared key:", - sshbuf_ptr(buf), sshbuf_len(buf)); + dump_digestb("concatenation of KEM key and ECDH shared key:", buf); #endif /* string-encoded hash is resulting shared secret */ sshbuf_reset(buf); @@ -142,7 +140,7 @@ ssh_digest_bytes(kex->hash_alg))) != 0) goto out; #ifdef DEBUG_KEXECDH - dump_digest("encoded shared secret:", sshbuf_ptr(buf), sshbuf_len(buf)); + dump_digestb("encoded shared secret:", buf); #endif *server_blobp = server_blob; *shared_secretp = buf; @@ -198,15 +196,14 @@ goto out; #ifdef DEBUG_KEXECDH dump_digest("client kem key:", kem_key, crypto_kem_sntrup761_BYTES); - dump_digest("concatenation of KEM key and ECDH shared key:", - sshbuf_ptr(buf), sshbuf_len(buf)); + dump_digestb("concatenation of KEM key and ECDH shared key:", buf); #endif sshbuf_reset(buf); if ((r = sshbuf_put_string(buf, hash, ssh_digest_bytes(kex->hash_alg))) != 0) goto out; #ifdef DEBUG_KEXECDH - dump_digest("encoded shared secret:", sshbuf_ptr(buf), sshbuf_len(buf)); + dump_digestb("encoded shared secret:", buf); #endif if (decoded != 0) { r = SSH_ERR_SIGNATURE_INVALID; @@ -220,32 +217,8 @@ return r; } -#else - -#include "ssherr.h" - -struct kex; -struct sshbuf; -struct sshkey; - -int -kex_kem_sntrup761x25519_keypair(struct kex *kex) -{ - return SSH_ERR_SIGN_ALG_UNSUPPORTED; -} +#else /* ENABLE_KEX_SNTRUP761X25519 */ -int -kex_kem_sntrup761x25519_enc(struct kex *kex, - const struct sshbuf *client_blob, struct sshbuf **server_blobp, - struct sshbuf **shared_secretp) -{ - return SSH_ERR_SIGN_ALG_UNSUPPORTED; -} +typedef int ssh_kexsntrup761x25519_empty_translation_unit; -int -kex_kem_sntrup761x25519_dec(struct kex *kex, - const struct sshbuf *server_blob, struct sshbuf **shared_secretp) -{ - return SSH_ERR_SIGN_ALG_UNSUPPORTED; -} -#endif /* USE_SNTRUP761X25519 */ +#endif /* ENABLE_KEX_SNTRUP761X25519 */ diff -ruN openssh-9.4p1/key-eng.c openssh-9.4p1+x509-14.2.1/key-eng.c --- openssh-9.4p1/key-eng.c 1970-01-01 02:00:00.000000000 +0200 +++ openssh-9.4p1+x509-14.2.1/key-eng.c 2023-08-20 10:07:01.000000000 +0300 @@ -0,0 +1,934 @@ +/* + * Copyright (c) 2011-2023 Roumen Petrov. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifndef USE_OPENSSL_PROVIDER +/* TODO: implement OpenSSL 4.0 API, as OpenSSL 3.* is quite nonfunctional */ +# define OPENSSL_SUPPRESS_DEPRECATED +#endif + +#define SSHKEY_INTERNAL +#include "includes.h" + +#include +#include + +#include +#ifdef USE_OPENSSL_STORE2 +# include +#endif +#include "evp-compat.h" + +#include "key-eng.h" +#include "ssh-x509.h" + +#include "misc.h" +#include "log.h" +#include "xmalloc.h" +#include "ssherr.h" + +/* structure reserved for future use */ +typedef struct ssh_pw_cb_data { + const void *password; +} SSH_PW_CB_DATA; + + +static UI_METHOD *ssh_ui_method = NULL; + +/**/ +static int +ui_open(UI *ui) { + return(UI_method_get_opener(UI_OpenSSL())(ui)); +} + + +static int +ui_read(UI *ui, UI_STRING *uis) { + enum UI_string_types uis_type; + int ui_flags; + + ui_flags = UI_get_input_flags(uis); + uis_type = UI_get_string_type(uis); + + if (ui_flags & UI_INPUT_FLAG_DEFAULT_PWD) { + SSH_PW_CB_DATA* cb_data = (SSH_PW_CB_DATA*)UI_get0_user_data(ui); + if (cb_data != NULL) { + switch(uis_type) { + case UIT_PROMPT: + case UIT_VERIFY: { + const char *password = cb_data->password; + if (password && password[0] != '\0') { + UI_set_result(ui, uis, password); + return(1); + } + } break; + default: + break; + } + } + } + +{ /* use own method to prompt properly */ + int flags = RP_USE_ASKPASS | RP_ALLOW_STDIN; + if (ui_flags & UI_INPUT_FLAG_ECHO) + flags |= RP_ECHO; + + switch(uis_type) { + case UIT_PROMPT: + case UIT_VERIFY: { + const char *prompt; + char *password; + + prompt = UI_get0_output_string(uis); + debug3_f("read_passphrase prompt=%s", prompt); + password = read_passphrase(prompt, flags); + UI_set_result(ui, uis, password); + memset(password, 'x', strlen(password)); + free(password); + return(1); + } break; + case UIT_INFO: { + const char *s = UI_get0_output_string(uis); + debug_f("UIT_INFO '%s'", s); + return(1); + } break; + case UIT_ERROR: { + const char *s = UI_get0_output_string(uis); + error_f("UIT_ERROR '%s'", s); + return(1); + } break; + default: + break; + } +} + + return(UI_method_get_reader(UI_OpenSSL())(ui, uis)); +} + + +static int +ui_write(UI *ui, UI_STRING *uis) { + enum UI_string_types uis_type; + int ui_flags; + + ui_flags = UI_get_input_flags(uis); + uis_type = UI_get_string_type(uis); + + if (ui_flags & UI_INPUT_FLAG_DEFAULT_PWD) { + SSH_PW_CB_DATA* cb_data = (SSH_PW_CB_DATA*)UI_get0_user_data(ui); + if (cb_data != NULL) { + switch(uis_type) { + case UIT_PROMPT: + case UIT_VERIFY: { + const char *password = cb_data->password; + if (password && password[0] != '\0') { + return(1); + } + } break; + default: + break; + } + } + } + switch(uis_type) { + case UIT_INFO: { + const char *s = UI_get0_output_string(uis); + debug_f("UIT_INFO '%s'", s); + return(1); + } break; + case UIT_ERROR: { + const char *s = UI_get0_output_string(uis); + error_f("UIT_ERROR '%s'", s); + return(1); + } break; + default: + break; + } + return(UI_method_get_writer(UI_OpenSSL())(ui, uis)); +} + + +static int +ui_close(UI *ui) { + return(UI_method_get_closer(UI_OpenSSL())(ui)); +} + + +static int/*bool*/setup_ssh_ui_method(void); +static void destroy_ssh_ui_method(void); + + +static int/*bool*/ +setup_ssh_ui_method() { + ssh_ui_method = UI_create_method("PKIX-SSH application user interface"); + + if (ssh_ui_method == NULL) return(0); + + if ((UI_method_set_opener(ssh_ui_method, ui_open ) < 0) + || (UI_method_set_reader(ssh_ui_method, ui_read ) < 0) + || (UI_method_set_writer(ssh_ui_method, ui_write) < 0) + || (UI_method_set_closer(ssh_ui_method, ui_close) < 0)) { + destroy_ssh_ui_method(); + return(0); + } + return(1); +} + + +static void +destroy_ssh_ui_method() { + if (ssh_ui_method == NULL) return; + + UI_destroy_method(ssh_ui_method); + ssh_ui_method = NULL; +} + + +static char* +ignore_suffixes(const char *filename) { + char* keyid; + size_t len = strlen(filename); + + /* ignore lame certificates "-cert" */ +{ const char sfx[5] = "-cert"; + if (len >= sizeof(sfx)) { + const char *s = filename + len - sizeof(sfx); + if (strncmp(s, sfx, sizeof(sfx)) == 0) + return NULL; + } +} + /* ignore lame certificates "-cert.pub" */ +{ const char sfx[9] = "-cert.pub"; + if (len >= sizeof(sfx)) { + const char *s = filename + len - sizeof(sfx); + if (strncmp(s, sfx, sizeof(sfx)) == 0) + return NULL; + } +} + + keyid = xstrdup(filename); /*fatal on error*/ + + if (len > 4) { + /* drop suffix ".pub" from copy */ + char *s = keyid + len - 4; + if (strncmp(s, ".pub", 4) == 0) + *s = '\0'; + } + return keyid; +} + + +#ifdef USE_OPENSSL_ENGINE +static void +eng_try_load_cert(ENGINE *e, const char *keyid, EVP_PKEY *pk, struct sshkey *k) { + X509* x509 = NULL; + int ctrl_ret = 0; + + if (e == NULL) + return; + + if ((k->type != KEY_RSA) && +#ifdef OPENSSL_HAS_ECC + (k->type != KEY_ECDSA) && +#endif + (k->type != KEY_DSA)) + return; + + /* try to load certificate with LOAD_CERT_EVP command */ + { + struct { + EVP_PKEY *pkey; + X509 *x509; + } param = {NULL, NULL}; + param.pkey = pk; + + ctrl_ret = ENGINE_ctrl_cmd(e, "LOAD_CERT_EVP", 0, ¶m, 0, 0); + debug3_f("eng cmd LOAD_CERT_EVP return %d", ctrl_ret); + if (ctrl_ret == 1) + x509 = param.x509; + } + + /* try to load certificate with LOAD_CERT_CTRL command */ + if (ctrl_ret != 1) { + struct { + const char *keyid; + X509 *x509; + } param = {NULL, NULL}; + param.keyid = keyid; + + ctrl_ret = ENGINE_ctrl_cmd(e, "LOAD_CERT_CTRL", 0, ¶m, 0, 0); + debug3_f("eng cmd LOAD_CERT_CTRL return %d", ctrl_ret); + if (ctrl_ret == 1) + x509 = param.x509; + } + debug3_f("certificate=%p", (void*)x509); + + if (x509 == NULL) + return; + + if (ssh_x509_set_cert(k, x509, NULL)) + x509key_build_chain(k); + else + error_f("can not set X.509 certificate to key "); +} + + +static ENGINE* +split_eng_keyid(const char *keyid, char **engkeyid) { + ENGINE* e = NULL; + char *p, *q; + + q = xstrdup(keyid); /*fatal on error*/ + + p = strchr(q, ':'); + if (p == NULL) { + fatal_f("missing engine identifier"); + goto done; /*;-)*/ + } + *p = '\0'; + p++; + if (*p == '\0') { + fatal_f("missing key identifier"); + goto done; /*;-)*/ + } + + e = ENGINE_by_id(q); + if (e != NULL) { + *engkeyid = xstrdup(p); + } +done: + free(q); + return(e); +} + + +int +engine_load_private(const char *name, const char *passphrase, + struct sshkey **keyp, char **commentp +) { + int ret; + ENGINE *e = NULL; + char *key_id = NULL; + const char *e_id; + EVP_PKEY *pk = NULL; + struct sshkey *prv = NULL; + + UNUSED(passphrase); + if (keyp != NULL) *keyp = NULL; + if (commentp != NULL) *commentp = NULL; + + e = split_eng_keyid(name, &key_id); + if (e == NULL) { + ret = SSH_ERR_INVALID_ARGUMENT; + goto done; + } + e_id = ENGINE_get_id(e); + + pk = ENGINE_load_private_key(e, key_id, ssh_ui_method, NULL); + if (pk == NULL) { + error_crypto_fmt("ENGINE_load_private_key", "engine %s", e_id); + ret = SSH_ERR_KEY_NOT_FOUND; + goto done; + } + + ret = sshkey_from_pkey(pk, &prv); + if (ret != SSH_ERR_SUCCESS) goto done; + + /* TODO: use EVP_PKEY from sshkey */ + eng_try_load_cert(e, key_id, pk, prv); + debug3("ENGINE private key type: %s", sshkey_type(prv)); + + pk = NULL; /* transferred */ + + if (commentp != NULL) + xasprintf(commentp, "engine:%s:%s", e_id, key_id); + + if (keyp != NULL) { + *keyp = prv; + prv = NULL; + } + +done: + EVP_PKEY_free(pk); + free(key_id); + if (e != NULL) { + /* check for NULL to avoid openssl error*/ + ENGINE_free(e); + } + debug("read ENGINE private key done: type %s", (prv ? sshkey_type(prv) : "")); + sshkey_free(prv); + return ret; +} + + +int +engine_try_load_public(const char *name, struct sshkey **keyp, char **commentp) { + int ret = SSH_ERR_INTERNAL_ERROR; + const char *url = NULL; + ENGINE *e = NULL; + char *key_id = NULL; + EVP_PKEY *pk = NULL; + struct sshkey *k = NULL; + + debug3_f("name=%s", name); + if (keyp != NULL) *keyp = NULL; + if (commentp != NULL) *commentp = NULL; + + url = ignore_suffixes(name); +/* NOTE: For external keys simulate "missing" file. + * This suppress extra messages due to faulty load control in ssh.c + */ + if (url == NULL) { + errno = ENOENT; + return SSH_ERR_SYSTEM_ERROR; + } + + debug3_f("url=%s", url); + + e = split_eng_keyid(url, &key_id); + if (e == NULL) { + ret = SSH_ERR_INVALID_ARGUMENT; + goto done; + } + + pk = ENGINE_load_public_key(e, key_id, ssh_ui_method, NULL); + if (pk == NULL) { + error_crypto_fmt("ENGINE_load_public_key", "engine %s", ENGINE_get_id(e)); + /* fatal here to avoid PIN lock, for instance + * when ssh-askpass program is missing. + * NOTE programs still try to load public key many times! + */ + fatal_f("avoid device locks ..."); + /* TODO library mode in case of failure */ + ret = SSH_ERR_KEY_NOT_FOUND; + goto done; + } + + ret = sshkey_from_pkey(pk, &k); + if (ret != SSH_ERR_SUCCESS) goto done; + + /* TODO: use EVP_PKEY from sshkey */ + eng_try_load_cert(e, key_id, pk, k); + debug3("ENGINE public key type: %s", sshkey_type(k)); + + pk = NULL; /* transferred */ + + if (commentp != NULL) + xasprintf(commentp, "engine:%s", url); + + if (keyp != NULL) { + *keyp = k; + k = NULL; + } + +done: + sshkey_free(k); + EVP_PKEY_free(pk); + free(key_id); + free((void*)url); + if (e != NULL) { + /* check for NULL to avoid openssl error*/ + ENGINE_free(e); + } + return(ret); +} + + +static ENGINE* +try_load_engine(const char *engine) { + ENGINE *e = NULL; + int self_registered = 0; + + if (engine == NULL) return NULL; + + /* Check if engine is not already loaded by openssl + * (as internal or from config file). + * If is not loaded we will call ENGINE_add to keep it + * loaded and registered for subsequent use. + */ + for (e = ENGINE_get_first(); e != NULL; e = ENGINE_get_next(e)) { + if (strcmp(engine, ENGINE_get_id(e)) == 0) { + /* with increase of structural reference */ + goto done; + } + } + + e = ENGINE_by_id(engine); + if (e == NULL) { + error_crypto("ENGINE_by_id"); + goto done; + } + +{ /* OpenSSL 1.0.1g start to register engines internaly! + * So we try to find our engine in internal list and if not + * found we use ENGINE_add to register it for compatibility + * with previous OpenSSL versions. + * Loop on all entries to avoid increase of structural + * reference. + */ + ENGINE *g; + for (g = ENGINE_get_first(); g != NULL; g = ENGINE_get_next(g)) { + if (strcmp(engine, ENGINE_get_id(g)) == 0) + self_registered = 1; + } +} + + if (!self_registered && !ENGINE_add(e)) { + error_crypto("ENGINE_add"); + /*ENGINE_free(e);?*/ + e = NULL; + } + +done: + if (e != NULL) + debug3_f("engine '%s' loaded", ENGINE_get_name(e)); + else + debug3_f("cannot load engine '%s'", engine); + return e; +} + + +static ENGINE* +ssh_engine_setup(const char *engine) { + int ctrl_ret; + ENGINE *e = NULL; + + e = try_load_engine(engine); + if (e == NULL) return NULL; + + if (!ENGINE_init(e)) { + error_crypto("ENGINE_init"); + return NULL; + } + + ctrl_ret = ENGINE_ctrl_cmd(e, "SET_USER_INTERFACE", 0, ssh_ui_method, 0, 1); + if (!ctrl_ret) + debug3_crypto_fmt("ENGINE_ctrl_cmd", + "engine %s, command SET_USER_INTERFACE", + engine); + + if (!ENGINE_free(e)) e = NULL; + + return e; +} + + +static void +ssh_engine_reset(const char *engine) { + ENGINE *e = NULL; + + e = ENGINE_by_id(engine); + if (e == NULL) return; + + /* decrease functional&structural reference from load - ENGINE_init */ + ENGINE_finish(e); + + /* decrease structural reference from above - ENGINE_by_id */ + ENGINE_free(e); +} + + +#define WHITESPACE " \t\r\n" +/* hold list with names of used engines to free at shutdown */ +static struct sshbuf *eng_list = NULL; + +/* name of currect engine to process */ +static char *eng_name = NULL; + + +static int/*bool*/ +process_engconfig_line(char *line, const char *filename, int linenum) { + int ret = 1; + size_t len; + char *s, *keyword, *arg; + ENGINE *e; + int ctrl_ret, r; + + /* strip trailing whitespace */ + len = strlen(line); + s = line + len - 1; + for (; len > 0; s--, len--) { + int ch = (unsigned char)*s; + if (strchr(WHITESPACE, ch) == NULL) + break; + *s = '\0'; + } + + /* ignore leading whitespace */ + s = line; + if (*s == '\0') return 1; + keyword = strdelim(&s); + if (keyword == NULL) return 1; + if (*keyword == '\0') + keyword = strdelim(&s); + if (keyword == NULL) return 1; + + /* ignore comments */ + if (*keyword == '#') return 1; + + if (strcasecmp(keyword, "engine") == 0) { + arg = strdelim(&s); + if (!arg || *arg == '\0') { + error("%.200s line %d: missing engine identifier" + , filename, linenum); + ret = 0; + goto done; + } + + e = ssh_engine_setup(arg); + if (e == NULL) { + error("%.200s line %d: cannot load engine %s", + filename, linenum, arg); + ret = 0; + goto done; + } + free(eng_name); + eng_name = xstrdup(arg); /*fatal on error*/ + r = sshbuf_put_cstring(eng_list, eng_name); + if (r != 0) { + error_fr(r, "buffer error"); + ret = 0; + goto done; + } + } + else { + if (eng_name == NULL) { + error("%.200s line %d: engine is not specified" + , filename, linenum); + ret = 0; + goto done; + } + + e = ENGINE_by_id(eng_name); + if (e == NULL) { + error("%.200s line %d: engine(%s) not found" + , filename, linenum, eng_name); + ret = 0; + goto done; + } + + arg = strdelim(&s); + + ctrl_ret = ENGINE_ctrl_cmd_string(e, keyword, arg, 0); + if (!ctrl_ret) { + error_crypto("ENGINE_ctrl_cmd_string"); + error("%.200s line %d: engine(%s) command fail" + , filename, linenum, eng_name); + ret = 0; + } + + ENGINE_free(e); + } + +done: + /* check that there is no garbage at end of line */ + if ((arg = strdelim(&s)) != NULL && *arg != '\0') { + error("%.200s line %d: garbage at end of line - '%.200s'.", + filename, linenum, arg); + ret = 0; + } + + return ret; +} + + +/* + * Reads the engine config file and execute commands accordingly. + * If the file does not exist, just exit. + */ +int/*bool*/ +process_engconfig_file(const char *filename) { + int ret = 1; /*true on empty file*/ + FILE *f; + + debug3("reading engine configuration options from '%s'", filename); + + f = fopen(filename, "r"); + if (f == NULL) return 0; + + {/*always check permissions on user engine file*/ + char errmsg[1024]; + if (safe_usr_fileno(fileno(f), filename, + errmsg, sizeof(errmsg)) == -1) { + error("%s", errmsg); + ret = 0; + goto done; + } + } + +{ char line[1024]; + int linenum = 0; + while (fgets(line, sizeof(line), f) != NULL) { + linenum++; + ret = process_engconfig_line(line, filename, linenum); + if (!ret) break; + } +} + +done: +{ int oerrno = errno; + fclose(f); + errno = oerrno; +} + return ret; +} +#endif /*def USE_OPENSSL_ENGINE*/ + + +#ifdef USE_OPENSSL_STORE2 +struct STORE_KEY_DATA_st { + EVP_PKEY *pk; + STACK_OF(X509) *chain; +}; +typedef struct STORE_KEY_DATA_st STORE_KEY_DATA; + +static STORE_KEY_DATA* +STORE_KEY_DATA_new(void) { + STORE_KEY_DATA* p; + + p = malloc(sizeof(STORE_KEY_DATA)); + if (p == NULL) return NULL; + + p->chain = sk_X509_new_null(); + if (p->chain == NULL) { + free(p); + return NULL; + } + + p->pk = NULL; + return p; +} + +static void +STORE_KEY_DATA_free(STORE_KEY_DATA* p) { + if (p == NULL) return; + + sk_X509_pop_free(p->chain, X509_free); + EVP_PKEY_free(p->pk); + free(p); +} + + +static STORE_KEY_DATA* +store_load_key(const char *url) { + STORE_KEY_DATA *ret; + OSSL_STORE_CTX *store_ctx; + + ret = STORE_KEY_DATA_new(); + if (ret == NULL) return NULL; + + store_ctx = OSSL_STORE_open(url, ssh_ui_method, NULL, NULL, NULL); + debug3_f("ctx: %p", (void*)store_ctx); + do_log_crypto_errors(SYSLOG_LEVEL_DEBUG3); + if (store_ctx == NULL) goto done; + + while (!OSSL_STORE_eof(store_ctx) ) { + OSSL_STORE_INFO *store_info; + int info_type; + + store_info = OSSL_STORE_load(store_ctx); + if (store_info == NULL) break; + + info_type = OSSL_STORE_INFO_get_type(store_info); + debug3_f("type: %d", info_type); + switch (info_type) { + case OSSL_STORE_INFO_PKEY: { + ret->pk = OSSL_STORE_INFO_get0_PKEY(store_info); + EVP_PKEY_up_ref(ret->pk); + } break; + case OSSL_STORE_INFO_CERT: { + X509 *x = OSSL_STORE_INFO_get0_CERT(store_info); + X509_up_ref(x); + sk_X509_insert(ret->chain, x, -1 /*last*/); + } break; + } + OSSL_STORE_INFO_free(store_info); + } + do_log_crypto_errors(SYSLOG_LEVEL_DEBUG3); + OSSL_STORE_close(store_ctx); + +done: + if (ret->pk == NULL) { + STORE_KEY_DATA_free(ret); + return NULL; + } + return ret; +} + + +static void +store_set_key_certs(STORE_KEY_DATA *kd, struct sshkey *key) { + int n, len; + X509 *x = NULL; + + len = sk_X509_num(kd->chain); + if (len <= 0) return; + + for (n = 0; n < sk_X509_num(kd->chain); n++) { + x = sk_X509_value(kd->chain, n); + + if (ssh_EVP_PKEY_eq(kd->pk, X509_get0_pubkey(x)) == 1) + break; + } + if (n >= len) { + debug3_f("no certificate that match private key"); + return; + } + + x = sk_X509_delete(kd->chain, n); + (void)ssh_x509_set_cert(key, x, kd->chain); +} + + +int +store_load_private(const char *name, const char *passphrase, + struct sshkey **keyp, char **commentp +) { + int ret; + STORE_KEY_DATA *kd = NULL; + struct sshkey *prv = NULL; + + UNUSED(passphrase); + debug3_f("name=%s", name); + + if (keyp != NULL) *keyp = NULL; + if (commentp != NULL) *commentp = NULL; + + kd = store_load_key(name); + if (kd == NULL) { + ret = SSH_ERR_KEY_NOT_FOUND; + goto done; + } + + ret = sshkey_from_pkey(kd->pk, &prv); + if (ret != SSH_ERR_SUCCESS) goto done; + + store_set_key_certs(kd, prv); + debug3("STORE private key type: %s", sshkey_type(prv)); + + kd->pk = NULL; /* transferred */ + + if (commentp != NULL) + xasprintf(commentp, "store:%s", name); + + if (keyp != NULL) { + *keyp = prv; + prv = NULL; + } + +done: + sshkey_free(prv); + STORE_KEY_DATA_free(kd); + return ret; +} + + +int +store_try_load_public(const char *name, struct sshkey **keyp, char **commentp) { + int ret; + const char *url = NULL; + STORE_KEY_DATA *kd = NULL; + struct sshkey *k = NULL; + + debug3_f("name=%s", name); + if (keyp != NULL) *keyp = NULL; + if (commentp != NULL) *commentp = NULL; + + url = ignore_suffixes(name); +/* NOTE: For external keys simulate "missing" file. + * This suppress extra messages due to faulty load control in ssh.c + */ + if (url == NULL) { + errno = ENOENT; + return SSH_ERR_SYSTEM_ERROR; + } + + debug3_f("url=%s", url); + + kd = store_load_key(url); + if (kd == NULL) { + ret = SSH_ERR_KEY_NOT_FOUND; + goto done; + } + + ret = sshkey_from_pkey(kd->pk, &k); + if (ret != SSH_ERR_SUCCESS) goto done; + + store_set_key_certs(kd, k); + debug3("STORE public key type: %s", sshkey_type(k)); + + kd->pk = NULL; /* transferred */ + + if (commentp != NULL) + xasprintf(commentp, "store:%s", url); + + if (keyp != NULL) { + *keyp = k; + k = NULL; + } + +done: + sshkey_free(k); + STORE_KEY_DATA_free(kd); + free((void*)url); + return ret; +} +#endif /*USE_OPENSSL_STORE2*/ + + +void +ssh_engines_startup() { +#ifdef USE_OPENSSL_ENGINE + eng_list = sshbuf_new(); + if (eng_list == NULL) + fatal_f("sshbuf_new failed"); +#endif + (void) setup_ssh_ui_method(); +} + + +void +ssh_engines_shutdown() { +#ifdef USE_OPENSSL_ENGINE + free(eng_name); + eng_name = NULL; + + while (sshbuf_len(eng_list) > 0) { + char *s; + int r; + + r = sshbuf_get_cstring(eng_list, &s, NULL); + if (r != 0) + fatal_fr(r, "buffer error"); + ssh_engine_reset(s); + free(s); + }; + sshbuf_free(eng_list); + eng_list = NULL; +#endif + destroy_ssh_ui_method(); +} diff -ruN openssh-9.4p1/key-eng.h openssh-9.4p1+x509-14.2.1/key-eng.h --- openssh-9.4p1/key-eng.h 1970-01-01 02:00:00.000000000 +0200 +++ openssh-9.4p1+x509-14.2.1/key-eng.h 2023-08-20 10:07:00.000000000 +0300 @@ -0,0 +1,50 @@ +#ifndef KEY_ENG_H +#define KEY_ENG_H +/* + * Copyright (c) 2011-2021 Roumen Petrov. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "includes.h" +#include "sshkey.h" + +extern void ssh_engines_startup(void); +extern void ssh_engines_shutdown(void); + +#ifdef USE_OPENSSL_ENGINE + +#include + +extern int/*bool*/ process_engconfig_file(const char *engconfig); + +extern void ssh_load_engines(void); + +extern int engine_load_private(const char *name, const char *passphrase, struct sshkey **keyp, char **commentp); +extern int engine_try_load_public(const char *name, struct sshkey **keyp, char **commentp); +#endif /*ndef USE_OPENSSL_ENGINE*/ + +#ifdef USE_OPENSSL_STORE2 +extern int store_load_private(const char *name, const char *passphrase, struct sshkey **keyp, char **commentp); +extern int store_try_load_public(const char *name, struct sshkey **keyp, char **commentp); +#endif /*USE_OPENSSL_STORE2*/ + +#endif /*ndef KEY_ENG_H*/ diff -ruN openssh-9.4p1/krl.c openssh-9.4p1+x509-14.2.1/krl.c --- openssh-9.4p1/krl.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/krl.c 2023-08-20 10:07:01.000000000 +0300 @@ -32,6 +32,7 @@ #include "sshbuf.h" #include "ssherr.h" #include "sshkey.h" +#include "compat.h" #include "authfile.h" #include "misc.h" #include "log.h" @@ -786,6 +787,7 @@ (r = sshbuf_put_stringb(buf, sect)) != 0) goto out; } +#ifdef HAVE_EVP_SHA256 sshbuf_reset(sect); RB_FOREACH(rb, revoked_blob_tree, &krl->revoked_sha256s) { KRL_DBG(("hash len %zu ", rb->len)); @@ -798,6 +800,7 @@ (r = sshbuf_put_stringb(buf, sect)) != 0) goto out; } +#endif /*def HAVE_EVP_SHA256*/ /* success */ r = 0; out: @@ -830,10 +833,10 @@ struct sshbuf *value = NULL; char *name = NULL; + UNUSED(krl); if ((r = sshbuf_get_cstring(subsect, &name, NULL)) != 0 || (r = sshbuf_get_u8(subsect, &critical)) != 0 || (r = sshbuf_froms(subsect, &value)) != 0) { - debug_fr(r, "parse"); error("KRL has invalid certificate extension subsection"); r = SSH_ERR_INVALID_FORMAT; goto out; @@ -1010,10 +1013,10 @@ struct sshbuf *value = NULL; char *name = NULL; + UNUSED(krl); if ((r = sshbuf_get_cstring(sect, &name, NULL)) != 0 || (r = sshbuf_get_u8(sect, &critical)) != 0 || (r = sshbuf_froms(sect, &value)) != 0) { - debug_fr(r, "parse"); error("KRL has invalid extension section"); r = SSH_ERR_INVALID_FORMAT; goto out; @@ -1112,11 +1115,13 @@ &krl->revoked_sha1s, 20)) != 0) goto out; break; +#ifdef HAVE_EVP_SHA256 case KRL_SECTION_FINGERPRINT_SHA256: if ((r = blob_section(sect, &krl->revoked_sha256s, 32)) != 0) goto out; break; +#endif /*def HAVE_EVP_SHA256*/ case KRL_SECTION_EXTENSION: if ((r = extension_section(sect, krl)) != 0) goto out; @@ -1204,6 +1209,7 @@ KRL_DBG(("revoked by key SHA1")); return SSH_ERR_KEY_REVOKED; } +#ifdef HAVE_EVP_SHA256 memset(&rb, 0, sizeof(rb)); if ((r = sshkey_fingerprint_raw(key, SSH_DIGEST_SHA256, &rb.blob, &rb.len)) != 0) @@ -1214,6 +1220,7 @@ KRL_DBG(("revoked by key SHA256")); return SSH_ERR_KEY_REVOKED; } +#endif /*def HAVE_EVP_SHA256*/ /* Next, explicit keys */ memset(&rb, 0, sizeof(rb)); @@ -1309,7 +1316,7 @@ fprintf(f, "# Generated at %s\n", timestamp); if (krl->comment != NULL && *krl->comment != '\0') { r = INT_MAX; - asmprintf(&fp, INT_MAX, &r, "%s", krl->comment); + asnmprintf(&fp, INT_MAX, &r, "%s", krl->comment); fprintf(f, "# Comment: %s\n", fp); free(fp); } @@ -1377,7 +1384,7 @@ * mess up the display. */ r = INT_MAX; - asmprintf(&fp, INT_MAX, &r, "%s", rki->key_id); + asnmprintf(&fp, INT_MAX, &r, "%s", rki->key_id); fprintf(f, "id: %s\n", fp); free(fp); } diff -ruN openssh-9.4p1/LICENCE openssh-9.4p1+x509-14.2.1/LICENCE --- openssh-9.4p1/LICENCE 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/LICENCE 2023-08-20 10:07:00.000000000 +0300 @@ -160,6 +160,7 @@ Per Allansson Nils Nordman Simon Wilkinson + Roumen Petrov Portable OpenSSH additionally includes code from the following copyright holders, also under the 2-term BSD license: @@ -210,14 +211,22 @@ 8) Portable OpenSSH contains the following additional licenses: - a) snprintf replacement + a) md5crypt.c, md5crypt.h + + * "THE BEER-WARE LICENSE" (Revision 42): + * wrote this file. As long as you retain this + * notice you can do whatever you want with this stuff. If we meet + * some day, and you think this stuff is worth it, you can buy me a + * beer in return. Poul-Henning Kamp + + b) snprintf replacement * Copyright Patrick Powell 1995 * This code is based on code written by Patrick Powell * (papowell@astart.com) It may be used for any purpose as long as this * notice remains intact on all source code distributions - b) Compatibility code (openbsd-compat) + c) Compatibility code (openbsd-compat) Apart from the previously mentioned licenses, various pieces of code in the openbsd-compat/ subdirectory are licensed as follows: diff -ruN openssh-9.4p1/log.c openssh-9.4p1+x509-14.2.1/log.c --- openssh-9.4p1/log.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/log.c 2023-08-20 10:07:01.000000000 +0300 @@ -12,6 +12,7 @@ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. + * Copyright (c) 2004-2022 Roumen Petrov. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -43,7 +44,6 @@ #include #include #include -#include #include #include #if defined(HAVE_STRNVIS) && defined(HAVE_VIS_H) && !defined(BROKEN_STRNVIS) @@ -52,6 +52,9 @@ #include "log.h" #include "match.h" +#include "ssherr.h" + +#define MSGBUFSIZ 1024 static LogLevel log_level = SYSLOG_LEVEL_INFO; static int log_on_stderr = 1; @@ -60,14 +63,40 @@ static const char *argv0; static log_handler_fn *log_handler; static void *log_handler_ctx; -static char **log_verbose; -static size_t nlog_verbose; +static char **log_verbose = NULL; +static size_t nlog_verbose = 0; extern char *__progname; #define LOG_SYSLOG_VIS (VIS_CSTYLE|VIS_NL|VIS_TAB|VIS_OCTAL) #define LOG_STDERR_VIS (VIS_SAFE|VIS_OCTAL) +#ifdef __ANDROID__ +#include + +static void +android_log(LogLevel level, const char *msg, void *ctx) { + android_LogPriority a; + + UNUSED(ctx); + + switch (level) { + case SYSLOG_LEVEL_QUIET : a = ANDROID_LOG_SILENT ; break; + case SYSLOG_LEVEL_FATAL : a = ANDROID_LOG_FATAL ; break; + case SYSLOG_LEVEL_ERROR : a = ANDROID_LOG_ERROR ; break; + case SYSLOG_LEVEL_INFO : a = ANDROID_LOG_WARN ; break; + case SYSLOG_LEVEL_VERBOSE : a = ANDROID_LOG_INFO ; break; + case SYSLOG_LEVEL_DEBUG1 : a = ANDROID_LOG_DEBUG ; break; + case SYSLOG_LEVEL_DEBUG2 : a = ANDROID_LOG_DEBUG ; break; + case SYSLOG_LEVEL_DEBUG3 : a = ANDROID_LOG_VERBOSE ; break; + default : a = ANDROID_LOG_UNKNOWN ; break; + } + + if (a != ANDROID_LOG_UNKNOWN) + __android_log_write(a, __progname, msg); +} +#endif /*def __ANDROID__*/ + /* textual representation of log-facilities/levels */ static struct { @@ -108,12 +137,6 @@ { NULL, SYSLOG_LEVEL_NOT_SET } }; -LogLevel -log_level_get(void) -{ - return log_level; -} - SyslogFacility log_facility_number(char *name) { @@ -161,29 +184,26 @@ } void -log_verbose_add(const char *s) -{ - char **tmp; - - /* Ignore failures here */ - if ((tmp = recallocarray(log_verbose, nlog_verbose, nlog_verbose + 1, - sizeof(*log_verbose))) != NULL) { - log_verbose = tmp; - if ((log_verbose[nlog_verbose] = strdup(s)) != NULL) - nlog_verbose++; - } -} - -void -log_verbose_reset(void) -{ - size_t i; +log_verbose_init(char **opts, size_t n) { + size_t k; - for (i = 0; i < nlog_verbose; i++) - free(log_verbose[i]); + for (k = 0; k < nlog_verbose; k++) + free(log_verbose[k]); free(log_verbose); - log_verbose = NULL; + nlog_verbose = 0; + if (n == 0) { + log_verbose = NULL; + return; + } + log_verbose = calloc(n, sizeof(*log_verbose)); + + for (k = 0; k < n; k++) { + /* non-fatal if strdup fail*/ + log_verbose[nlog_verbose] = strdup(opts[k]); + if (log_verbose[nlog_verbose] != NULL) + nlog_verbose++; + } } /* @@ -194,10 +214,6 @@ log_init(const char *av0, LogLevel level, SyslogFacility facility, int on_stderr) { -#if defined(HAVE_OPENLOG_R) && defined(SYSLOG_DATA_INIT) - struct syslog_data sdata = SYSLOG_DATA_INIT; -#endif - argv0 = av0; if (log_change_level(level) != 0) { @@ -213,6 +229,9 @@ if (on_stderr) return; +#ifdef __ANDROID__ + log_handler = android_log; +#endif switch (facility) { case SYSLOG_FACILITY_DAEMON: log_facility = LOG_DAEMON; @@ -264,14 +283,18 @@ * immediately after reexec, syslog may be pointing to the wrong * facility, so we force an open/close of syslog here. */ +{ const char *progname = (argv0 != NULL) ? argv0 : __progname; #if defined(HAVE_OPENLOG_R) && defined(SYSLOG_DATA_INIT) - openlog_r(argv0 ? argv0 : __progname, LOG_PID, log_facility, &sdata); + struct syslog_data sdata = SYSLOG_DATA_INIT; + + openlog_r(progname, LOG_PID, log_facility, &sdata); closelog_r(&sdata); #else - openlog(argv0 ? argv0 : __progname, LOG_PID, log_facility); + openlog(progname, LOG_PID, log_facility); closelog(); #endif } +} int log_change_level(LogLevel new_log_level) @@ -324,7 +347,11 @@ log_stderr_fd = fd; } -#define MSGBUFSIZ 1024 +LogLevel +get_log_level(void) { + return log_level; +} + void set_log_handler(log_handler_fn *handler, void *ctx) @@ -333,23 +360,40 @@ log_handler_ctx = ctx; } -static void -do_log(LogLevel level, int force, const char *suffix, const char *fmt, - va_list args) +static int/*boolean*/ +forced_logging(const char *file, const char *func, int line) +{ + char tag[128]; + size_t k; + + if (nlog_verbose == 0) return 0; + +{ const char *s = strrchr(file, '/'); + if (s != NULL ) file = s + 1; + snprintf(tag, sizeof(tag), "%.48s:%.48s():%d", file, func, line); +} + for (k = 0; k < nlog_verbose; k++) { + if (match_pattern_list(tag, log_verbose[k], 0) == 1) + return 1; + } + return 0; +} + +void +sshlogv(const char *file, const char *func, int line, + LogLevel level, const char *fmt, va_list args) { -#if defined(HAVE_OPENLOG_R) && defined(SYSLOG_DATA_INIT) - struct syslog_data sdata = SYSLOG_DATA_INIT; -#endif char msgbuf[MSGBUFSIZ]; char fmtbuf[MSGBUFSIZ]; char *txt = NULL; int pri = LOG_INFO; int saved_errno = errno; - log_handler_fn *tmp_handler; - const char *progname = argv0 != NULL ? argv0 : __progname; + const char *progname = (argv0 != NULL) ? argv0 : __progname; - if (!force && level > log_level) - return; + if ((line > 0) && (level > log_level)) { + if (!forced_logging(file, func, line)) + return; + } switch (level) { case SYSLOG_LEVEL_FATAL: @@ -391,17 +435,17 @@ } else { vsnprintf(msgbuf, sizeof(msgbuf), fmt, args); } - if (suffix != NULL) { - snprintf(fmtbuf, sizeof(fmtbuf), "%s: %s", msgbuf, suffix); - strlcpy(msgbuf, fmtbuf, sizeof(msgbuf)); - } +#if 0 /*TODO: vis result is completely broken on UTF-8 */ strnvis(fmtbuf, msgbuf, sizeof(fmtbuf), log_on_stderr ? LOG_STDERR_VIS : LOG_SYSLOG_VIS); +#else + snprintf(fmtbuf, sizeof(fmtbuf), "%s", msgbuf); +#endif if (log_handler != NULL) { /* Avoid recursion */ - tmp_handler = log_handler; + log_handler_fn *tmp_handler = log_handler; log_handler = NULL; - tmp_handler(level, force, fmtbuf, log_handler_ctx); + tmp_handler(level, fmtbuf, log_handler_ctx); log_handler = tmp_handler; } else if (log_on_stderr) { snprintf(msgbuf, sizeof msgbuf, "%s%s%.*s\r\n", @@ -411,12 +455,14 @@ (void)write(log_stderr_fd, msgbuf, strlen(msgbuf)); } else { #if defined(HAVE_OPENLOG_R) && defined(SYSLOG_DATA_INIT) + struct syslog_data sdata = SYSLOG_DATA_INIT; + openlog_r(progname, LOG_PID, log_facility, &sdata); - syslog_r(pri, &sdata, "%.500s", fmtbuf); + syslog_r(pri, &sdata, "%.1000s", fmtbuf); closelog_r(&sdata); #else openlog(progname, LOG_PID, log_facility); - syslog(pri, "%.500s", fmtbuf); + syslog(pri, "%.1000s", fmtbuf); closelog(); #endif } @@ -424,77 +470,112 @@ } void -sshlog(const char *file, const char *func, int line, int showfunc, - LogLevel level, const char *suffix, const char *fmt, ...) +sshlog(const char *file, const char *func, int line, + LogLevel level, const char *fmt, ...) { va_list args; va_start(args, fmt); - sshlogv(file, func, line, showfunc, level, suffix, fmt, args); + sshlogv(file, func, line, level, fmt, args); va_end(args); } void -sshlogdie(const char *file, const char *func, int line, int showfunc, - LogLevel level, const char *suffix, const char *fmt, ...) +sshlogdie(const char *file, const char *func, int line, + const char *fmt,...) { va_list args; va_start(args, fmt); - sshlogv(file, func, line, showfunc, SYSLOG_LEVEL_INFO, - suffix, fmt, args); + sshlogv(file, func, line, SYSLOG_LEVEL_INFO, fmt, args); va_end(args); cleanup_exit(255); } void -sshsigdie(const char *file, const char *func, int line, int showfunc, - LogLevel level, const char *suffix, const char *fmt, ...) +sshsigdie(const char *file, const char *func, int line, + const char *fmt,...) { +#if 1 +/* NOTE: "OpenSSH bug 3286". See grace_alarm_handler() in sshd.c. + * Logging in signal handler cannot be considered as safe. + * Let enable log as now daemon does not sent explicitly alarm + * signal. This should avoid logging in child signal handler. + */ +# define DO_LOG_SAFE_IN_SIGHAND +#endif +#ifdef DO_LOG_SAFE_IN_SIGHAND va_list args; va_start(args, fmt); - sshlogv(file, func, line, showfunc, SYSLOG_LEVEL_FATAL, - suffix, fmt, args); + sshlogv(file, func, line, SYSLOG_LEVEL_FATAL, fmt, args); va_end(args); +#else + UNUSED(file); UNUSED(func); UNUSED(line); + UNUSED(fmt); +#endif _exit(1); } void -sshlogv(const char *file, const char *func, int line, int showfunc, - LogLevel level, const char *suffix, const char *fmt, va_list args) +sshlogv_f(const char *file, const char *func, int line, + LogLevel level, const char *fmt, va_list args) { - char tag[128], fmt2[MSGBUFSIZ + 128]; - int forced = 0; - const char *cp; - size_t i; - - snprintf(tag, sizeof(tag), "%.48s:%.48s():%d (pid=%ld)", - (cp = strrchr(file, '/')) == NULL ? file : cp + 1, func, line, - (long)getpid()); - for (i = 0; i < nlog_verbose; i++) { - if (match_pattern_list(tag, log_verbose[i], 0) == 1) { - forced = 1; - break; - } - } + char msgbuf[MSGBUFSIZ]; + + vsnprintf(msgbuf, sizeof(msgbuf), fmt, args); + sshlog(file, func, line, level, "%s: %s", func, msgbuf); +} - if (forced) - snprintf(fmt2, sizeof(fmt2), "%s: %s", tag, fmt); - else if (showfunc) - snprintf(fmt2, sizeof(fmt2), "%s: %s", func, fmt); - else - strlcpy(fmt2, fmt, sizeof(fmt2)); +void +sshlog_f(const char *file, const char *func, int line, + LogLevel level, const char *fmt, ...) +{ + va_list args; + + va_start(args, fmt); + sshlogv_f(file, func, line, level, fmt, args); + va_end(args); +} + +void +sshlogv_r(const char *file, const char *func, int line, + int errcode, LogLevel level, const char *fmt, va_list args) +{ + char msgbuf[MSGBUFSIZ]; + + vsnprintf(msgbuf, sizeof(msgbuf), fmt, args); + sshlog(file, func, line, level, "%s - %s", msgbuf, ssh_err(errcode)); +} + +void +sshlog_r(const char *file, const char *func, int line, + int errcode, LogLevel level, const char *fmt, ...) +{ + va_list args; + + va_start(args, fmt); + sshlogv_r(file, func, line, errcode, level, fmt, args); + va_end(args); +} + +void +sshlogv_fr(const char *file, const char *func, int line, + int errcode, LogLevel level, const char *fmt, va_list args) +{ + char msgbuf[MSGBUFSIZ]; - do_log(level, forced, suffix, fmt2, args); + vsnprintf(msgbuf, sizeof(msgbuf), fmt, args); + sshlog(file, func, line, level, "%s: %s - %s", func, msgbuf, ssh_err(errcode)); } void -sshlogdirect(LogLevel level, int forced, const char *fmt, ...) +sshlog_fr(const char *file, const char *func, int line, + int errcode, LogLevel level, const char *fmt, ...) { va_list args; va_start(args, fmt); - do_log(level, forced, NULL, fmt, args); + sshlogv_fr(file, func, line, errcode, level, fmt, args); va_end(args); } diff -ruN openssh-9.4p1/log-crypto.c openssh-9.4p1+x509-14.2.1/log-crypto.c --- openssh-9.4p1/log-crypto.c 1970-01-01 02:00:00.000000000 +0200 +++ openssh-9.4p1+x509-14.2.1/log-crypto.c 2023-08-20 10:07:01.000000000 +0300 @@ -0,0 +1,145 @@ +/* + * Copyright (c) 2004-2022 Roumen Petrov. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "includes.h" + +#include "log.h" +#include + +#define MSGBUFSIZ 4096 + + +static inline unsigned long +ssh_ERR_get_error_all(const char **data, int *flags) { +#ifdef HAVE_ERR_GET_ERROR_ALL /* OpenSSL >= 3.0 */ + return ERR_get_error_all(NULL, NULL, NULL, data, flags); +#else + return ERR_get_error_line_data(NULL, NULL, data, flags); +#endif +} + + +static char* +get_one_crypto_error(char *buf, size_t len) { + unsigned long err_code; + const char *err_data; + int err_flags; + + err_code = ssh_ERR_get_error_all(&err_data, &err_flags); + if (err_code == 0) return NULL; + + if (!(err_flags & ERR_TXT_STRING)) + err_data = NULL; + +{ char ebuf[MSGBUFSIZ]; + ERR_error_string_n(err_code, ebuf, sizeof(ebuf)); + snprintf(buf, len, "%s%s%s", ebuf + , err_data ? ":" : "" + , err_data ? err_data : "" + ); +} + + return buf; +} + + +void +sshlog_cryptoerr_all(const char *file, const char *func, int line, + LogLevel level +) { + char ebuf[MSGBUFSIZ]; + const char *emsg; + for ( + emsg = get_one_crypto_error(ebuf, sizeof(ebuf)); + emsg != NULL; + emsg = get_one_crypto_error(ebuf, sizeof(ebuf)) + ) + sshlog(file, func, line, level, + "%s: crypto message: '%s'", func, emsg); +} + + +static char* +crypto_errormsg(char *buf, size_t len) { + unsigned long err_code; + const char *err_data; + int err_flags; + + if (buf == NULL) goto out; + + err_code = ssh_ERR_get_error_all(&err_data, &err_flags); + if (err_code == 0) { + if (len > 0) *buf = '\0'; + goto out; + } + if (!(err_flags & ERR_TXT_STRING)) + err_data = NULL; + +{ char ebuf[MSGBUFSIZ]; + ERR_error_string_n(err_code, ebuf, sizeof(ebuf)); + snprintf(buf, len, "%s%s%s", ebuf + , err_data ? ":" : "" + , err_data ? err_data : "" + ); +} + +out: + /* clear rest of errors in OpenSSL "error buffer" */ + ERR_clear_error(); + return buf; +} + + +void +sshlog_cryptoerr_fmt(const char *file, const char *func, int line, + LogLevel level, const char *openssl_method, const char *fmt, ...) +{ + char *sep, mbuf[MSGBUFSIZ], ebuf[MSGBUFSIZ]; + va_list args; + + va_start(args, fmt); + vsnprintf(mbuf, sizeof(mbuf), fmt, args); + va_end(args); + + sep = mbuf[0] != '\0' ? "/" : "", + + crypto_errormsg(ebuf, sizeof(ebuf)); + + sshlog(file, func, line, level, + "%s->%s%s%s%s last error: '%s'", func, openssl_method, + sep, mbuf, sep, ebuf); +} + + +void +sshlog_cryptoerr(const char *file, const char *func, int line, + LogLevel level, const char *openssl_method) +{ + char ebuf[MSGBUFSIZ]; + + crypto_errormsg(ebuf, sizeof(ebuf)); + + sshlog(file, func, line, level, + "%s->%s last error: '%s'", func, openssl_method, ebuf); +} diff -ruN openssh-9.4p1/log.h openssh-9.4p1+x509-14.2.1/log.h --- openssh-9.4p1/log.h 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/log.h 2023-08-20 10:07:00.000000000 +0300 @@ -1,5 +1,4 @@ /* $OpenBSD: log.h,v 1.33 2021/04/15 16:24:31 markus Exp $ */ - /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -11,12 +10,36 @@ * incompatible with the protocol description in the RFC file, it must be * called by a name other than "ssh" or "Secure Shell". */ +/* + * Copyright (c) 2020-2021 Roumen Petrov. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ #ifndef SSH_LOG_H #define SSH_LOG_H +/* syslog.h include is required to get define for LOG_AUTHPRIV */ +#include #include /* va_list */ -#include "ssherr.h" /* ssh_err() */ /* Supported syslog facilities and levels. */ typedef enum { @@ -49,15 +72,14 @@ SYSLOG_LEVEL_NOT_SET = -1 } LogLevel; -typedef void (log_handler_fn)(LogLevel, int, const char *, void *); +typedef void (log_handler_fn)(LogLevel level, const char *msg, void *ctx); void log_init(const char *, LogLevel, SyslogFacility, int); -LogLevel log_level_get(void); int log_change_level(LogLevel); int log_is_on_stderr(void); void log_redirect_stderr_to(const char *); -void log_verbose_add(const char *); -void log_verbose_reset(void); +void log_verbose_init(char **, size_t); +LogLevel get_log_level(void); SyslogFacility log_facility_number(char *); const char * log_facility_name(SyslogFacility); @@ -67,66 +89,124 @@ void set_log_handler(log_handler_fn *, void *); void cleanup_exit(int) __attribute__((noreturn)); -void sshlog(const char *, const char *, int, int, - LogLevel, const char *, const char *, ...) - __attribute__((format(printf, 7, 8))); -void sshlogv(const char *, const char *, int, int, - LogLevel, const char *, const char *, va_list); -void sshsigdie(const char *, const char *, int, int, - LogLevel, const char *, const char *, ...) __attribute__((noreturn)) - __attribute__((format(printf, 7, 8))); -void sshlogdie(const char *, const char *, int, int, - LogLevel, const char *, const char *, ...) __attribute__((noreturn)) - __attribute__((format(printf, 7, 8))); -void sshfatal(const char *, const char *, int, int, - LogLevel, const char *, const char *, ...) __attribute__((noreturn)) - __attribute__((format(printf, 7, 8))); -void sshlogdirect(LogLevel, int, const char *, ...) - __attribute__((format(printf, 3, 4))); - -#define do_log2(level, ...) sshlog(__FILE__, __func__, __LINE__, 0, level, NULL, __VA_ARGS__) -#define debug3(...) sshlog(__FILE__, __func__, __LINE__, 0, SYSLOG_LEVEL_DEBUG3, NULL, __VA_ARGS__) -#define debug2(...) sshlog(__FILE__, __func__, __LINE__, 0, SYSLOG_LEVEL_DEBUG2, NULL, __VA_ARGS__) -#define debug(...) sshlog(__FILE__, __func__, __LINE__, 0, SYSLOG_LEVEL_DEBUG1, NULL, __VA_ARGS__) -#define verbose(...) sshlog(__FILE__, __func__, __LINE__, 0, SYSLOG_LEVEL_VERBOSE, NULL, __VA_ARGS__) -#define logit(...) sshlog(__FILE__, __func__, __LINE__, 0, SYSLOG_LEVEL_INFO, NULL, __VA_ARGS__) -#define error(...) sshlog(__FILE__, __func__, __LINE__, 0, SYSLOG_LEVEL_ERROR, NULL, __VA_ARGS__) -#define fatal(...) sshfatal(__FILE__, __func__, __LINE__, 0, SYSLOG_LEVEL_FATAL, NULL, __VA_ARGS__) -#define logdie(...) sshlogdie(__FILE__, __func__, __LINE__, 0, SYSLOG_LEVEL_ERROR, NULL, __VA_ARGS__) -#define sigdie(...) sshsigdie(__FILE__, __func__, __LINE__, 0, SYSLOG_LEVEL_ERROR, NULL, __VA_ARGS__) - -/* Variants that prepend the caller's function */ -#define do_log2_f(level, ...) sshlog(__FILE__, __func__, __LINE__, 1, level, NULL, __VA_ARGS__) -#define debug3_f(...) sshlog(__FILE__, __func__, __LINE__, 1, SYSLOG_LEVEL_DEBUG3, NULL, __VA_ARGS__) -#define debug2_f(...) sshlog(__FILE__, __func__, __LINE__, 1, SYSLOG_LEVEL_DEBUG2, NULL, __VA_ARGS__) -#define debug_f(...) sshlog(__FILE__, __func__, __LINE__, 1, SYSLOG_LEVEL_DEBUG1, NULL, __VA_ARGS__) -#define verbose_f(...) sshlog(__FILE__, __func__, __LINE__, 1, SYSLOG_LEVEL_VERBOSE, NULL, __VA_ARGS__) -#define logit_f(...) sshlog(__FILE__, __func__, __LINE__, 1, SYSLOG_LEVEL_INFO, NULL, __VA_ARGS__) -#define error_f(...) sshlog(__FILE__, __func__, __LINE__, 1, SYSLOG_LEVEL_ERROR, NULL, __VA_ARGS__) -#define fatal_f(...) sshfatal(__FILE__, __func__, __LINE__, 1, SYSLOG_LEVEL_FATAL, NULL, __VA_ARGS__) -#define logdie_f(...) sshlogdie(__FILE__, __func__, __LINE__, 1, SYSLOG_LEVEL_ERROR, NULL, __VA_ARGS__) -#define sigdie_f(...) sshsigdie(__FILE__, __func__, __LINE__, 1, SYSLOG_LEVEL_ERROR, NULL, __VA_ARGS__) - -/* Variants that appends a ssh_err message */ -#define do_log2_r(r, level, ...) sshlog(__FILE__, __func__, __LINE__, 0, level, ssh_err(r), __VA_ARGS__) -#define debug3_r(r, ...) sshlog(__FILE__, __func__, __LINE__, 0, SYSLOG_LEVEL_DEBUG3, ssh_err(r), __VA_ARGS__) -#define debug2_r(r, ...) sshlog(__FILE__, __func__, __LINE__, 0, SYSLOG_LEVEL_DEBUG2, ssh_err(r), __VA_ARGS__) -#define debug_r(r, ...) sshlog(__FILE__, __func__, __LINE__, 0, SYSLOG_LEVEL_DEBUG1, ssh_err(r), __VA_ARGS__) -#define verbose_r(r, ...) sshlog(__FILE__, __func__, __LINE__, 0, SYSLOG_LEVEL_VERBOSE, ssh_err(r), __VA_ARGS__) -#define logit_r(r, ...) sshlog(__FILE__, __func__, __LINE__, 0, SYSLOG_LEVEL_INFO, ssh_err(r), __VA_ARGS__) -#define error_r(r, ...) sshlog(__FILE__, __func__, __LINE__, 0, SYSLOG_LEVEL_ERROR, ssh_err(r), __VA_ARGS__) -#define fatal_r(r, ...) sshfatal(__FILE__, __func__, __LINE__, 0, SYSLOG_LEVEL_FATAL, ssh_err(r), __VA_ARGS__) -#define logdie_r(r, ...) sshlogdie(__FILE__, __func__, __LINE__, 0, SYSLOG_LEVEL_ERROR, ssh_err(r), __VA_ARGS__) -#define sigdie_r(r, ...) sshsigdie(__FILE__, __func__, __LINE__, 0, SYSLOG_LEVEL_ERROR, ssh_err(r), __VA_ARGS__) -#define do_log2_fr(r, level, ...) sshlog(__FILE__, __func__, __LINE__, 1, level, ssh_err(r), __VA_ARGS__) -#define debug3_fr(r, ...) sshlog(__FILE__, __func__, __LINE__, 1, SYSLOG_LEVEL_DEBUG3, ssh_err(r), __VA_ARGS__) -#define debug2_fr(r, ...) sshlog(__FILE__, __func__, __LINE__, 1, SYSLOG_LEVEL_DEBUG2, ssh_err(r), __VA_ARGS__) -#define debug_fr(r, ...) sshlog(__FILE__, __func__, __LINE__, 1, SYSLOG_LEVEL_DEBUG1, ssh_err(r), __VA_ARGS__) -#define verbose_fr(r, ...) sshlog(__FILE__, __func__, __LINE__, 1, SYSLOG_LEVEL_VERBOSE, ssh_err(r), __VA_ARGS__) -#define logit_fr(r, ...) sshlog(__FILE__, __func__, __LINE__, 1, SYSLOG_LEVEL_INFO, ssh_err(r), __VA_ARGS__) -#define error_fr(r, ...) sshlog(__FILE__, __func__, __LINE__, 1, SYSLOG_LEVEL_ERROR, ssh_err(r), __VA_ARGS__) -#define fatal_fr(r, ...) sshfatal(__FILE__, __func__, __LINE__, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), __VA_ARGS__) -#define logdie_fr(r, ...) sshlogdie(__FILE__, __func__, __LINE__, 1, SYSLOG_LEVEL_ERROR, ssh_err(r), __VA_ARGS__) -#define sigdie_fr(r, ...) sshsigdie(__FILE__, __func__, __LINE__, 1, SYSLOG_LEVEL_ERROR, ssh_err(r), __VA_ARGS__) +void sshlog(const char *file, const char *func, int line, + LogLevel level, const char *fmt, ...) + __attribute__((format(printf, 5, 6))); +void sshlogv(const char *file, const char *func, int line, + LogLevel level, const char *fmt, va_list args); + +#define do_log2(level, ...) sshlog(__FILE__, __func__, __LINE__, level, __VA_ARGS__) + +/* Error messages that should be logged. */ +#define error(...) sshlog(__FILE__, __func__, __LINE__, SYSLOG_LEVEL_ERROR, __VA_ARGS__) +/* Log this message (information that usually should go to the log). */ +#define logit(...) sshlog(__FILE__, __func__, __LINE__, SYSLOG_LEVEL_INFO, __VA_ARGS__) +/* More detailed messages (information that does not need to go to the log). */ +#define verbose(...) sshlog(__FILE__, __func__, __LINE__, SYSLOG_LEVEL_VERBOSE, __VA_ARGS__) +/* Debugging messages that should not be logged during normal operation. */ +#define debug(...) sshlog(__FILE__, __func__, __LINE__, SYSLOG_LEVEL_DEBUG1, __VA_ARGS__) +#define debug2(...) sshlog(__FILE__, __func__, __LINE__, SYSLOG_LEVEL_DEBUG2, __VA_ARGS__) +#define debug3(...) sshlog(__FILE__, __func__, __LINE__, SYSLOG_LEVEL_DEBUG3, __VA_ARGS__) + +void sshfatal(const char *file, const char *func, int line, + const char *fmt, ...) __attribute__((noreturn)) + __attribute__((format(printf, 4, 5))); +void sshsigdie(const char *file, const char *func, int line, + const char *fmt, ...) __attribute__((noreturn)) + __attribute__((format(printf, 4, 5))); +void sshlogdie(const char *file, const char *func, int line, + const char *fmt, ...) __attribute__((noreturn)) + __attribute__((format(printf, 4, 5))); + +#define fatal(...) sshfatal(__FILE__, __func__, __LINE__, __VA_ARGS__) +#define logdie(...) sshlogdie(__FILE__, __func__, __LINE__, __VA_ARGS__) +#define sigdie(...) sshsigdie(__FILE__, __func__, __LINE__, __VA_ARGS__) + + +/* Error messages from cryptographic library that should be logged. */ +void sshlog_cryptoerr(const char *file, const char *func, int line, + LogLevel level, const char *openssl_method); +void sshlog_cryptoerr_fmt(const char *file, const char *func, int line, + LogLevel level, const char *openssl_method, const char *fmt, ...) + __attribute__((format(printf, 6, 7))); +void sshlog_cryptoerr_all(const char *file, const char *func, int line, + LogLevel level); + +#define error_crypto(openssl_method) \ + sshlog_cryptoerr(__FILE__, __func__, __LINE__, SYSLOG_LEVEL_ERROR, openssl_method) +#define debug3_crypto(openssl_method) \ + sshlog_cryptoerr(__FILE__, __func__, __LINE__, SYSLOG_LEVEL_DEBUG3, openssl_method) + +#define error_crypto_fmt(openssl_method, ...) \ + sshlog_cryptoerr_fmt(__FILE__, __func__, __LINE__, SYSLOG_LEVEL_ERROR, openssl_method, __VA_ARGS__) +#define debug3_crypto_fmt(openssl_method, ...) \ + sshlog_cryptoerr_fmt(__FILE__, __func__, __LINE__, SYSLOG_LEVEL_DEBUG3, openssl_method, __VA_ARGS__) + +#define do_log_crypto_errors(level) \ + sshlog_cryptoerr_all(__FILE__, __func__, __LINE__, level) + + +/* Variants that prepend the caller's function. + * Excludes information and verbose messages. + */ +void sshlog_f(const char *file, const char *func, int line, + LogLevel level, const char *fmt, ...) + __attribute__((format(printf, 5, 6))); +void sshlogv_f(const char *file, const char *func, int line, + LogLevel level, const char *fmt, va_list args); + +#define do_log2_f(level, ...) sshlog_f(__FILE__, __func__, __LINE__, level, __VA_ARGS__) + +#define error_f(...) sshlog_f(__FILE__, __func__, __LINE__, SYSLOG_LEVEL_ERROR, __VA_ARGS__) +#define debug_f(...) sshlog_f(__FILE__, __func__, __LINE__, SYSLOG_LEVEL_DEBUG1, __VA_ARGS__) +#define debug2_f(...) sshlog_f(__FILE__, __func__, __LINE__, SYSLOG_LEVEL_DEBUG2, __VA_ARGS__) +#define debug3_f(...) sshlog_f(__FILE__, __func__, __LINE__, SYSLOG_LEVEL_DEBUG3, __VA_ARGS__) + +void sshfatal_f(const char *file, const char *func, int line, + const char *fmt, ...) __attribute__((noreturn)) + __attribute__((format(printf, 4, 5))); + +#define fatal_f(...) sshfatal_f(__FILE__, __func__, __LINE__, __VA_ARGS__) + + +/* Variants that appends a secsh error reason. */ +void sshlog_r(const char *file, const char *func, int line, + int errcode, LogLevel level, const char *fmt, ...) + __attribute__((format(printf, 6, 7))); +void sshlogv_r(const char *file, const char *func, int line, + int errcode, LogLevel level, const char *fmt, va_list args); + +#define do_log2_r(errcode, level, ...) sshlog_r(__FILE__, __func__, __LINE__, errcode, level, __VA_ARGS__) + +#define error_r(errcode, ...) sshlog_r(__FILE__, __func__, __LINE__, errcode, SYSLOG_LEVEL_ERROR, __VA_ARGS__) +#define debug_r(errcode, ...) sshlog_r(__FILE__, __func__, __LINE__, errcode, SYSLOG_LEVEL_DEBUG1, __VA_ARGS__) +#define debug2_r(errcode, ...) sshlog_r(__FILE__, __func__, __LINE__, errcode, SYSLOG_LEVEL_DEBUG2, __VA_ARGS__) +#define debug3_r(errcode, ...) sshlog_r(__FILE__, __func__, __LINE__, errcode, SYSLOG_LEVEL_DEBUG3, __VA_ARGS__) + +void sshfatal_r(const char *file, const char *func, int line, + int errcode, const char *fmt, ...) __attribute__((noreturn)) + __attribute__((format(printf, 5, 6))); + +#define fatal_r(errcode, ...) sshfatal_r(__FILE__, __func__, __LINE__, errcode, __VA_ARGS__) + + +/* Variants that prepend the caller's function and + * appends a secsh error reason. + */ +void sshlog_fr(const char *file, const char *func, int line, + int errcode, LogLevel level, const char *fmt, ...) + __attribute__((format(printf, 6, 7))); +void sshlogv_fr(const char *file, const char *func, int line, + int errcode, LogLevel level, const char *fmt, va_list args); + +#define do_log2_fr(errcode, level, ...) sshlog_fr(__FILE__, __func__, __LINE__, errcode, level, __VA_ARGS__) + +#define error_fr(errcode, ...) sshlog_fr(__FILE__, __func__, __LINE__, errcode, SYSLOG_LEVEL_ERROR, __VA_ARGS__) + +void sshfatal_fr(const char *file, const char *func, int line, + int errcode, const char *fmt, ...) __attribute__((noreturn)) + __attribute__((format(printf, 5, 6))); + +#define fatal_fr(errcode, ...) sshfatal_fr(__FILE__, __func__, __LINE__, errcode, __VA_ARGS__) #endif diff -ruN openssh-9.4p1/loginrec.c openssh-9.4p1+x509-14.2.1/loginrec.c --- openssh-9.4p1/loginrec.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/loginrec.c 2023-08-20 10:07:01.000000000 +0300 @@ -1,4 +1,5 @@ /* + * Copyright (c) 2012-2018 Roumen Petrov. All rights reserved. * Copyright (c) 2000 Andre Lucas. All rights reserved. * Portions copyright (c) 1998 Todd C. Miller * Portions copyright (c) 1996 Jason Downs @@ -169,8 +170,11 @@ #include #include +#ifdef HAVE_UTIL_H +# include +#endif + #include "xmalloc.h" -#include "sshkey.h" #include "hostfile.h" #include "ssh.h" #include "loginrec.h" @@ -181,11 +185,6 @@ #include "auth.h" #include "sshbuf.h" #include "ssherr.h" -#include "misc.h" - -#ifdef HAVE_UTIL_H -# include -#endif /** ** prototypes for helper functions in this file @@ -219,6 +218,16 @@ /* pick the shortest string */ #define MIN_SIZEOF(s1,s2) (sizeof(s1) < sizeof(s2) ? sizeof(s1) : sizeof(s2)) +#ifdef __ANDROID__ +/* Android define only user process */ +# ifndef DEAD_PROCESS +# define DEAD_PROCESS USER_PROCESS +# endif +# ifndef LOGIN_PROCESS +# define LOGIN_PROCESS USER_PROCESS +# endif +#endif + /** ** platform-independent login functions **/ @@ -314,12 +323,11 @@ */ pw = getpwuid(uid); if (pw == NULL) - fatal("%s: Cannot find account for uid %ld", __func__, - (long)uid); + fatal_f("Cannot find account for uid %ld", (long)uid); if (strlcpy(li->username, pw->pw_name, sizeof(li->username)) >= sizeof(li->username)) { - error("%s: username too long (%lu > max %lu)", __func__, + error_f("username too long (%lu > max %lu)", (unsigned long)strlen(pw->pw_name), (unsigned long)sizeof(li->username) - 1); return NULL; @@ -332,7 +340,7 @@ } /* - * login_alloc_entry(int, char*, char*, char*) - Allocate and initialise + * login_alloc_entry(pid_t, char*, char*, char*) - Allocate and initialise * a logininfo structure * * This function creates a new struct logininfo, a data structure @@ -386,10 +394,8 @@ if (username) { strlcpy(li->username, username, sizeof(li->username)); pw = getpwnam(li->username); - if (pw == NULL) { - fatal("%s: Cannot find user \"%s\"", __func__, - li->username); - } + if (pw == NULL) + fatal_f("Cannot find user \"%s\"", li->username); li->uid = pw->pw_uid; } @@ -439,6 +445,9 @@ int login_write(struct logininfo *li) { +#if defined(__ANDROID__) + return 0; +#endif #ifndef HAVE_CYGWIN if (geteuid() != 0) { logit("Attempt to write login records by non-root user (aborting)"); @@ -524,6 +533,7 @@ #if defined(DISABLE_LASTLOG) /* On some systems we shouldn't even try to obtain last login * time, e.g. AIX */ + UNUSED(li); return (0); # elif defined(USE_WTMP) && \ (defined(HAVE_TIME_IN_UTMP) || defined(HAVE_TV_IN_UTMP)) @@ -535,6 +545,7 @@ return (wtmpx_get_entry(li)); # else /* Give up: No means of retrieving last login time */ + UNUSED(li); return (0); # endif /* DISABLE_LASTLOG */ #endif /* USE_LASTLOG */ @@ -818,6 +829,12 @@ # if !defined(DISABLE_PUTUTLINE) && defined(HAVE_SETUTENT) && \ defined(HAVE_PUTUTLINE) # define UTMP_USE_LIBRARY +# if !HAVE_DECL_PUTUTLINE +struct utmp *pututline(const struct utmp *ut); +# endif +# if defined(HAVE_ENDUTENT) && !HAVE_DECL_ENDUTENT +void endutent(void); +# endif # endif @@ -826,6 +843,7 @@ static int utmp_write_library(struct logininfo *li, struct utmp *ut) { + UNUSED(li); setutent(); pututline(ut); # ifdef HAVE_ENDUTENT @@ -861,7 +879,7 @@ endttyent(); if (NULL == ty) { - logit("%s: tty not found", __func__); + error_f("tty not found"); return (0); } #else /* FIXME */ @@ -870,18 +888,18 @@ #endif /* HAVE_GETTTYENT */ - if (tty > 0 && (fd = open(UTMP_FILE, O_RDWR|O_CREAT, 0644)) >= 0) { + if (tty > 0 && (fd = open(UTMP_FILE, O_RDWR|O_CREAT, 0644)) != -1) { off_t pos, ret; pos = (off_t)tty * sizeof(struct utmp); if ((ret = lseek(fd, pos, SEEK_SET)) == -1) { - logit("%s: lseek: %s", __func__, strerror(errno)); + error_f("lseek: %s", strerror(errno)); close(fd); return (0); } if (ret != pos) { - logit("%s: Couldn't seek to tty %d slot in %s", - __func__, tty, UTMP_FILE); + error_f("couldn't seek to tty %d slot in %s", + tty, UTMP_FILE); close(fd); return (0); } @@ -897,18 +915,18 @@ memcpy(ut->ut_host, old_ut.ut_host, sizeof(ut->ut_host)); if ((ret = lseek(fd, pos, SEEK_SET)) == -1) { - logit("%s: lseek: %s", __func__, strerror(errno)); + error_f("lseek: %s", strerror(errno)); close(fd); return (0); } if (ret != pos) { - logit("%s: Couldn't seek to tty %d slot in %s", - __func__, tty, UTMP_FILE); + error_f("couldn't seek to tty %d slot in %s", + tty, UTMP_FILE); close(fd); return (0); } if (atomicio(vwrite, fd, ut, sizeof(*ut)) != sizeof(*ut)) { - logit("%s: error writing %s: %s", __func__, + error_f("error writing %s: %s", UTMP_FILE, strerror(errno)); close(fd); return (0); @@ -930,12 +948,12 @@ construct_utmp(li, &ut); # ifdef UTMP_USE_LIBRARY if (!utmp_write_library(li, &ut)) { - logit("%s: utmp_write_library() failed", __func__); + error_f("utmp_write_library() failed"); return (0); } # else if (!utmp_write_direct(li, &ut)) { - logit("%s: utmp_write_direct() failed", __func__); + error_f("utmp_write_direct() failed"); return (0); } # endif @@ -951,12 +969,12 @@ construct_utmp(li, &ut); # ifdef UTMP_USE_LIBRARY if (!utmp_write_library(li, &ut)) { - logit("%s: utmp_write_library() failed", __func__); + error_f("utmp_write_library() failed"); return (0); } # else if (!utmp_write_direct(li, &ut)) { - logit("%s: utmp_write_direct() failed", __func__); + error_f("utmp_write_direct() failed"); return (0); } # endif @@ -975,7 +993,7 @@ return (utmp_perform_logout(li)); default: - logit("%s: invalid type field", __func__); + error_f("invalid type field"); return (0); } } @@ -1001,6 +1019,7 @@ static int utmpx_write_library(struct logininfo *li, struct utmpx *utx) { + UNUSED(li); setutxent(); pututxline(utx); @@ -1016,7 +1035,8 @@ static int utmpx_write_direct(struct logininfo *li, struct utmpx *utx) { - logit("%s: not implemented!", __func__); + UNUSED(li); UNUSED(utx); + error_f("not implemented!"); return (0); } # endif /* UTMPX_USE_LIBRARY */ @@ -1029,12 +1049,12 @@ construct_utmpx(li, &utx); # ifdef UTMPX_USE_LIBRARY if (!utmpx_write_library(li, &utx)) { - logit("%s: utmp_write_library() failed", __func__); + error_f("utmp_write_library() failed"); return (0); } # else if (!utmpx_write_direct(li, &ut)) { - logit("%s: utmp_write_direct() failed", __func__); + error_f("utmp_write_direct() failed"); return (0); } # endif @@ -1072,7 +1092,7 @@ case LTYPE_LOGOUT: return (utmpx_perform_logout(li)); default: - logit("%s: invalid type field", __func__); + error_f("invalid type field"); return (0); } } @@ -1095,15 +1115,16 @@ struct stat buf; int fd, ret = 1; - if ((fd = open(WTMP_FILE, O_WRONLY|O_APPEND, 0)) < 0) { - logit("%s: problem writing %s: %s", __func__, + UNUSED(li); + if ((fd = open(WTMP_FILE, O_WRONLY|O_APPEND)) == -1) { + error_f("problem writing %s: %s", WTMP_FILE, strerror(errno)); return (0); } - if (fstat(fd, &buf) == 0) + if (fstat(fd, &buf) != -1) if (atomicio(vwrite, fd, ut, sizeof(*ut)) != sizeof(*ut)) { ftruncate(fd, buf.st_size); - logit("%s: problem writing %s: %s", __func__, + error_f("problem writing %s: %s", WTMP_FILE, strerror(errno)); ret = 0; } @@ -1140,7 +1161,7 @@ case LTYPE_LOGOUT: return (wtmp_perform_logout(li)); default: - logit("%s: invalid type field", __func__); + error_f("invalid type field"); return (0); } } @@ -1189,13 +1210,13 @@ /* Clear the time entries in our logininfo */ li->tv_sec = li->tv_usec = 0; - if ((fd = open(WTMP_FILE, O_RDONLY)) < 0) { - logit("%s: problem opening %s: %s", __func__, + if ((fd = open(WTMP_FILE, O_RDONLY)) == -1) { + error_f("problem opening %s: %s", WTMP_FILE, strerror(errno)); return (0); } - if (fstat(fd, &st) != 0) { - logit("%s: couldn't stat %s: %s", __func__, + if (fstat(fd, &st) == -1) { + error_f("couldn't stat %s: %s", WTMP_FILE, strerror(errno)); close(fd); return (0); @@ -1210,7 +1231,7 @@ while (!found) { if (atomicio(read, fd, &ut, sizeof(ut)) != sizeof(ut)) { - logit("%s: read of %s failed: %s", __func__, + error_f("read of %s failed: %s", WTMP_FILE, strerror(errno)); close (fd); return (0); @@ -1267,16 +1288,17 @@ struct stat buf; int fd, ret = 1; - if ((fd = open(WTMPX_FILE, O_WRONLY|O_APPEND, 0)) < 0) { - logit("%s: problem opening %s: %s", __func__, + UNUSED(li); + if ((fd = open(WTMPX_FILE, O_WRONLY|O_APPEND)) == -1) { + error_f("problem opening %s: %s", WTMPX_FILE, strerror(errno)); return (0); } - if (fstat(fd, &buf) == 0) + if (fstat(fd, &buf) != -1) if (atomicio(vwrite, fd, utx, sizeof(*utx)) != sizeof(*utx)) { ftruncate(fd, buf.st_size); - logit("%s: problem writing %s: %s", __func__, + error_f("problem writing %s: %s", WTMPX_FILE, strerror(errno)); ret = 0; } @@ -1284,6 +1306,7 @@ return (ret); #else + UNUSED(li); updwtmpx(WTMPX_FILE, utx); return (1); #endif @@ -1319,7 +1342,7 @@ case LTYPE_LOGOUT: return (wtmpx_perform_logout(li)); default: - logit("%s: invalid type field", __func__); + error_f("invalid type field"); return (0); } } @@ -1354,13 +1377,13 @@ /* Clear the time entries */ li->tv_sec = li->tv_usec = 0; - if ((fd = open(WTMPX_FILE, O_RDONLY)) < 0) { - logit("%s: problem opening %s: %s", __func__, + if ((fd = open(WTMPX_FILE, O_RDONLY)) == -1) { + error_f("problem opening %s: %s", WTMPX_FILE, strerror(errno)); return (0); } - if (fstat(fd, &st) != 0) { - logit("%s: couldn't stat %s: %s", __func__, + if (fstat(fd, &st) == -1) { + error_f("couldn't stat %s: %s", WTMPX_FILE, strerror(errno)); close(fd); return (0); @@ -1375,7 +1398,7 @@ while (!found) { if (atomicio(read, fd, &utx, sizeof(utx)) != sizeof(utx)) { - logit("%s: read of %s failed: %s", __func__, + error_f("read of %s failed: %s", WTMPX_FILE, strerror(errno)); close (fd); return (0); @@ -1436,7 +1459,7 @@ (void)line_stripname(line, li->line, sizeof(line)); if (!logout(line)) - logit("%s: logout() returned an error", __func__); + error_f("logout() returned an error"); # ifdef HAVE_LOGWTMP else logwtmp(line, "", ""); @@ -1458,7 +1481,7 @@ case LTYPE_LOGOUT: return (syslogin_perform_logout(li)); default: - logit("%s: Invalid type field", __func__); + error_f("invalid type field"); return (0); } } @@ -1481,8 +1504,8 @@ char lastlog_file[1024]; struct stat st; - if (stat(LASTLOG_FILE, &st) != 0) { - logit("%s: Couldn't stat %s: %s", __func__, + if (stat(LASTLOG_FILE, &st) == -1) { + error_f("couldn't stat %s: %s", LASTLOG_FILE, strerror(errno)); return (0); } @@ -1492,14 +1515,14 @@ } else if (S_ISREG(st.st_mode)) { strlcpy(lastlog_file, LASTLOG_FILE, sizeof(lastlog_file)); } else { - logit("%s: %.100s is not a file or directory!", __func__, + error_f("%.100s is not a file or directory!", LASTLOG_FILE); return (0); } *fd = open(lastlog_file, filemode, 0600); - if (*fd < 0) { - debug("%s: Couldn't open %s: %s", __func__, + if (*fd == -1) { + error_f("couldn't open %s: %s", lastlog_file, strerror(errno)); return (0); } @@ -1509,7 +1532,7 @@ offset = (off_t) ((u_long)li->uid * sizeof(struct lastlog)); if (lseek(*fd, offset, SEEK_SET) != offset) { - logit("%s: %s->lseek(): %s", __func__, + error_f("%s->lseek(): %s", lastlog_file, strerror(errno)); close(*fd); return (0); @@ -1528,7 +1551,7 @@ case LTYPE_LOGIN: return 1; /* lastlog written by pututxline */ default: - logit("lastlog_write_entry: Invalid type field"); + error("lastlog_write_entry: Invalid type field"); return 0; } } @@ -1547,22 +1570,22 @@ strlcpy(last.ll_host, li->hostname, MIN_SIZEOF(last.ll_host, li->hostname)); last.ll_time = li->tv_sec; - + if (!lastlog_openseek(li, &fd, O_RDWR|O_CREAT)) return (0); - + /* write the entry */ if (atomicio(vwrite, fd, &last, sizeof(last)) != sizeof(last)) { close(fd); - logit("%s: Error writing to %s: %s", __func__, + error_f("error writing to %s: %s", LASTLOG_FILE, strerror(errno)); return (0); } - + close(fd); return (1); default: - logit("%s: Invalid type field", __func__); + error_f("invalid type field"); return (0); } } @@ -1609,12 +1632,12 @@ li->tv_sec = last.ll_time; return (1); case -1: - error("%s: Error reading from %s: %s", __func__, + error_f("error reading from %s: %s", LASTLOG_FILE, strerror(errno)); return (0); default: - error("%s: Error reading from %s: Expecting %d, got %d", - __func__, LASTLOG_FILE, (int)sizeof(last), ret); + error_f("error reading from %s: expecting %d, got %d", + LASTLOG_FILE, (int)sizeof(last), ret); return (0); } @@ -1671,20 +1694,21 @@ time_t t; struct stat fst; + UNUSED(ttyn); if (geteuid() != 0) return; - if ((fd = open(_PATH_BTMP, O_WRONLY | O_APPEND)) < 0) { - debug("Unable to open the btmp file %s: %s", _PATH_BTMP, + if ((fd = open(_PATH_BTMP, O_WRONLY | O_APPEND)) == -1) { + error("Unable to open the btmp file %s: %s", _PATH_BTMP, strerror(errno)); return; } - if (fstat(fd, &fst) < 0) { - logit("%s: fstat of %s failed: %s", __func__, _PATH_BTMP, + if (fstat(fd, &fst) == -1) { + error_f("fstat of %s failed: %s", _PATH_BTMP, strerror(errno)); goto out; } if((fst.st_mode & (S_IXGRP | S_IRWXO)) || (fst.st_uid != 0)){ - logit("Excess permission or bad ownership on file %s", + error("Excess permission or bad ownership on file %s", _PATH_BTMP); goto out; } @@ -1704,7 +1728,7 @@ if (ssh_packet_connection_is_on_socket(ssh) && getpeername(ssh_packet_get_connection_in(ssh), - (struct sockaddr *)&from, &fromlen) == 0) { + (struct sockaddr *)&from, &fromlen) != -1) { ipv64_normalise_mapped(&from, &fromlen); if (from.ss_family == AF_INET) { a4 = (struct sockaddr_in *)&from; diff -ruN openssh-9.4p1/loginrec.h openssh-9.4p1+x509-14.2.1/loginrec.h --- openssh-9.4p1/loginrec.h 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/loginrec.h 2023-08-20 10:07:00.000000000 +0300 @@ -113,7 +113,7 @@ /* set the network address based on network address type */ void login_set_addr(struct logininfo *li, const struct sockaddr *sa, - const unsigned int sa_size); + const unsigned int sa_size); /* * lastlog retrieval functions diff -ruN openssh-9.4p1/logintest.c openssh-9.4p1+x509-14.2.1/logintest.c --- openssh-9.4p1/logintest.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/logintest.c 2023-08-20 10:07:01.000000000 +0300 @@ -105,7 +105,7 @@ printf("login_alloc_entry test (no host info):\n"); /* FIXME fake tty more effectively - this could upset some platforms */ - li1 = login_alloc_entry((int)getpid(), username, NULL, ttyname(0)); + li1 = login_alloc_entry(getpid(), username, NULL, ttyname(0)); strlcpy(li1->progname, "OpenSSH-logintest", sizeof(li1->progname)); if (be_verbose) @@ -159,7 +159,7 @@ login_login(li1); snprintf(cmdstring, sizeof(cmdstring), "who | grep '%s '", - stripline); + stripline); system(cmdstring); printf("--\nPausing for %d second(s)...\n", PAUSE_BEFORE_LOGOUT); @@ -206,7 +206,7 @@ "an entry for root \n on %s for the time shown above:\n--\n", stripline); snprintf(cmdstring, sizeof(cmdstring), "last | grep '%s ' | head -3", - stripline); + stripline); system(cmdstring); printf("--\nEnd of login test.\n"); diff -ruN openssh-9.4p1/m4/android.m4 openssh-9.4p1+x509-14.2.1/m4/android.m4 --- openssh-9.4p1/m4/android.m4 1970-01-01 02:00:00.000000000 +0200 +++ openssh-9.4p1+x509-14.2.1/m4/android.m4 2023-08-20 10:07:00.000000000 +0300 @@ -0,0 +1,113 @@ +# Android configuration settings +# +# Copyright (c) 2018 Roumen Petrov +# Revisions: +# 27 Dec 2018 : refactored from configure.ac +# +# serail 20181217 + +AC_DEFUN([SSH_ANDROID_PRECONF], [ +case "$host" in +*-*-linux-android*) + dnl PKIX-SSH up to version 11.6 support as minimum API level 9 and + dnl build only with platform headers. + dnl Version after 11.6 support as minimum API level 16 and build + dnl either with platform or unified headers. + + dnl API before 21 define "getpagesize" is inline function, i.e. + dnl not-detectable by function checks. + ac_cv_func_getpagesize=yes + + dnl Function "openpty" is defined in API 23, but declared only in + dnl unified headers => for consistency across versions always use + dnl local port, based on /dev/ptmx + ac_cv_search_openpty=no + ac_cv_func_openpty=use_port + ac_cv_file__dev_ptmx=yes + + dnl API 21 adds to platform headers but it is always + dnl available as unified header is. + dnl Before API 21 functions "statvfs" and "fstatvfs" are defined in + dnl Bionic "C" library only on some platforms! + dnl => use local port for consistency across versions + ac_cv_header_sys_statvfs_h=ignore + ac_cv_func_statvfs=use_port + ac_cv_func_fstatvfs=use_port + + dnl Platform headers always declare syscall wrapper function "getsid". + dnl In unified it is declared for API 17. Also before API 17 it is + dnl defined in "C" library only on some platforms! + dnl => always use local inline replacement (see misc.c) + ac_cv_func_getsid=yes + + dnl Function "mbtowc" is defined in API 21 but always declared + dnl => use local port for consistency + ac_cv_func_mbtowc=use_port + + dnl Function "getline" is defined in API 18 but in platform headers + dnl is not declared until API 21. + dnl Note in unified headers function is declared accordingly. + dnl => use local port for consistency + ac_cv_func_getline=use_port + + dnl If build is with unified headers configuration check will + dnl define _FILE_OFFSET_BITS and as result on 32-bit platforms + dnl is activated __USE_FILE_OFFSET64 + dnl => temporary suppress for now + ac_cv_sys_file_offset_bits=no + + dnl see port-android.c for details + ac_cv_func_endgrent=yes + + dnl Function "getifaddrs" is defined in API 24 and declared + dnl in unified headers accordingly. + dnl => do not use "bind interface" for consistency + ac_cv_func_getifaddrs=ignore + + dnl Function "futimes" is defined in API 26, but declared only in + dnl unified headers. + dnl => use utimes as work-around for consistency + ac_cv_func_futimes=ignore + + dnl Function "nl_langinfo" is declared in API 26 only in unified + dnl headers. It is defined in "C" library only on some platforms + dnl depending from NDK version! + dnl => do not use "nl_langinfo" for consistency + ac_cv_func_nl_langinfo=ignore + + dnl Function "mblen" is defined in API 26 only on some platforms + dnl depending from NDK version! + dnl It is declared in unified headers, but declaration exist in + dnl headers for previous API + dnl => do not use "mblen" for consistency + ac_cv_func_mblen=ignore + + dnl Function "getrandom" is declared in API 28(unified headers). + dnl Before API 28 it is defined in "C" static-library on some + dnl platforms depending from NDK version! + dnl => do not use "getrandom" for consistency + ac_cv_func_getrandom=ignore + + dnl Function "getentropy" is declared in API 28(unified headers). + dnl Before API 28 it is defined in "C" static-library on some + dnl platforms depending from NDK version! + dnl => do not use "getentropy" for consistency + ac_cv_func_getentropy=ignore + + dnl Function "glob" is declared in API 28(unified headers). + dnl Before API 28 it is defined in "C" static-library on some + dnl platforms depending from NDK version! + dnl => do not use "glob" for consistency + ac_cv_func_glob=ignore + + dnl Function "reallocarray" is declared in API 29(unified headers). + dnl Before API 29 it is defined in "C" static-library on some + dnl platforms depending from NDK version! + dnl => do not use "reallocarray" for consistency + ac_cv_func_reallocarray=ignore + + dnl Function "ppoll" is declared in API 21(unified headers). + dnl NOTE: Use system. + ;; +esac +]) diff -ruN openssh-9.4p1/m4/c.m4 openssh-9.4p1+x509-14.2.1/m4/c.m4 --- openssh-9.4p1/m4/c.m4 1970-01-01 02:00:00.000000000 +0200 +++ openssh-9.4p1+x509-14.2.1/m4/c.m4 2023-08-20 10:07:00.000000000 +0300 @@ -0,0 +1,21 @@ +# options to check compiler +# +# Author: Roumen Petrov +# Revision: 2022-01-30 +# + +AC_DEFUN([SSH_AC_PROG_CC], +[ + AC_REQUIRE([AC_PROG_CC]) + # check for macro defined in 2.69b + m4_ifdef([AC_CONFIG_MACRO_DIRS], + [ +# Note autoconf 2.69b obsoletes AC_PROG_CC_C99 macro and c99 tests +# are performed in standard macro. + ], + [ +# Note macro AC_PROG_CC_C99 is added in autoconf 2.60. + m4_ifdef([AC_PROG_CC_C99], [AC_REQUIRE([AC_PROG_CC_C99])]) + ] + ) +]) diff -ruN openssh-9.4p1/m4/ldap.m4 openssh-9.4p1+x509-14.2.1/m4/ldap.m4 --- openssh-9.4p1/m4/ldap.m4 1970-01-01 02:00:00.000000000 +0200 +++ openssh-9.4p1+x509-14.2.1/m4/ldap.m4 2023-08-20 10:07:00.000000000 +0300 @@ -0,0 +1,237 @@ +# Options to build with LDAP +# +# Author: Roumen Petrov +# Revision: 7 Dec 2011 +# +dnl The variables provided are : +dnl - build flags: +dnl LDAP_LDFLAGS +dnl LDAP_LIBS +dnl LDAP_CPPFLAGS +dnl - conditional: +dnl LDAP_ON (e.g. '' or '#') +dnl LDAP_OFF (e.g. '#' or '' - opposite of LDAP_ON) +dnl - paths: +dnl LDAP_BINDIR +dnl LDAP_LIBEXECDIR +dnl LDAP_SYSCONFDIR + +AC_DEFUN([AC_WITH_LDAP], +[ +dnl +dnl Get the ldap paths +dnl + +ac_ldap=none +AC_ARG_ENABLE([ldap], + [AS_HELP_STRING([--enable-ldap], [Enable LDAP queries])], + [ac_ldap=$enableval] +) + +if test "x$ac_ldap" = xyes; then + ac_ldap_prefix="" + AC_ARG_WITH([ldap-prefix], + [AS_HELP_STRING( + [--with-ldap-prefix=PATH], + [Prefix where LDAP is installed (optional)] + )], + [ac_ldap_prefix=$withval] + ) + + AC_ARG_WITH([ldap-bindir], + [AS_HELP_STRING( + [--with-ldap-bindir=PATH], + [Prefix where LDAP user executables are installed (optional)] + )], + [LDAP_BINDIR=$withval], + [ + if test "x$ac_ldap_prefix" != "x"; then + LDAP_BINDIR="$ac_ldap_prefix/bin" + fi + ] + ) + AC_SUBST(LDAP_BINDIR) + + AC_ARG_WITH([ldap-libexecdir], + [AS_HELP_STRING( + [--with-ldap-libexecdir=PATH], + [Prefix where LDAP program executables are installed (optional)] + )], + [LDAP_LIBEXECDIR=$withval], + [ + if test "x$ac_ldap_prefix" = "x"; then + LDAP_LIBEXECDIR="/usr/libexec" + else + LDAP_LIBEXECDIR="$ac_ldap_prefix/libexec" + fi + ] + ) + AC_SUBST([LDAP_LIBEXECDIR]) +dnl### Check for slapd +dnl if test "x$cross_compiling" = "xyes" ; then +dnl AC_MSG_NOTICE([cannot check for LDAP daemon when cross compiling]) +dnl else +dnl AC_CHECK_FILES( +dnl [ +dnl $LDAP_LIBEXECDIR/slapd +dnl ] +dnl ) +dnl fi + + AC_ARG_WITH([ldap-sysconfdir], + [AS_HELP_STRING( + [--with-ldap-sysconfdir=PATH], + [Prefix where LDAP single-machine data are installed (optional)] + )], + [LDAP_SYSCONFDIR=$withval], + [LDAP_SYSCONFDIR="$ac_ldap_prefix/etc/openldap"] + ) + AC_SUBST([LDAP_SYSCONFDIR]) +dnl### Check for schema files +dnl if test "x$cross_compiling" = "xyes" ; then +dnl AC_MSG_NOTICE([cannot check for schema files existence when cross compiling]) +dnl else +dnl AC_CHECK_FILES( +dnl [ +dnl $LDAP_SYSCONFDIR/schema/core.schema +dnl $LDAP_SYSCONFDIR/schema/cosine.schema +dnl $LDAP_SYSCONFDIR/schema/inetorgperson.schema +dnl ] +dnl ) +dnl fi + + + AC_ARG_WITH([ldap-libdir], + [AS_HELP_STRING( + [--with-ldap-libdir=PATH], + [Prefix where LDAP libraries are installed (optional)] + )], + [LDAP_LDFLAGS="-L$withval"], + [ + if test "x$ac_ldap_prefix" != "x"; then + LDAP_LDFLAGS="-L$ac_ldap_prefix/lib" + else + LDAP_LDFLAGS="" + fi + ] + ) + AC_SUBST(LDAP_LDFLAGS) + + AC_ARG_WITH([ldap-includedir], + [AS_HELP_STRING( + [--with-ldap-includedir=PATH], + [Prefix where LDAP header files are installed (optional)] + )], + [LDAP_CPPFLAGS="-I$withval"], + [ + if test "x$ac_ldap_prefix" != "x"; then + LDAP_CPPFLAGS="-I$ac_ldap_prefix/include" + else + LDAP_CPPFLAGS="" + fi + ] + ) + AC_SUBST([LDAP_CPPFLAGS]) + + + ac_save_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS $LDAP_CPPFLAGS" + AC_CHECK_HEADERS( + [lber.h ldap.h], + [], + [ + AC_MSG_ERROR([cannot found LDAP headers]) + ] + ) + CPPFLAGS="$ac_save_CPPFLAGS" + + ac_ldap_libs="" + AC_ARG_WITH([ldap-libs], + [AS_HELP_STRING( + [--with-ldap-libs=LIBS], + [Specify LDAP libraries to link with (default is -lldap -llber -lssl -lcrypto)] + )], + [ac_ldap_libs="$withval"] + ) + +### Try to link with LDAP libs + ac_save_LDFLAGS="$LDFLAGS" + ac_save_LIBS="$LIBS" + + LDFLAGS="$LDAP_LDFLAGS $LDFLAGS" + ac_LDAP_LINK="" + if test "x$ac_ldap_libs" != "x"; then + AC_MSG_CHECKING([to link with specified LDAP libs]) + + LDAP_LIBS="$ac_ldap_libs" + LIBS="$LDAP_LIBS $ac_save_LIBS" + AC_LINK_IFELSE( + [AC_LANG_CALL([], [ldap_init])], + [ac_LDAP_LINK="yes"] + ) + if test "x$ac_LDAP_LINK" != "xyes"; then + AC_MSG_ERROR([cannot link with specified LDAP libs]) + fi + else + AC_MSG_CHECKING([how to link LDAP libs]) + + LDAP_LIBS="-lldap" + for L in lber ssl crypto; do + LDAP_LIBS="$LDAP_LIBS -l$L" + LIBS="$LDAP_LIBS $ac_save_LIBS" + AC_LINK_IFELSE( + [AC_LANG_CALL([], [ldap_init])], + [ac_LDAP_LINK="yes"] + ) + if test "x$ac_LDAP_LINK" = "xyes"; then + break + fi + done + if test "x$ac_LDAP_LINK" != "xyes"; then + AC_MSG_ERROR([cannot link with default LDAP libs]) + fi + fi + AC_MSG_RESULT([done]) + LIBS="$ac_save_LIBS" + LDFLAGS="$ac_save_LDFLAGS" + AC_SUBST([LDAP_LIBS]) +else + AC_MSG_NOTICE([LDAP is disabled]) +fi + +if test "x$ac_ldap" = "xyes"; then + AC_DEFINE_UNQUOTED( + [LDAP_ENABLED], [1], + [Define if you want to enable LDAP queries]) + LDAP_ON='' + LDAP_OFF='#' +else + LDAP_ON='#' + LDAP_OFF='' +fi +AC_SUBST([LDAP_ON]) +AC_SUBST([LDAP_OFF]) +]) + + +# AC_LDAP_FUNCS(FUNCTION...) +# -------------------------------- +AC_DEFUN([AC_LDAP_FUNCS], +[ +dnl +dnl Check ldap functions +dnl +AC_REQUIRE([AC_WITH_LDAP]) +if test "x$ac_ldap" = "xyes"; then + ac_save_CPPFLAGS="$CPPFLAGS" + ac_save_LDFLAGS="$LDFLAGS" + ac_save_LIBS="$LIBS" + CPPFLAGS="$CPPFLAGS $LDAP_CPPFLAGS" + LDFLAGS="$LDFLAGS $LDAP_LDFLAGS" + LIBS="$LDAP_LIBS $LIBS" + AC_CHECK_FUNCS([$1],[],[]) + LIBS="$ac_save_LIBS" + LDFLAGS="$ac_save_LDFLAGS" + CPPFLAGS="$ac_save_CPPFLAGS" +fi +]) diff -ruN openssh-9.4p1/m4/local.m4 openssh-9.4p1+x509-14.2.1/m4/local.m4 --- openssh-9.4p1/m4/local.m4 1970-01-01 02:00:00.000000000 +0200 +++ openssh-9.4p1+x509-14.2.1/m4/local.m4 2023-08-20 10:07:00.000000000 +0300 @@ -0,0 +1,167 @@ +dnl PKIX-SSH-specific autoconf macros +dnl + +AC_DEFUN([SSH_LANG_PROGRAM_CHECK_FLAGS], [ +AC_LANG_SOURCE([[ +#include +#include +/* Trivial function to help test for flags like -fzero-call-used-regs. +Note compiler does not inform whether this option is supported unless it +runs into the situation where it would need to emit corresponding code.*/ +static int f(int n) {return n;} +int main(int argc, char *argv[]) { + /* Some math to catch -ftrapv problems in the toolchain */ + int i = 123 * argc, j = 456 + argc, k = 789 - argc; + float l = i * 2.1; + double m = l / 0.5; + long long int n = argc * 12345LL, o = 12345LL * (long long int)argc; + long long int p = n * o; + printf("%d %d %d %f %f %lld %lld %lld %d\n", i, j, k, l, m, n, o, p, f(0)); + (void)argv; + return 0; +} +]])]) + +dnl OSSH_CHECK_CFLAG_COMPILE(check_flag[, define_flag]) +dnl Check that $CC accepts a flag 'check_flag'. If it is supported append +dnl 'define_flag' to $CFLAGS. If 'define_flag' is not specified, then append +dnl 'check_flag'. +AC_DEFUN([OSSH_CHECK_CFLAG_COMPILE], [{ + AC_MSG_CHECKING([if $CC supports compile flag $1]) + saved_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS $WERROR $1" + _define_flag="$2" + test "x$_define_flag" = "x" && _define_flag="$1" + AC_COMPILE_IFELSE([SSH_LANG_PROGRAM_CHECK_FLAGS], [ +if $EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null +then + AC_MSG_RESULT([no]) + CFLAGS="$saved_CFLAGS" +else + AC_MSG_RESULT([yes]) + CFLAGS="$saved_CFLAGS $_define_flag" +fi], + [ AC_MSG_RESULT([no]) + CFLAGS="$saved_CFLAGS" ] + ) +}]) + +dnl OSSH_CHECK_CFLAG_LINK(check_flag[, define_flag]) +dnl Check that $CC accepts a flag 'check_flag'. If it is supported append +dnl 'define_flag' to $CFLAGS. If 'define_flag' is not specified, then append +dnl 'check_flag'. +AC_DEFUN([OSSH_CHECK_CFLAG_LINK], [{ + AC_MSG_CHECKING([if $CC supports compile flag $1 and linking succeeds]) + saved_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS $WERROR $1" + _define_flag="$2" + test "x$_define_flag" = "x" && _define_flag="$1" + AC_LINK_IFELSE([SSH_LANG_PROGRAM_CHECK_FLAGS], [ +if $EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null +then + AC_MSG_RESULT([no]) + CFLAGS="$saved_CFLAGS" +else + AC_MSG_RESULT([yes]) + CFLAGS="$saved_CFLAGS $_define_flag" +fi], + [ AC_MSG_RESULT([no]) + CFLAGS="$saved_CFLAGS" ] + ) +}]) + +dnl OSSH_CHECK_LDFLAG_LINK(check_flag[, define_flag]) +dnl Check that $LD accepts a flag 'check_flag'. If it is supported append +dnl 'define_flag' to $LDFLAGS. If 'define_flag' is not specified, then append +dnl 'check_flag'. +AC_DEFUN([OSSH_CHECK_LDFLAG_LINK], [{ + AC_MSG_CHECKING([if $LD supports link flag $1]) + saved_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS $WERROR $1" + _define_flag="$2" + test "x$_define_flag" = "x" && _define_flag="$1" + AC_LINK_IFELSE([SSH_LANG_PROGRAM_CHECK_FLAGS], [ +if $EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null +then + AC_MSG_RESULT([no]) + LDFLAGS="$saved_LDFLAGS" +else + AC_MSG_RESULT([yes]) + LDFLAGS="$saved_LDFLAGS $_define_flag" +fi ], + [ AC_MSG_RESULT([no]) + LDFLAGS="$saved_LDFLAGS" ] + ) +}]) + +dnl OSSH_CHECK_HEADER_FOR_FIELD(field, header, symbol) +dnl Does AC_EGREP_HEADER on 'header' for the string 'field' +dnl If found, set 'symbol' to be defined. Cache the result. +dnl TODO: This is not foolproof, better to compile and read from there +AC_DEFUN([OSSH_CHECK_HEADER_FOR_FIELD], [ +# look for field '$1' in header '$2' + dnl This strips characters illegal to m4 from the header filename + ossh_safe=`echo "$2" | sed 'y%./+-%__p_%'` + dnl + ossh_varname="ossh_cv_$ossh_safe""_has_"$1 + AC_MSG_CHECKING(for $1 field in $2) + AC_CACHE_VAL($ossh_varname, [ + AC_EGREP_HEADER($1, $2, [ dnl + eval "$ossh_varname=yes" dnl + ], [ dnl + eval "$ossh_varname=no" dnl + ]) dnl + ]) + ossh_result=`eval 'echo $'"$ossh_varname"` + if test -n "`echo $ossh_varname`"; then + AC_MSG_RESULT($ossh_result) + if test "x$ossh_result" = "xyes"; then + AC_DEFINE($3, 1, [Define if you have $1 in $2]) + fi + else + AC_MSG_RESULT(no) + fi +]) + +dnl Check for socklen_t: historically on BSD it is an int, and in +dnl POSIX 1g it is a type of its own, but some platforms use different +dnl types for the argument to getsockopt, getpeername, etc. So we +dnl have to test to find something that will work. +AC_DEFUN([TYPE_SOCKLEN_T], +[ + AC_CHECK_TYPE([socklen_t], ,[ + AC_MSG_CHECKING([for socklen_t equivalent]) + AC_CACHE_VAL([curl_cv_socklen_t_equiv], + [ + # Systems have either "struct sockaddr *" or + # "void *" as the second argument to getpeername + curl_cv_socklen_t_equiv= + for arg2 in "struct sockaddr" void; do + for t in int size_t unsigned long "unsigned long"; do + AC_COMPILE_IFELSE([ + AC_LANG_PROGRAM([[ + #include + #include + int getpeername (int, $arg2 *, $t *); + ]], [[ + $t len; + getpeername(0,0,&len); + ]]) + ],[ + curl_cv_socklen_t_equiv="$t" + break + ]) + done + done + + if test "x$curl_cv_socklen_t_equiv" = x; then + AC_MSG_ERROR([Cannot find a type to use in place of socklen_t]) + fi + ]) + AC_MSG_RESULT($curl_cv_socklen_t_equiv) + AC_DEFINE_UNQUOTED(socklen_t, $curl_cv_socklen_t_equiv, + [type to use in place of socklen_t if not defined])], + [#include +#include ]) +]) + diff -ruN openssh-9.4p1/m4/openssh.m4 openssh-9.4p1+x509-14.2.1/m4/openssh.m4 --- openssh-9.4p1/m4/openssh.m4 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/m4/openssh.m4 1970-01-01 02:00:00.000000000 +0200 @@ -1,203 +0,0 @@ -dnl OpenSSH-specific autoconf macros -dnl - -dnl OSSH_CHECK_CFLAG_COMPILE(check_flag[, define_flag]) -dnl Check that $CC accepts a flag 'check_flag'. If it is supported append -dnl 'define_flag' to $CFLAGS. If 'define_flag' is not specified, then append -dnl 'check_flag'. -AC_DEFUN([OSSH_CHECK_CFLAG_COMPILE], [{ - AC_MSG_CHECKING([if $CC supports compile flag $1]) - saved_CFLAGS="$CFLAGS" - CFLAGS="$CFLAGS $WERROR $1" - _define_flag="$2" - test "x$_define_flag" = "x" && _define_flag="$1" - AC_COMPILE_IFELSE([AC_LANG_SOURCE([[ -#include -#include -/* Trivial function to help test for -fzero-call-used-regs */ -void f(int n) {} -int main(int argc, char **argv) { - (void)argv; - /* Some math to catch -ftrapv problems in the toolchain */ - int i = 123 * argc, j = 456 + argc, k = 789 - argc; - float l = i * 2.1; - double m = l / 0.5; - long long int n = argc * 12345LL, o = 12345LL * (long long int)argc; - f(0); - printf("%d %d %d %f %f %lld %lld\n", i, j, k, l, m, n, o); - /* - * Test fallthrough behaviour. clang 10's -Wimplicit-fallthrough does - * not understand comments and we don't use the "fallthrough" attribute - * that it's looking for. - */ - switch(i){ - case 0: j += i; - /* FALLTHROUGH */ - default: j += k; - } - exit(0); -} - ]])], - [ -if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null -then - AC_MSG_RESULT([no]) - CFLAGS="$saved_CFLAGS" -else - AC_MSG_RESULT([yes]) - CFLAGS="$saved_CFLAGS $_define_flag" -fi], - [ AC_MSG_RESULT([no]) - CFLAGS="$saved_CFLAGS" ] - ) -}]) - -dnl OSSH_CHECK_CFLAG_LINK(check_flag[, define_flag]) -dnl Check that $CC accepts a flag 'check_flag'. If it is supported append -dnl 'define_flag' to $CFLAGS. If 'define_flag' is not specified, then append -dnl 'check_flag'. -AC_DEFUN([OSSH_CHECK_CFLAG_LINK], [{ - AC_MSG_CHECKING([if $CC supports compile flag $1 and linking succeeds]) - saved_CFLAGS="$CFLAGS" - CFLAGS="$CFLAGS $WERROR $1" - _define_flag="$2" - test "x$_define_flag" = "x" && _define_flag="$1" - AC_LINK_IFELSE([AC_LANG_SOURCE([[ -#include -#include -int main(int argc, char **argv) { - (void)argv; - /* Some math to catch -ftrapv problems in the toolchain */ - int i = 123 * argc, j = 456 + argc, k = 789 - argc; - float l = i * 2.1; - double m = l / 0.5; - long long int n = argc * 12345LL, o = 12345LL * (long long int)argc; - long long int p = n * o; - printf("%d %d %d %f %f %lld %lld %lld\n", i, j, k, l, m, n, o, p); - exit(0); -} - ]])], - [ -if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null -then - AC_MSG_RESULT([no]) - CFLAGS="$saved_CFLAGS" -else - AC_MSG_RESULT([yes]) - CFLAGS="$saved_CFLAGS $_define_flag" -fi], - [ AC_MSG_RESULT([no]) - CFLAGS="$saved_CFLAGS" ] - ) -}]) - -dnl OSSH_CHECK_LDFLAG_LINK(check_flag[, define_flag]) -dnl Check that $LD accepts a flag 'check_flag'. If it is supported append -dnl 'define_flag' to $LDFLAGS. If 'define_flag' is not specified, then append -dnl 'check_flag'. -AC_DEFUN([OSSH_CHECK_LDFLAG_LINK], [{ - AC_MSG_CHECKING([if $LD supports link flag $1]) - saved_LDFLAGS="$LDFLAGS" - LDFLAGS="$LDFLAGS $WERROR $1" - _define_flag="$2" - test "x$_define_flag" = "x" && _define_flag="$1" - AC_LINK_IFELSE([AC_LANG_SOURCE([[ -#include -#include -int main(int argc, char **argv) { - (void)argv; - /* Some math to catch -ftrapv problems in the toolchain */ - int i = 123 * argc, j = 456 + argc, k = 789 - argc; - float l = i * 2.1; - double m = l / 0.5; - long long int n = argc * 12345LL, o = 12345LL * (long long int)argc; - long long p = n * o; - printf("%d %d %d %f %f %lld %lld %lld\n", i, j, k, l, m, n, o, p); - exit(0); -} - ]])], - [ -if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null -then - AC_MSG_RESULT([no]) - LDFLAGS="$saved_LDFLAGS" -else - AC_MSG_RESULT([yes]) - LDFLAGS="$saved_LDFLAGS $_define_flag" -fi ], - [ AC_MSG_RESULT([no]) - LDFLAGS="$saved_LDFLAGS" ] - ) -}]) - -dnl OSSH_CHECK_HEADER_FOR_FIELD(field, header, symbol) -dnl Does AC_EGREP_HEADER on 'header' for the string 'field' -dnl If found, set 'symbol' to be defined. Cache the result. -dnl TODO: This is not foolproof, better to compile and read from there -AC_DEFUN([OSSH_CHECK_HEADER_FOR_FIELD], [ -# look for field '$1' in header '$2' - dnl This strips characters illegal to m4 from the header filename - ossh_safe=`echo "$2" | sed 'y%./+-%__p_%'` - dnl - ossh_varname="ossh_cv_$ossh_safe""_has_"$1 - AC_MSG_CHECKING(for $1 field in $2) - AC_CACHE_VAL($ossh_varname, [ - AC_EGREP_HEADER($1, $2, [ dnl - eval "$ossh_varname=yes" dnl - ], [ dnl - eval "$ossh_varname=no" dnl - ]) dnl - ]) - ossh_result=`eval 'echo $'"$ossh_varname"` - if test -n "`echo $ossh_varname`"; then - AC_MSG_RESULT($ossh_result) - if test "x$ossh_result" = "xyes"; then - AC_DEFINE($3, 1, [Define if you have $1 in $2]) - fi - else - AC_MSG_RESULT(no) - fi -]) - -dnl Check for socklen_t: historically on BSD it is an int, and in -dnl POSIX 1g it is a type of its own, but some platforms use different -dnl types for the argument to getsockopt, getpeername, etc. So we -dnl have to test to find something that will work. -AC_DEFUN([TYPE_SOCKLEN_T], -[ - AC_CHECK_TYPE([socklen_t], ,[ - AC_MSG_CHECKING([for socklen_t equivalent]) - AC_CACHE_VAL([curl_cv_socklen_t_equiv], - [ - # Systems have either "struct sockaddr *" or - # "void *" as the second argument to getpeername - curl_cv_socklen_t_equiv= - for arg2 in "struct sockaddr" void; do - for t in int size_t unsigned long "unsigned long"; do - AC_COMPILE_IFELSE([ - AC_LANG_PROGRAM([[ - #include - #include - int getpeername (int, $arg2 *, $t *); - ]], [[ - $t len; - getpeername(0,0,&len); - ]]) - ],[ - curl_cv_socklen_t_equiv="$t" - break - ]) - done - done - - if test "x$curl_cv_socklen_t_equiv" = x; then - AC_MSG_ERROR([Cannot find a type to use in place of socklen_t]) - fi - ]) - AC_MSG_RESULT($curl_cv_socklen_t_equiv) - AC_DEFINE_UNQUOTED(socklen_t, $curl_cv_socklen_t_equiv, - [type to use in place of socklen_t if not defined])], - [#include -#include ]) -]) - diff -ruN openssh-9.4p1/mac.c openssh-9.4p1+x509-14.2.1/mac.c --- openssh-9.4p1/mac.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/mac.c 2023-08-20 10:07:01.000000000 +0300 @@ -1,6 +1,7 @@ /* $OpenBSD: mac.c,v 1.35 2019/09/06 04:53:27 djm Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. + * Copyright (c) 2011-2022 Roumen Petrov. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -31,22 +32,26 @@ #include #include +#ifdef HAVE_OPENSSL_FIPS_H +# include /* for FIPS_mode() */ +#endif + #include "digest.h" #include "hmac.h" #include "umac.h" #include "mac.h" #include "misc.h" +#include "xmalloc.h" +#include "log.h" #include "ssherr.h" #include "sshbuf.h" -#include "openbsd-compat/openssl-compat.h" - #define SSH_DIGEST 1 /* SSH_DIGEST_XXX */ #define SSH_UMAC 2 /* UMAC (not integrated with OpenSSL) */ #define SSH_UMAC128 3 struct macalg { - char *name; + const char *name; int type; int alg; int truncatebits; /* truncate digest if != 0 */ @@ -59,8 +64,10 @@ /* Encrypt-and-MAC (encrypt-and-authenticate) variants */ { "hmac-sha1", SSH_DIGEST, SSH_DIGEST_SHA1, 0, 0, 0, 0 }, { "hmac-sha1-96", SSH_DIGEST, SSH_DIGEST_SHA1, 96, 0, 0, 0 }, +#ifdef HAVE_EVP_SHA256 { "hmac-sha2-256", SSH_DIGEST, SSH_DIGEST_SHA256, 0, 0, 0, 0 }, { "hmac-sha2-512", SSH_DIGEST, SSH_DIGEST_SHA512, 0, 0, 0, 0 }, +#endif { "hmac-md5", SSH_DIGEST, SSH_DIGEST_MD5, 0, 0, 0, 0 }, { "hmac-md5-96", SSH_DIGEST, SSH_DIGEST_MD5, 96, 0, 0, 0 }, { "umac-64@openssh.com", SSH_UMAC, 0, 0, 128, 64, 0 }, @@ -69,8 +76,10 @@ /* Encrypt-then-MAC variants */ { "hmac-sha1-etm@openssh.com", SSH_DIGEST, SSH_DIGEST_SHA1, 0, 0, 0, 1 }, { "hmac-sha1-96-etm@openssh.com", SSH_DIGEST, SSH_DIGEST_SHA1, 96, 0, 0, 1 }, +#ifdef HAVE_EVP_SHA256 { "hmac-sha2-256-etm@openssh.com", SSH_DIGEST, SSH_DIGEST_SHA256, 0, 0, 0, 1 }, { "hmac-sha2-512-etm@openssh.com", SSH_DIGEST, SSH_DIGEST_SHA512, 0, 0, 0, 1 }, +#endif { "hmac-md5-etm@openssh.com", SSH_DIGEST, SSH_DIGEST_MD5, 0, 0, 0, 1 }, { "hmac-md5-96-etm@openssh.com", SSH_DIGEST, SSH_DIGEST_MD5, 96, 0, 0, 1 }, { "umac-64-etm@openssh.com", SSH_UMAC, 0, 0, 128, 64, 1 }, @@ -79,6 +88,21 @@ { NULL, 0, 0, 0, 0, 0, 0 } }; +static inline int/*bool*/ +macalg_allowed(const struct macalg *m) { +#ifdef OPENSSL_FIPS + if (FIPS_mode()) { + if (m->type != SSH_DIGEST) + return(0); + if (ssh_digest_bytes(m->alg) == 0) + return(0); + } +#else + UNUSED(m); +#endif + return(1); +} + /* Returns a list of supported MACs separated by the specified char. */ char * mac_alg_list(char sep) @@ -88,6 +112,8 @@ const struct macalg *m; for (m = macs; m->name != NULL; m++) { + if (!macalg_allowed(m)) + continue; if (ret != NULL) ret[rlen++] = sep; nlen = strlen(m->name); @@ -129,6 +155,8 @@ for (m = macs; m->name != NULL; m++) { if (strcmp(name, m->name) != 0) continue; + if (!macalg_allowed(m)) + continue; if (mac != NULL) return mac_setup_by_alg(mac, m); return 0; diff -ruN openssh-9.4p1/mac.h openssh-9.4p1+x509-14.2.1/mac.h --- openssh-9.4p1/mac.h 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/mac.h 2023-08-20 10:07:00.000000000 +0300 @@ -1,6 +1,7 @@ /* $OpenBSD: mac.h,v 1.10 2016/07/08 03:44:42 djm Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. + * Copyright (c) 2011 Roumen Petrov. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -50,4 +51,8 @@ const u_char *, size_t); void mac_clear(struct sshmac *); +#ifdef OPENSSL_FIPS +extern char* only_fips_valid_macs(const char*); +#endif + #endif /* SSHMAC_H */ diff -ruN openssh-9.4p1/Makefile.in openssh-9.4p1+x509-14.2.1/Makefile.in --- openssh-9.4p1/Makefile.in 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/Makefile.in 2023-08-20 10:07:01.000000000 +0300 @@ -1,4 +1,5 @@ -SHELL=@SH@ +# uncomment if you run a non bourne compatible shell. Ie. csh +#SHELL = @SH@ AUTORECONF=autoreconf @@ -12,64 +13,62 @@ mandir=@mandir@ mansubdir=@mansubdir@ sysconfdir=@sysconfdir@ +sshcadir=@sshcadir@ piddir=@piddir@ srcdir=@srcdir@ -top_srcdir=@top_srcdir@ -abs_top_srcdir=@abs_top_srcdir@ -abs_top_builddir=@abs_top_builddir@ +abs_srcdir=@abs_srcdir@ +abs_builddir=@abs_builddir@ DESTDIR= VPATH=@srcdir@ -SSH_PROGRAM=@bindir@/ssh -ASKPASS_PROGRAM=$(libexecdir)/ssh-askpass -SFTP_SERVER=$(libexecdir)/sftp-server -SSH_KEYSIGN=$(libexecdir)/ssh-keysign -SSH_PKCS11_HELPER=$(libexecdir)/ssh-pkcs11-helper -SSH_SK_HELPER=$(libexecdir)/ssh-sk-helper PRIVSEP_PATH=@PRIVSEP_PATH@ SSH_PRIVSEP_USER=@SSH_PRIVSEP_USER@ STRIP_OPT=@STRIP_OPT@ TEST_SHELL=@TEST_SHELL@ -BUILDDIR=@abs_top_builddir@ +BUILDDIR=@abs_builddir@ PATHS= -DSSHDIR=\"$(sysconfdir)\" \ - -D_PATH_SSH_PROGRAM=\"$(SSH_PROGRAM)\" \ - -D_PATH_SSH_ASKPASS_DEFAULT=\"$(ASKPASS_PROGRAM)\" \ - -D_PATH_SFTP_SERVER=\"$(SFTP_SERVER)\" \ - -D_PATH_SSH_KEY_SIGN=\"$(SSH_KEYSIGN)\" \ - -D_PATH_SSH_PKCS11_HELPER=\"$(SSH_PKCS11_HELPER)\" \ - -D_PATH_SSH_SK_HELPER=\"$(SSH_SK_HELPER)\" \ + -DSSHCADIR=\"$(sshcadir)\" \ + -DSSHBINDIR=\"$(bindir)\" \ + -DSSHLIBEXECDIR=\"$(libexecdir)\" \ -D_PATH_SSH_PIDDIR=\"$(piddir)\" \ -D_PATH_PRIVSEP_CHROOT_DIR=\"$(PRIVSEP_PATH)\" +FIPSLD_CC=@FIPSLD_CC@ CC=@CC@ LD=@LD@ -CFLAGS=@CFLAGS@ -CFLAGS_NOPIE=@CFLAGS_NOPIE@ -CPPFLAGS=-I. -I$(srcdir) @CPPFLAGS@ $(PATHS) @DEFS@ -PICFLAG=@PICFLAG@ +CFLAGS=@CFLAGS@ $(CFLAGS_EXTRA) +CPPFLAGS=-I. -I$(srcdir) @CPPFLAGS@ @LDAP_CPPFLAGS@ $(PATHS) @DEFS@ LIBS=@LIBS@ -CHANNELLIBS=@CHANNELLIBS@ K5LIBS=@K5LIBS@ GSSLIBS=@GSSLIBS@ SSHDLIBS=@SSHDLIBS@ LIBEDIT=@LIBEDIT@ -LIBFIDO2=@LIBFIDO2@ +LIBOCSP=@LIBOCSP@ +LIBLDAP=@LDAP_LDFLAGS@ @LDAP_LIBS@ +FIPS_LIBS=@FIPS_LIBS@ AR=@AR@ AWK=@AWK@ RANLIB=@RANLIB@ INSTALL=@INSTALL@ SED=@SED@ XAUTH_PATH=@XAUTH_PATH@ -LDFLAGS=-L. -Lopenbsd-compat/ @LDFLAGS@ -LDFLAGS_NOPIE=-L. -Lopenbsd-compat/ @LDFLAGS_NOPIE@ +XLDFLAGS = @XLDFLAGS@ +LDFLAGS=-L. -Lopenbsd-compat/ @LDFLAGS@ $(XLDFLAGS) EXEEXT=@EXEEXT@ MANFMT=@MANFMT@ -MKDIR_P=@MKDIR_P@ +MKDIR_P=$(srcdir)/install-sh -d -.SUFFIXES: .lo +@LDAP_ON@LDAP_OBJS=x509_by_ldap.o e_ldap.o ssh_ldap.o +@LDAP_OFF@LDAP_OBJS= -TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-keyscan${EXEEXT} ssh-keysign${EXEEXT} ssh-pkcs11-helper$(EXEEXT) ssh-agent$(EXEEXT) scp$(EXEEXT) sftp-server$(EXEEXT) sftp$(EXEEXT) ssh-sk-helper$(EXEEXT) +@OCSP_ON@OCSP_OBJS=ssh-ocsp.o +@OCSP_OFF@OCSP_OBJS= + +SSHX509_OBJS=ssh-x509.o ssh-xkalg.o x509_nm_cmp.o key-eng.o a_utf8.o +X509STORE_OBJS=x509store.o x509_by_store.o $(LDAP_OBJS) + +TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-keyscan${EXEEXT} ssh-keysign${EXEEXT} ssh-pkcs11-helper$(EXEEXT) ssh-agent$(EXEEXT) scp$(EXEEXT) sftp-server$(EXEEXT) sftp$(EXEEXT) XMSS_OBJS=\ ssh-xmss.o \ @@ -85,6 +84,7 @@ ssherr.o \ sshbuf.o \ sshkey.o \ + sshkey-crypto.o \ sshbuf-getput-basic.o \ sshbuf-misc.o \ sshbuf-getput-crypto.o \ @@ -95,32 +95,32 @@ LIBSSH_OBJS=${LIBOPENSSH_OBJS} \ authfd.o authfile.o \ canohost.o channels.o cipher.o cipher-aes.o cipher-aesctr.o \ - cleanup.o \ + cipher-ctr.o cleanup.o \ compat.o fatal.o hostfile.o \ - log.o match.o moduli.o nchan.o packet.o \ + log.o log-crypto.o match.o moduli.o nchan.o packet.o \ readpass.o ttymodes.o xmalloc.o addr.o addrmatch.o \ atomicio.o dispatch.o mac.o misc.o utf8.o \ - monitor_fdpass.o rijndael.o ssh-dss.o ssh-ecdsa.o ssh-ecdsa-sk.o \ - ssh-ed25519-sk.o ssh-rsa.o dh.o \ - msg.o progressmeter.o dns.o entropy.o gss-genr.o umac.o umac128.o \ - ssh-pkcs11.o smult_curve25519_ref.o \ + monitor_fdpass.o rijndael.o ssh-dss.o ssh-ecdsa.o ssh-rsa.o dh.o \ + $(SSHX509_OBJS) \ + msg.o progressmeter.o dns.o entropy.o ssh-prngd.o gss-genr.o umac.o umac128.o \ + ssh-pkcs11-err.o smult_curve25519_ref.o \ poly1305.o chacha.o cipher-chachapoly.o cipher-chachapoly-libcrypto.o \ - ssh-ed25519.o digest-openssl.o digest-libc.o \ - hmac.o ed25519.o hash.o \ - kex.o kexdh.o kexgex.o kexecdh.o kexc25519.o \ - kexgexc.o kexgexs.o \ - kexsntrup761x25519.o sntrup761.o kexgen.o \ - sftp-realpath.o platform-pledge.o platform-tracing.o platform-misc.o \ + ssh-ed25519.o digest-openssl.o digest-libc.o hmac.o \ + ed25519.o hash.o blocks.o \ + kex.o kex-crypto.o kexdh.o kexgex.o kexecdh.o kexc25519.o \ + kexgen.o kexgexc.o kexgexs.o \ + kexsntrup761x25519.o sntrup761.o \ + platform-pledge.o platform-tracing.o platform-misc.o \ sshbuf-io.o -SKOBJS= ssh-sk-client.o - SSHOBJS= ssh.o readconf.o clientloop.o sshtty.o \ - sshconnect.o sshconnect2.o mux.o $(SKOBJS) + ssh-pkcs11.o $(X509STORE_OBJS) $(OCSP_OBJS) \ + sshconnect.o sshconnect2.o mux.o SSHDOBJS=sshd.o auth-rhosts.o auth-passwd.o \ audit.o audit-bsm.o audit-linux.o platform.o \ - sshpty.o sshlogin.o servconf.o serverloop.o \ + sshpty.o sshlogin.o servconf.o serverloop.o ssh-pselect.o \ + $(X509STORE_OBJS) $(OCSP_OBJS) \ auth.o auth2.o auth-options.o session.o \ auth2-chall.o groupaccess.o \ auth-bsdauth.o auth2-hostbased.o auth2-kbdint.o \ @@ -131,32 +131,30 @@ srclimit.o sftp-server.o sftp-common.o \ sandbox-null.o sandbox-rlimit.o sandbox-systrace.o sandbox-darwin.o \ sandbox-seccomp-filter.o sandbox-capsicum.o sandbox-pledge.o \ - sandbox-solaris.o uidswap.o $(SKOBJS) + sandbox-solaris.o uidswap.o SFTP_CLIENT_OBJS=sftp-common.o sftp-client.o sftp-glob.o SCP_OBJS= scp.o progressmeter.o $(SFTP_CLIENT_OBJS) -SSHADD_OBJS= ssh-add.o $(SKOBJS) - -SSHAGENT_OBJS= ssh-agent.o ssh-pkcs11-client.o $(SKOBJS) +SSHADD_OBJS= ssh-add.o -SSHKEYGEN_OBJS= ssh-keygen.o sshsig.o $(SKOBJS) +SSHAGENT_OBJS= ssh-agent.o ssh-pkcs11-client.o -SSHKEYSIGN_OBJS=ssh-keysign.o readconf.o uidswap.o $(SKOBJS) +SSHKEYGEN_OBJS= ssh-keygen.o ssh-pkcs11.o -P11HELPER_OBJS= ssh-pkcs11-helper.o ssh-pkcs11.o $(SKOBJS) +SSHKEYSIGN_OBJS=ssh-keysign.o readconf.o uidswap.o x509store.o -SKHELPER_OBJS= ssh-sk-helper.o ssh-sk.o sk-usbhid.o +P11HELPER_OBJS= ssh-pkcs11-helper.o ssh-pkcs11.o -SSHKEYSCAN_OBJS=ssh-keyscan.o $(SKOBJS) +SSHKEYSCAN_OBJS=ssh-keyscan.o -SFTPSERVER_OBJS=sftp-common.o sftp-server.o sftp-server-main.o +SFTPSERVER_OBJS=sftp-server-main.o sftp-server.o sftp-common.o SFTP_OBJS= sftp.o sftp-usergroup.o progressmeter.o $(SFTP_CLIENT_OBJS) -MANPAGES = moduli.5.out scp.1.out ssh-add.1.out ssh-agent.1.out ssh-keygen.1.out ssh-keyscan.1.out ssh.1.out sshd.8.out sftp-server.8.out sftp.1.out ssh-keysign.8.out ssh-pkcs11-helper.8.out ssh-sk-helper.8.out sshd_config.5.out ssh_config.5.out -MANPAGES_IN = moduli.5 scp.1 ssh-add.1 ssh-agent.1 ssh-keygen.1 ssh-keyscan.1 ssh.1 sshd.8 sftp-server.8 sftp.1 ssh-keysign.8 ssh-pkcs11-helper.8 ssh-sk-helper.8 sshd_config.5 ssh_config.5 +MANPAGES = moduli.5.out scp.1.out ssh-add.1.out ssh-agent.1.out ssh-keygen.1.out ssh-keyscan.1.out ssh.1.out sshd.8.out sftp-server.8.out sftp.1.out ssh-keysign.8.out ssh-pkcs11-helper.8.out sshd_config.5.out ssh_config.5.out ssh_engine.5.out +MANPAGES_IN = moduli.5 scp.1 ssh-add.1 ssh-agent.1 ssh-keygen.1 ssh-keyscan.1 ssh.1 sshd.8 sftp-server.8 sftp.1 ssh-keysign.8 ssh-pkcs11-helper.8 sshd_config.5 ssh_config.5 ssh_engine.5 MANTYPE = @MANTYPE@ CONFIGFILES=sshd_config.out ssh_config.out moduli.out @@ -173,6 +171,10 @@ -e 's|/etc/ssh/ssh_host_dsa_key|$(sysconfdir)/ssh_host_dsa_key|g' \ -e 's|/etc/ssh/ssh_host_rsa_key|$(sysconfdir)/ssh_host_rsa_key|g' \ -e 's|/etc/ssh/ssh_host_ed25519_key|$(sysconfdir)/ssh_host_ed25519_key|g' \ + -e 's|/etc/ssh/ca/ca-bundle.crt|$(sshcadir)/ca-bundle.crt|g' \ + -e 's|/etc/ssh/ca/crt|$(sshcadir)/crt|g' \ + -e 's|/etc/ssh/ca/ca-bundle.crl|$(sshcadir)/ca-bundle.crl|g' \ + -e 's|/etc/ssh/ca/crl|$(sshcadir)/crl|g' \ -e 's|/var/run/sshd.pid|$(piddir)/sshd.pid|g' \ -e 's|/etc/moduli|$(sysconfdir)/moduli|g' \ -e 's|/etc/ssh/moduli|$(sysconfdir)/moduli|g' \ @@ -185,11 +187,23 @@ FIXALGORITHMSCMD= $(SHELL) $(srcdir)/fixalgorithms $(SED) \ @UNSUPPORTED_ALGORITHMS@ -all: $(CONFIGFILES) $(MANPAGES) $(TARGETS) +all: configure-check $(CONFIGFILES) $(MANPAGES) $(TARGETS) $(LIBSSH_OBJS): Makefile.in config.h $(SSHOBJS): Makefile.in config.h +ssh-prngd.o: openbsd-compat/port-prngd.c $(SSHDOBJS): Makefile.in config.h +ssh-pselect.o: openbsd-compat/bsd-pselect.c +configure-check: $(srcdir)/configure + +$(srcdir)/configure: \ + $(srcdir)/m4/android.m4 \ + $(srcdir)/m4/c.m4 \ + $(srcdir)/m4/ldap.m4 \ + $(srcdir)/m4/local.m4 \ + $(srcdir)/configure.ac + @(echo; echo " ERROR: $@ is out of date; please re-genenarate (and configure)"; echo) 1>&2 + @exit 1 .c.o: $(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $@ @@ -203,45 +217,53 @@ $(AR) rv $@ $(LIBSSH_OBJS) $(RANLIB) $@ -ssh$(EXEEXT): $(LIBCOMPAT) libssh.a $(SSHOBJS) - $(LD) -o $@ $(SSHOBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) $(GSSLIBS) $(CHANNELLIBS) +libappinfo.so: appinfo.o + $(LD) -shared -o $@ appinfo.o -sshd$(EXEEXT): libssh.a $(LIBCOMPAT) $(SSHDOBJS) - $(LD) -o $@ $(SSHDOBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(SSHDLIBS) $(LIBS) $(GSSLIBS) $(K5LIBS) $(CHANNELLIBS) +XDEPLIBS = @XDEPLIBS@ +DEPLIBS = $(LIBCOMPAT) libssh.a $(XDEPLIBS) -scp$(EXEEXT): $(LIBCOMPAT) libssh.a $(SCP_OBJS) - $(LD) -o $@ $(SCP_OBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) -ssh-add$(EXEEXT): $(LIBCOMPAT) libssh.a $(SSHADD_OBJS) - $(LD) -o $@ $(SSHADD_OBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) $(CHANNELLIBS) +ssh$(EXEEXT): $(DEPLIBS) $(SSHOBJS) + $(LD) -o $@ $(SSHOBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(LIBLDAP) $(LIBOCSP) $(FIPS_LIBS) $(LIBS) $(GSSLIBS) + @@FIPSHMAC@ $@ -ssh-agent$(EXEEXT): $(LIBCOMPAT) libssh.a $(SSHAGENT_OBJS) - $(LD) -o $@ $(SSHAGENT_OBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) $(CHANNELLIBS) +sshd$(EXEEXT): $(DEPLIBS) $(SSHDOBJS) + $(LD) -o $@ $(SSHDOBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(LIBLDAP) $(LIBOCSP) $(SSHDLIBS) $(FIPS_LIBS) $(LIBS) $(GSSLIBS) $(K5LIBS) + @@FIPSHMAC@ $@ -ssh-keygen$(EXEEXT): $(LIBCOMPAT) libssh.a $(SSHKEYGEN_OBJS) - $(LD) -o $@ $(SSHKEYGEN_OBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) $(CHANNELLIBS) +scp$(EXEEXT): $(DEPLIBS) $(SCP_OBJS) + $(LD) -o $@ $(SCP_OBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) -ssh-keysign$(EXEEXT): $(LIBCOMPAT) libssh.a $(SSHKEYSIGN_OBJS) - $(LD) -o $@ $(SSHKEYSIGN_OBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) $(CHANNELLIBS) +ssh-add$(EXEEXT): $(DEPLIBS) $(SSHADD_OBJS) + $(LD) -o $@ $(SSHADD_OBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) -ssh-pkcs11-helper$(EXEEXT): $(LIBCOMPAT) libssh.a $(P11HELPER_OBJS) - $(LD) -o $@ $(P11HELPER_OBJS) $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS) $(CHANNELLIBS) +ssh-agent$(EXEEXT): $(DEPLIBS) $(SSHAGENT_OBJS) + $(LD) -o $@ $(SSHAGENT_OBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(FIPS_LIBS) $(LIBS) + @@FIPSHMAC@ $@ -ssh-sk-helper$(EXEEXT): $(LIBCOMPAT) libssh.a $(SKHELPER_OBJS) - $(LD) -o $@ $(SKHELPER_OBJS) $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS) $(LIBFIDO2) $(CHANNELLIBS) +ssh-keygen$(EXEEXT): $(DEPLIBS) $(SSHKEYGEN_OBJS) + $(LD) -o $@ $(SSHKEYGEN_OBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(FIPS_LIBS) $(LIBS) + @@FIPSHMAC@ $@ -ssh-keyscan$(EXEEXT): $(LIBCOMPAT) libssh.a $(SSHKEYSCAN_OBJS) - $(LD) -o $@ $(SSHKEYSCAN_OBJS) $(LDFLAGS) -lssh -lopenbsd-compat -lssh $(LIBS) $(CHANNELLIBS) +ssh-keysign$(EXEEXT): $(DEPLIBS) $(SSHKEYSIGN_OBJS) + $(LD) -o $@ $(SSHKEYSIGN_OBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) -sftp-server$(EXEEXT): $(LIBCOMPAT) libssh.a $(SFTPSERVER_OBJS) - $(LD) -o $@ $(SFTPSERVER_OBJS) $(LDFLAGS) -lssh -lopenbsd-compat -lssh $(LIBS) +ssh-pkcs11-helper$(EXEEXT): $(DEPLIBS) $(P11HELPER_OBJS) + $(LD) -o $@ $(P11HELPER_OBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) -sftp$(EXEEXT): $(LIBCOMPAT) libssh.a $(SFTP_OBJS) +ssh-keyscan$(EXEEXT): $(DEPLIBS) $(SSHKEYSCAN_OBJS) + $(LD) -o $@ $(SSHKEYSCAN_OBJS) $(LDFLAGS) -lssh -lopenbsd-compat -lssh $(LIBS) + +sftp-server$(EXEEXT): $(DEPLIBS) $(SFTPSERVER_OBJS) + $(LD) -o $@ $(SFTPSERVER_OBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) + +sftp$(EXEEXT): $(DEPLIBS) $(SFTP_OBJS) $(LD) -o $@ $(SFTP_OBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) $(LIBEDIT) # test driver for the loginrec code - not built by default -logintest: logintest.o $(LIBCOMPAT) libssh.a loginrec.o - $(LD) -o $@ logintest.o $(LDFLAGS) loginrec.o -lopenbsd-compat -lssh $(LIBS) +logintest: logintest.o $(DEPLIBS) loginrec.o + $(LD) -o $@ logintest.o $(LDFLAGS) loginrec.o -lssh -lopenbsd-compat $(LIBS) $(MANPAGES): $(MANPAGES_IN) if test "$(MANTYPE)" = "cat"; then \ @@ -264,11 +286,14 @@ moduli: echo -clean: regressclean - rm -f *.o *.lo *.a $(TARGETS) logintest config.cache config.log +localclean: + rm -f *.o *.a $(TARGETS) logintest config.cache config.log rm -f *.out core survey - rm -f regress/check-perm$(EXEEXT) - rm -f regress/mkdtemp$(EXEEXT) + rm -f regress/check-perm$(EXEEXT) regress/check-perm.o + rm -f regress/mkdtemp$(EXEEXT) regress/mkdtemp.o + rm -f regress/modpipe$(EXEEXT) regress/modpipe.o + rm -f regress/netcat$(EXEEXT) regress/netcat.o + rm -f regress/setuid-allowed$(EXEEXT) regress/setuid-allowed.o rm -f regress/unittests/test_helper/*.a rm -f regress/unittests/test_helper/*.o rm -f regress/unittests/authopt/*.o @@ -289,51 +314,20 @@ rm -f regress/unittests/sshbuf/test_sshbuf$(EXEEXT) rm -f regress/unittests/sshkey/*.o rm -f regress/unittests/sshkey/test_sshkey$(EXEEXT) - rm -f regress/unittests/sshsig/*.o - rm -f regress/unittests/sshsig/test_sshsig$(EXEEXT) rm -f regress/unittests/utf8/*.o rm -f regress/unittests/utf8/test_utf8$(EXEEXT) - rm -f regress/misc/sk-dummy/*.o - rm -f regress/misc/sk-dummy/*.lo - rm -f regress/misc/sk-dummy/sk-dummy.so + +clean: regressclean localclean (cd openbsd-compat && $(MAKE) clean) -distclean: regressclean - rm -f *.o *.a $(TARGETS) logintest config.cache config.log - rm -f *.out core opensshd.init openssh.xml +distclean: regressclean localclean + rm -f opensshd.init openssh.xml rm -f Makefile buildpkg.sh config.h config.status - rm -f survey.sh openbsd-compat/regress/Makefile *~ + rm -f survey.sh openbsd-compat/regress/Makefile *~ rm -rf autom4te.cache - rm -f regress/check-perm - rm -f regress/mkdtemp - rm -f regress/unittests/test_helper/*.a - rm -f regress/unittests/test_helper/*.o - rm -f regress/unittests/authopt/*.o - rm -f regress/unittests/authopt/test_authopt - rm -f regress/unittests/bitmap/*.o - rm -f regress/unittests/bitmap/test_bitmap - rm -f regress/unittests/conversion/*.o - rm -f regress/unittests/conversion/test_conversion - rm -f regress/unittests/hostkeys/*.o - rm -f regress/unittests/hostkeys/test_hostkeys - rm -f regress/unittests/kex/*.o - rm -f regress/unittests/kex/test_kex - rm -f regress/unittests/match/*.o - rm -f regress/unittests/match/test_match - rm -f regress/unittests/misc/*.o - rm -f regress/unittests/misc/test_misc - rm -f regress/unittests/sshbuf/*.o - rm -f regress/unittests/sshbuf/test_sshbuf - rm -f regress/unittests/sshkey/*.o - rm -f regress/unittests/sshkey/test_sshkey - rm -f regress/unittests/sshsig/*.o - rm -f regress/unittests/sshsig/test_sshsig - rm -f regress/unittests/utf8/*.o - rm -f regress/unittests/utf8/test_utf8 - rm -f regress/misc/sk-dummy/*.o - rm -f regress/misc/sk-dummy/*.lo - rm -f regress/misc/sk-dummy/sk-dummy.so (cd openbsd-compat && $(MAKE) distclean) + rm -f tests/env + (cd tests/CA && $(MAKE) distclean) if test -d pkg ; then \ rm -fr pkg ; \ fi @@ -351,38 +345,26 @@ @for f in $(MANPAGES_IN) ; do \ base=`echo $$f | sed 's/\..*$$//'` ; \ echo "$$f -> $$base.0" ; \ + LANG=C LANGUAGE=C LC_ALL=C \ $(MANFMT) $$f | cat -v | sed -e 's/.\^H//g' \ >$$base.0 ; \ done -depend: depend-rebuild - rm -f .depend.bak - -depend-rebuild: - mv .depend .depend.old - rm -f config.h .depend - touch config.h .depend - makedepend -w1000 -Y. -f .depend *.c 2>/dev/null - (echo '# Automatically generated by makedepend.'; \ - echo '# Run "make depend" to rebuild.'; sort .depend ) >.depend.tmp - mv .depend.tmp .depend - rm -f .depend.bak - mv .depend.old .depend.bak - rm -f config.h - -depend-check: depend-rebuild - cmp .depend .depend.bak || (echo .depend stale && exit 1) - -distprep: catman-do depend-check +distprep: $(AUTORECONF) - -rm -rf autom4te.cache .depend.bak + -rm -rf autom4te.cache + @test -n "$(MANFMT)" && echo "run 'make -f Makefile.in catman-do MANFMT=....' with appropriate for you host MANFMT macro" install: $(CONFIGFILES) $(MANPAGES) $(TARGETS) install-files install-sysconf host-key check-config install-nokeys: $(CONFIGFILES) $(MANPAGES) $(TARGETS) install-files install-sysconf install-nosysconf: $(CONFIGFILES) $(MANPAGES) $(TARGETS) install-files check-config: - -$(DESTDIR)$(sbindir)/sshd -t -f $(DESTDIR)$(sysconfdir)/sshd_config + -@if test -z "$(DESTDIR)" ; then \ + $(sbindir)/sshd -t -f $(sysconfdir)/sshd_config; \ + else \ + echo "skip $@ - no host-keys in staged installs"; \ + fi install-files: $(MKDIR_P) $(DESTDIR)$(bindir) @@ -391,6 +373,8 @@ $(MKDIR_P) $(DESTDIR)$(mandir)/$(mansubdir)5 $(MKDIR_P) $(DESTDIR)$(mandir)/$(mansubdir)8 $(MKDIR_P) $(DESTDIR)$(libexecdir) + $(MKDIR_P) $(DESTDIR)$(sshcadir) + $(MKDIR_P) $(DESTDIR)$(piddir) $(MKDIR_P) -m 0755 $(DESTDIR)$(PRIVSEP_PATH) $(INSTALL) -m 0755 $(STRIP_OPT) ssh$(EXEEXT) $(DESTDIR)$(bindir)/ssh$(EXEEXT) $(INSTALL) -m 0755 $(STRIP_OPT) scp$(EXEEXT) $(DESTDIR)$(bindir)/scp$(EXEEXT) @@ -399,11 +383,14 @@ $(INSTALL) -m 0755 $(STRIP_OPT) ssh-keygen$(EXEEXT) $(DESTDIR)$(bindir)/ssh-keygen$(EXEEXT) $(INSTALL) -m 0755 $(STRIP_OPT) ssh-keyscan$(EXEEXT) $(DESTDIR)$(bindir)/ssh-keyscan$(EXEEXT) $(INSTALL) -m 0755 $(STRIP_OPT) sshd$(EXEEXT) $(DESTDIR)$(sbindir)/sshd$(EXEEXT) - $(INSTALL) -m 4711 $(STRIP_OPT) ssh-keysign$(EXEEXT) $(DESTDIR)$(SSH_KEYSIGN)$(EXEEXT) - $(INSTALL) -m 0755 $(STRIP_OPT) ssh-pkcs11-helper$(EXEEXT) $(DESTDIR)$(SSH_PKCS11_HELPER)$(EXEEXT) - $(INSTALL) -m 0755 $(STRIP_OPT) ssh-sk-helper$(EXEEXT) $(DESTDIR)$(SSH_SK_HELPER)$(EXEEXT) + $(INSTALL) -m 4711 $(STRIP_OPT) ssh-keysign$(EXEEXT) $(DESTDIR)$(libexecdir)/ssh-keysign$(EXEEXT) + $(INSTALL) -m 0755 $(STRIP_OPT) ssh-pkcs11-helper$(EXEEXT) $(DESTDIR)$(libexecdir)/ssh-pkcs11-helper$(EXEEXT) $(INSTALL) -m 0755 $(STRIP_OPT) sftp$(EXEEXT) $(DESTDIR)$(bindir)/sftp$(EXEEXT) - $(INSTALL) -m 0755 $(STRIP_OPT) sftp-server$(EXEEXT) $(DESTDIR)$(SFTP_SERVER)$(EXEEXT) + $(INSTALL) -m 0755 $(STRIP_OPT) sftp-server$(EXEEXT) $(DESTDIR)$(libexecdir)/sftp-server$(EXEEXT) + @@FIPSHMAC@ $(DESTDIR)$(bindir)/ssh$(EXEEXT) + @@FIPSHMAC@ $(DESTDIR)$(bindir)/ssh-agent$(EXEEXT) + @@FIPSHMAC@ $(DESTDIR)$(bindir)/ssh-keygen$(EXEEXT) + @@FIPSHMAC@ $(DESTDIR)$(sbindir)/sshd$(EXEEXT) $(INSTALL) -m 644 ssh.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/ssh.1 $(INSTALL) -m 644 scp.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/scp.1 $(INSTALL) -m 644 ssh-add.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-add.1 @@ -413,12 +400,12 @@ $(INSTALL) -m 644 moduli.5.out $(DESTDIR)$(mandir)/$(mansubdir)5/moduli.5 $(INSTALL) -m 644 sshd_config.5.out $(DESTDIR)$(mandir)/$(mansubdir)5/sshd_config.5 $(INSTALL) -m 644 ssh_config.5.out $(DESTDIR)$(mandir)/$(mansubdir)5/ssh_config.5 + $(INSTALL) -m 644 ssh_engine.5.out $(DESTDIR)$(mandir)/$(mansubdir)5/ssh_engine.5 $(INSTALL) -m 644 sshd.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/sshd.8 $(INSTALL) -m 644 sftp.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/sftp.1 $(INSTALL) -m 644 sftp-server.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/sftp-server.8 $(INSTALL) -m 644 ssh-keysign.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-keysign.8 $(INSTALL) -m 644 ssh-pkcs11-helper.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-pkcs11-helper.8 - $(INSTALL) -m 644 ssh-sk-helper.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-sk-helper.8 install-sysconf: $(MKDIR_P) $(DESTDIR)$(sysconfdir) @@ -449,7 +436,6 @@ fi host-key-force: ssh-keygen$(EXEEXT) ssh$(EXEEXT) - ./ssh-keygen -t dsa -f $(DESTDIR)$(sysconfdir)/ssh_host_dsa_key -N "" ./ssh-keygen -t rsa -f $(DESTDIR)$(sysconfdir)/ssh_host_rsa_key -N "" ./ssh-keygen -t ed25519 -f $(DESTDIR)$(sysconfdir)/ssh_host_ed25519_key -N "" if ./ssh -Q key | grep ecdsa >/dev/null ; then \ @@ -476,10 +462,9 @@ -rm -f $(DESTDIR)$(bindir)/ssh-keyscan$(EXEEXT) -rm -f $(DESTDIR)$(bindir)/sftp$(EXEEXT) -rm -f $(DESTDIR)$(sbindir)/sshd$(EXEEXT) - -rm -r $(DESTDIR)$(SFTP_SERVER)$(EXEEXT) - -rm -f $(DESTDIR)$(SSH_KEYSIGN)$(EXEEXT) - -rm -f $(DESTDIR)$(SSH_PKCS11_HELPER)$(EXEEXT) - -rm -f $(DESTDIR)$(SSH_SK_HELPER)$(EXEEXT) + -rm -r $(DESTDIR)$(libexecdir)/sftp-server$(EXEEXT) + -rm -f $(DESTDIR)$(libexecdir)/ssh-keysign$(EXEEXT) + -rm -f $(DESTDIR)$(libexecdir)/ssh-pkcs11-helper$(EXEEXT) -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/ssh.1 -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/scp.1 -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-add.1 @@ -491,50 +476,44 @@ -rm -f $(DESTDIR)$(mandir)/$(mansubdir)8/sftp-server.8 -rm -f $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-keysign.8 -rm -f $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-pkcs11-helper.8 - -rm -f $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-sk-helper.8 regress-prep: - $(MKDIR_P) `pwd`/regress/unittests/test_helper - $(MKDIR_P) `pwd`/regress/unittests/authopt - $(MKDIR_P) `pwd`/regress/unittests/bitmap - $(MKDIR_P) `pwd`/regress/unittests/conversion - $(MKDIR_P) `pwd`/regress/unittests/hostkeys - $(MKDIR_P) `pwd`/regress/unittests/kex - $(MKDIR_P) `pwd`/regress/unittests/match - $(MKDIR_P) `pwd`/regress/unittests/misc - $(MKDIR_P) `pwd`/regress/unittests/sshbuf - $(MKDIR_P) `pwd`/regress/unittests/sshkey - $(MKDIR_P) `pwd`/regress/unittests/sshsig - $(MKDIR_P) `pwd`/regress/unittests/utf8 - $(MKDIR_P) `pwd`/regress/misc/sk-dummy - [ -f `pwd`/regress/Makefile ] || \ - ln -s `cd $(srcdir) && pwd`/regress/Makefile `pwd`/regress/Makefile + $(MKDIR_P) regress/unittests/test_helper + $(MKDIR_P) regress/unittests/authopt + $(MKDIR_P) regress/unittests/bitmap + $(MKDIR_P) regress/unittests/conversion + $(MKDIR_P) regress/unittests/hostkeys + $(MKDIR_P) regress/unittests/kex + $(MKDIR_P) regress/unittests/match + $(MKDIR_P) regress/unittests/misc + $(MKDIR_P) regress/unittests/sshbuf + $(MKDIR_P) regress/unittests/sshkey + $(MKDIR_P) regress/unittests/utf8 + test -f regress/Makefile || \ + ln -s $(abs_srcdir)/regress/Makefile regress/Makefile -REGRESSLIBS=libssh.a $(LIBCOMPAT) -TESTLIBS=$(LIBS) $(CHANNELLIBS) -regress/modpipe$(EXEEXT): $(srcdir)/regress/modpipe.c $(REGRESSLIBS) - $(CC) $(CFLAGS) $(CPPFLAGS) -o $@ $(srcdir)/regress/modpipe.c \ - $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(TESTLIBS) +REGRESSLIBS = $(LIBCOMPAT) libssh.a +TESTLIBS = $(LIBS) -regress/timestamp$(EXEEXT): $(srcdir)/regress/timestamp.c $(REGRESSLIBS) - $(CC) $(CFLAGS) $(CPPFLAGS) -o $@ $(srcdir)/regress/timestamp.c \ +regress/modpipe$(EXEEXT): regress/modpipe.o $(REGRESSLIBS) + $(LD) -o $@ regress/modpipe.o \ $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(TESTLIBS) -regress/setuid-allowed$(EXEEXT): $(srcdir)/regress/setuid-allowed.c $(REGRESSLIBS) - $(CC) $(CFLAGS) $(CPPFLAGS) -o $@ $(srcdir)/regress/setuid-allowed.c \ +regress/setuid-allowed$(EXEEXT): regress/setuid-allowed.o $(REGRESSLIBS) + $(LD) -o $@ regress/setuid-allowed.o \ $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(TESTLIBS) -regress/netcat$(EXEEXT): $(srcdir)/regress/netcat.c $(REGRESSLIBS) - $(CC) $(CFLAGS) $(CPPFLAGS) -o $@ $(srcdir)/regress/netcat.c \ +regress/netcat$(EXEEXT): regress/netcat.o $(REGRESSLIBS) + $(LD) -o $@ regress/netcat.o \ $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(TESTLIBS) -regress/check-perm$(EXEEXT): $(srcdir)/regress/check-perm.c $(REGRESSLIBS) - $(CC) $(CFLAGS) $(CPPFLAGS) -o $@ $(srcdir)/regress/check-perm.c \ +regress/check-perm$(EXEEXT): regress/check-perm.o $(REGRESSLIBS) + $(LD) -o $@ regress/check-perm.o \ $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(TESTLIBS) -regress/mkdtemp$(EXEEXT): $(srcdir)/regress/mkdtemp.c $(REGRESSLIBS) - $(CC) $(CFLAGS) $(CPPFLAGS) -o $@ $(srcdir)/regress/mkdtemp.c \ +regress/mkdtemp$(EXEEXT): regress/mkdtemp.o $(REGRESSLIBS) + $(LD) -o $@ regress/mkdtemp.o \ $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(TESTLIBS) UNITTESTS_TEST_HELPER_OBJS=\ @@ -566,8 +545,7 @@ regress/unittests/sshkey/tests.o \ regress/unittests/sshkey/common.o \ regress/unittests/sshkey/test_file.o \ - regress/unittests/sshkey/test_sshkey.o \ - $(SKOBJS) + regress/unittests/sshkey/test_sshkey.o regress/unittests/sshkey/test_sshkey$(EXEEXT): ${UNITTESTS_TEST_SSHKEY_OBJS} \ regress/unittests/test_helper/libtest_helper.a libssh.a @@ -575,17 +553,6 @@ regress/unittests/test_helper/libtest_helper.a \ -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(TESTLIBS) -UNITTESTS_TEST_SSHSIG_OBJS=\ - sshsig.o \ - regress/unittests/sshsig/tests.o \ - $(SKOBJS) - -regress/unittests/sshsig/test_sshsig$(EXEEXT): ${UNITTESTS_TEST_SSHSIG_OBJS} \ - regress/unittests/test_helper/libtest_helper.a libssh.a - $(LD) -o $@ $(LDFLAGS) $(UNITTESTS_TEST_SSHSIG_OBJS) \ - regress/unittests/test_helper/libtest_helper.a \ - -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(TESTLIBS) - UNITTESTS_TEST_BITMAP_OBJS=\ regress/unittests/bitmap/tests.o @@ -620,8 +587,7 @@ UNITTESTS_TEST_KEX_OBJS=\ regress/unittests/kex/tests.o \ regress/unittests/kex/test_kex.o \ - regress/unittests/kex/test_proposal.o \ - $(SKOBJS) + regress/unittests/kex/test_proposal.o regress/unittests/kex/test_kex$(EXEEXT): ${UNITTESTS_TEST_KEX_OBJS} \ regress/unittests/test_helper/libtest_helper.a libssh.a @@ -631,8 +597,7 @@ UNITTESTS_TEST_HOSTKEYS_OBJS=\ regress/unittests/hostkeys/tests.o \ - regress/unittests/hostkeys/test_iterate.o \ - $(SKOBJS) + regress/unittests/hostkeys/test_iterate.o regress/unittests/hostkeys/test_hostkeys$(EXEEXT): \ ${UNITTESTS_TEST_HOSTKEYS_OBJS} \ @@ -655,7 +620,6 @@ regress/unittests/misc/tests.o \ regress/unittests/misc/test_parse.o \ regress/unittests/misc/test_expand.o \ - regress/unittests/misc/test_convtime.o \ regress/unittests/misc/test_argv.o \ regress/unittests/misc/test_strdelim.o \ regress/unittests/misc/test_hpdelim.o \ @@ -678,31 +642,12 @@ regress/unittests/test_helper/libtest_helper.a \ -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(TESTLIBS) -# These all need to be compiled -fPIC, so they are treated differently. -SK_DUMMY_OBJS=\ - regress/misc/sk-dummy/sk-dummy.lo \ - regress/misc/sk-dummy/fatal.lo \ - ed25519.lo hash.lo - -SK_DUMMY_LIBRARY=@SK_DUMMY_LIBRARY@ - -.c.lo: Makefile.in config.h - $(CC) $(CFLAGS_NOPIE) $(PICFLAG) $(CPPFLAGS) -c $< -o $@ - -regress/misc/sk-dummy/sk-dummy.so: $(SK_DUMMY_OBJS) - $(CC) $(CFLAGS) $(CPPFLAGS) $(PICFLAG) -shared -o $@ $(SK_DUMMY_OBJS) \ - -L. -Lopenbsd-compat -lopenbsd-compat $(LDFLAGS_NOPIE) $(TESTLIBS) - -regress-binaries: regress-prep $(LIBCOMPAT) \ +regress-binaries: regress-prep \ regress/modpipe$(EXEEXT) \ - regress/timestamp$(EXEEXT) \ regress/setuid-allowed$(EXEEXT) \ regress/netcat$(EXEEXT) \ regress/check-perm$(EXEEXT) \ regress/mkdtemp$(EXEEXT) \ - $(SK_DUMMY_LIBRARY) - -regress-unit-binaries: regress-prep $(REGRESSLIBS) \ regress/unittests/authopt/test_authopt$(EXEEXT) \ regress/unittests/bitmap/test_bitmap$(EXEEXT) \ regress/unittests/conversion/test_conversion$(EXEEXT) \ @@ -712,61 +657,74 @@ regress/unittests/misc/test_misc$(EXEEXT) \ regress/unittests/sshbuf/test_sshbuf$(EXEEXT) \ regress/unittests/sshkey/test_sshkey$(EXEEXT) \ - regress/unittests/sshsig/test_sshsig$(EXEEXT) \ regress/unittests/utf8/test_utf8$(EXEEXT) -tests: file-tests t-exec interop-tests unit - echo all tests passed - -unit: regress-unit-binaries - cd $(srcdir)/regress || exit $$?; \ - $(MAKE) \ - .CURDIR="$(abs_top_srcdir)/regress" \ - .OBJDIR="$(BUILDDIR)/regress" \ - OBJ="$(BUILDDIR)/regress" \ - $@ && echo $@ tests passed - -interop-tests t-exec file-tests: regress-prep regress-binaries $(TARGETS) +# Target check is more common for the projects using autoXXXX tools +check: + $(MAKE) check-core + $(MAKE) check-certs + +# for compatibility +tests: check + +check-core unit file-tests t-exec f-exec interop-tests: regress-binaries $(TARGETS) + TEST_SSH_SCP="$${TEST_SSH_SCP-$(BUILDDIR)/scp}"; \ + TEST_SSH_SSH="$${TEST_SSH_SSH-$(BUILDDIR)/ssh}"; \ + TEST_SSH_SSHD="$${TEST_SSH_SSHD-$(BUILDDIR)/sshd}"; \ + TEST_SSH_SSHAGENT="$${TEST_SSH_SSHAGENT-$(BUILDDIR)/ssh-agent}"; \ + TEST_SSH_SSHADD="$${TEST_SSH_SSHADD-$(BUILDDIR)/ssh-add}"; \ + TEST_SSH_SSHKEYGEN="$${TEST_SSH_SSHKEYGEN-$(BUILDDIR)/ssh-keygen}"; \ + TEST_SSH_SSHPKCS11HELPER="$${TEST_SSH_SSHPKCS11HELPER-$(BUILDDIR)/ssh-pkcs11-helper}"; \ + TEST_SSH_SSHKEYSCAN="$${TEST_SSH_SSHKEYSCAN-$(BUILDDIR)/ssh-keyscan}"; \ + TEST_SSH_SFTP="$${TEST_SSH_SFTP-$(BUILDDIR)/sftp}"; \ + TEST_SSH_SFTPSERVER="$${TEST_SSH_SFTPSERVER-$(BUILDDIR)/sftp-server}"; \ + TEST_SSH_MODULI_FILE="$(abs_srcdir)/moduli"; \ cd $(srcdir)/regress || exit $$?; \ - EGREP='@EGREP@' \ - OPENSSL_BIN='@OPENSSL_BIN@' \ $(MAKE) \ - .CURDIR="$(abs_top_srcdir)/regress" \ + .CURDIR="$(abs_srcdir)/regress" \ .OBJDIR="$(BUILDDIR)/regress" \ BUILDDIR="$(BUILDDIR)" \ OBJ="$(BUILDDIR)/regress" \ - PATH="$(BUILDDIR):$${PATH}" \ TEST_ENV=MALLOC_OPTIONS="@TEST_MALLOC_OPTIONS@" \ TEST_MALLOC_OPTIONS="@TEST_MALLOC_OPTIONS@" \ - TEST_SSH_SCP="$(BUILDDIR)/scp" \ - TEST_SSH_SSH="$(BUILDDIR)/ssh" \ - TEST_SSH_SSHD="$(BUILDDIR)/sshd" \ - TEST_SSH_SSHAGENT="$(BUILDDIR)/ssh-agent" \ - TEST_SSH_SSHADD="$(BUILDDIR)/ssh-add" \ - TEST_SSH_SSHKEYGEN="$(BUILDDIR)/ssh-keygen" \ - TEST_SSH_SSHPKCS11HELPER="$(BUILDDIR)/ssh-pkcs11-helper" \ - TEST_SSH_SSHKEYSCAN="$(BUILDDIR)/ssh-keyscan" \ - TEST_SSH_SFTP="$(BUILDDIR)/sftp" \ - TEST_SSH_PKCS11_HELPER="$(BUILDDIR)/ssh-pkcs11-helper" \ - TEST_SSH_SK_HELPER="$(BUILDDIR)/ssh-sk-helper" \ - TEST_SSH_SFTPSERVER="$(BUILDDIR)/sftp-server" \ - TEST_SSH_MODULI_FILE="$(abs_top_srcdir)/moduli" \ - TEST_SSH_PLINK="plink" \ - TEST_SSH_PUTTYGEN="puttygen" \ - TEST_SSH_CONCH="conch" \ - TEST_SSH_IPV6="@TEST_SSH_IPV6@" \ - TEST_SSH_UTF8="@TEST_SSH_UTF8@" \ + TEST_SSH_SCP="$${TEST_SSH_SCP}" \ + TEST_SSH_SSH="$${TEST_SSH_SSH}" \ + TEST_SSH_SSHD="$${TEST_SSH_SSHD}" \ + TEST_SSH_SSHAGENT="$${TEST_SSH_SSHAGENT}" \ + TEST_SSH_SSHADD="$${TEST_SSH_SSHADD}" \ + TEST_SSH_SSHKEYGEN="$${TEST_SSH_SSHKEYGEN}" \ + TEST_SSH_SSHPKCS11HELPER="$${TEST_SSH_SSHPKCS11HELPER}" \ + TEST_SSH_SSHKEYSCAN="$${TEST_SSH_SSHKEYSCAN}" \ + TEST_SSH_SFTP="$${TEST_SSH_SFTP}" \ + TEST_SSH_SFTPSERVER="$${TEST_SSH_SFTPSERVER}" \ + TEST_SSH_MODULI_FILE="$${TEST_SSH_MODULI_FILE}" \ TEST_SHELL="$(TEST_SHELL)" \ - EXEEXT="$(EXEEXT)" \ - $@ && echo all $@ passed + $@ && echo 'regress test "$@" pass' + +CHECKCERTSENV = \ + TEST_SSH_SSH="$${TEST_SSH_SSH-$(BUILDDIR)/ssh}" \ + TEST_SSH_SSHD="$${TEST_SSH_SSHD-$(BUILDDIR)/sshd}" \ + TEST_SSH_SSHAGENT="$${TEST_SSH_SSHAGENT-$(BUILDDIR)/ssh-agent}" \ + TEST_SSH_SSHADD="$${TEST_SSH_SSHADD-$(BUILDDIR)/ssh-add}" \ + TEST_SSH_SSHKEYGEN="$${TEST_SSH_SSHKEYGEN-$(BUILDDIR)/ssh-keygen}" + +check-certs: $(TARGETS) + @if test skip = "$$SSH_X509TESTS"; then echo 'skip X.509 certificate tests'; else \ + $(CHECKCERTSENV); \ + cd tests/CA || exit $$?; \ + $(MAKE) \ + $(CHECKCERTSENV) \ + $@; \ + fi compat-tests: $(LIBCOMPAT) (cd openbsd-compat/regress && $(MAKE)) regressclean: if [ -f regress/Makefile ] && [ -r regress/Makefile ]; then \ - (cd regress && $(MAKE) clean) \ + (cd regress && $(MAKE) clean TEST_SHELL="$(TEST_SHELL)" ) \ fi + (cd tests/CA && $(MAKE) clean) survey: survey.sh ssh @$(SHELL) ./survey.sh > survey @@ -782,4 +740,8 @@ sh buildpkg.sh; \ fi -# @DEPEND@ +# Useful only if build is in source tree. +# Outside source tree (VPATH build) result is not correct. +depend: + (cd openbsd-compat && $(MAKE) $@) + makedepend -- $(CPPFLAGS) $(CFLAGS) -- $(srcdir)/*.c diff -ruN openssh-9.4p1/misc.c openssh-9.4p1+x509-14.2.1/misc.c --- openssh-9.4p1/misc.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/misc.c 2023-08-20 10:07:01.000000000 +0300 @@ -1,31 +1,36 @@ -/* $OpenBSD: misc.c,v 1.185 2023/08/04 06:32:40 dtucker Exp $ */ +/* $OpenBSD: misc.c,v 1.186 2023/08/18 01:37:41 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. - * Copyright (c) 2005-2020 Damien Miller. All rights reserved. - * Copyright (c) 2004 Henning Brauer + * Copyright (c) 2005,2006 Damien Miller. All rights reserved. + * Copyright (c) 2012-2023 Roumen Petrov. All rights reserved. * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ - #include "includes.h" #include #include -#include #include #include -#include #include #include @@ -34,17 +39,15 @@ # include #endif #ifdef HAVE_POLL_H -#include -#endif -#ifdef HAVE_NLIST_H -#include +# include +#else +# ifdef HAVE_SYS_POLL_H +# include +# endif #endif #include #include #include -#ifdef HAVE_STDINT_H -# include -#endif #include #include #include @@ -62,9 +65,9 @@ #include #ifdef HAVE_PATHS_H # include +#endif #include #include -#endif #ifdef SSH_TUN_OPENBSD #include #endif @@ -77,6 +80,28 @@ #include "ssherr.h" #include "platform.h" +/* Operations on timespecs. */ +#ifndef timespecclear +#define timespecclear(tsp) (tsp)->tv_sec = (tsp)->tv_nsec = 0 +#endif +#ifndef timespeccmp +#define timespeccmp(tsp, usp, cmp) \ + (((tsp)->tv_sec == (usp)->tv_sec) ? \ + ((tsp)->tv_nsec cmp (usp)->tv_nsec) : \ + ((tsp)->tv_sec cmp (usp)->tv_sec)) +#endif +#ifndef timespecsub +#define timespecsub(tsp, usp, vsp) \ + do { \ + (vsp)->tv_sec = (tsp)->tv_sec - (usp)->tv_sec; \ + (vsp)->tv_nsec = (tsp)->tv_nsec - (usp)->tv_nsec; \ + if ((vsp)->tv_nsec < 0) { \ + (vsp)->tv_sec--; \ + (vsp)->tv_nsec += 1000000000L; \ + } \ + } while (0) +#endif + /* remove newline at end of string */ char * chop(char *s) @@ -93,20 +118,6 @@ } -/* remove whitespace from end of string */ -void -rtrim(char *s) -{ - size_t i; - - if ((i = strlen(s)) == 0) - return; - for (i--; i > 0; i--) { - if (isspace((unsigned char)s[i])) - s[i] = '\0'; - } -} - /* set/unset filedescriptor to non-blocking */ int set_nonblock(int fd) @@ -116,20 +127,20 @@ val = fcntl(fd, F_GETFL); if (val == -1) { error("fcntl(%d, F_GETFL): %s", fd, strerror(errno)); - return (-1); + return -1; } if (val & O_NONBLOCK) { debug3("fd %d is O_NONBLOCK", fd); - return (0); + return 0; } debug2("fd %d setting O_NONBLOCK", fd); val |= O_NONBLOCK; if (fcntl(fd, F_SETFL, val) == -1) { debug("fcntl(%d, F_SETFL, O_NONBLOCK): %s", fd, strerror(errno)); - return (-1); + return -1; } - return (0); + return 1; } int @@ -140,20 +151,20 @@ val = fcntl(fd, F_GETFL); if (val == -1) { error("fcntl(%d, F_GETFL): %s", fd, strerror(errno)); - return (-1); + return -1; } if (!(val & O_NONBLOCK)) { debug3("fd %d is not O_NONBLOCK", fd); - return (0); + return 0; } debug("fd %d clearing O_NONBLOCK", fd); val &= ~O_NONBLOCK; if (fcntl(fd, F_SETFL, val) == -1) { debug("fcntl(%d, F_SETFL, ~O_NONBLOCK): %s", fd, strerror(errno)); - return (-1); + return -1; } - return (0); + return 1; } const char * @@ -218,6 +229,7 @@ xasprintf(&ret, "%d", rtable); return ret; #else /* defined(__OpenBSD__) */ + UNUSED(fd); return NULL; #endif } @@ -248,6 +260,8 @@ } return 0; #else /* defined(__OpenBSD__) */ + UNUSED(fd); + UNUSED(name); error("Setting routing domain is not supported on this platform"); return -1; #endif @@ -261,7 +275,7 @@ memset(&to, 0, sizeof(to)); if (getsockname(fd, (struct sockaddr *)&to, &tolen) == -1) - return -1; + return AF_UNSPEC; #ifdef IPV4_IN_IPV6 if (to.ss_family == AF_INET6 && IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)&to)->sin6_addr)) @@ -274,30 +288,28 @@ set_sock_tos(int fd, int tos) { #ifndef IP_TOS_IS_BROKEN - int af; + int af = get_sock_af(fd); - switch ((af = get_sock_af(fd))) { - case -1: + switch (af) { + case AF_UNSPEC: /* assume not a socket */ break; case AF_INET: # ifdef IP_TOS debug3_f("set socket %d IP_TOS 0x%02x", fd, tos); if (setsockopt(fd, IPPROTO_IP, IP_TOS, - &tos, sizeof(tos)) == -1) { + &tos, sizeof(tos)) == -1) error("setsockopt socket %d IP_TOS %d: %s", fd, tos, strerror(errno)); - } # endif /* IP_TOS */ break; case AF_INET6: # ifdef IPV6_TCLASS debug3_f("set socket %d IPV6_TCLASS 0x%02x", fd, tos); if (setsockopt(fd, IPPROTO_IPV6, IPV6_TCLASS, - &tos, sizeof(tos)) == -1) { + &tos, sizeof(tos)) == -1) error("setsockopt socket %d IPV6_TCLASS %d: %s", fd, tos, strerror(errno)); - } # endif /* IPV6_TCLASS */ break; default: @@ -313,20 +325,39 @@ * Returns 0 if fd ready or -1 on timeout or error (see errno). */ static int -waitfd(int fd, int *timeoutp, short events) +waitfd(int fd, int *timeoutp, short events, volatile sig_atomic_t *stop) { struct pollfd pfd; - struct timeval t_start; - int oerrno, r, have_timeout = (*timeoutp >= 0); + struct timespec timeout; + int oerrno, r; + sigset_t nsigset; + if (timeoutp && *timeoutp == -1) + timeoutp = NULL; pfd.fd = fd; pfd.events = events; - for (; !have_timeout || *timeoutp >= 0;) { - monotime_tv(&t_start); - r = poll(&pfd, 1, *timeoutp); + ptimeout_init(&timeout); + if (timeoutp != NULL) + ptimeout_deadline_ms(&timeout, *timeoutp); + if (stop != NULL) + sigfillset(&nsigset); + for (; timeoutp == NULL || *timeoutp >= 0;) { + sigset_t osigset, *psigset = NULL; + if (stop != NULL) { + sigprocmask(SIG_BLOCK, &nsigset, &osigset); + if (*stop) { + sigprocmask(SIG_SETMASK, &osigset, NULL); + errno = EINTR; + return -1; + } + psigset = &osigset; + } + r = ppoll(&pfd, 1, ptimeout_get_tsp(&timeout), psigset); oerrno = errno; - if (have_timeout) - ms_subtract_diff(&t_start, timeoutp); + if (stop != NULL) + sigprocmask(SIG_SETMASK, &osigset, NULL); + if (timeoutp) + *timeoutp = ptimeout_get_ms(&timeout); errno = oerrno; if (r > 0) return 0; @@ -346,8 +377,8 @@ * Returns 0 if fd ready or -1 on timeout or error (see errno). */ int -waitrfd(int fd, int *timeoutp) { - return waitfd(fd, timeoutp, POLLIN); +waitrfd(int fd, int *timeoutp, volatile sig_atomic_t *stop) { + return waitfd(fd, timeoutp, POLLIN, stop); } /* @@ -369,8 +400,8 @@ return connect(sockfd, serv_addr, addrlen); set_nonblock(sockfd); - for (;;) { - if (connect(sockfd, serv_addr, addrlen) == 0) { + while (1) { + if (connect(sockfd, serv_addr, addrlen) != -1) { /* Succeeded already? */ unset_nonblock(sockfd); return 0; @@ -381,7 +412,7 @@ break; } - if (waitfd(sockfd, timeoutp, POLLIN | POLLOUT) == -1) + if (waitfd(sockfd, timeoutp, POLLIN | POLLOUT, NULL) == -1) return -1; /* Completed or failed */ @@ -405,7 +436,7 @@ static char * strdelim_internal(char **s, int split_equals) { - char *old; + char *old, *cp; int wspace = 0; if (*s == NULL) @@ -420,13 +451,25 @@ if (*s[0] == '\"') { memmove(*s, *s + 1, strlen(*s)); /* move nul too */ + /* Find matching quote */ - if ((*s = strpbrk(*s, QUOTE)) == NULL) { - return (NULL); /* no matching quote */ - } else { - *s[0] = '\0'; - *s += strspn(*s + 1, WHITESPACE) + 1; - return (old); + for (cp = *s; ; cp++) { + if (*cp == '\0') + return NULL; /* no matching quote */ + if (*cp == '\\') { + /* Escape sequence */ + if (cp[1] == '\"' || cp[1] == '\'' || + cp[1] == '\\') { + memmove(cp, cp + 1, strlen(cp)); + continue; + } + return NULL; /* invalid escape */ + } else if (*cp == '\"') { + *(cp++) = '\0'; + *s = cp; + *s += strspn(cp, WHITESPACE); + return old; + } } } @@ -463,12 +506,19 @@ } struct passwd * -pwcopy(struct passwd *pw) +pwcopy(const struct passwd *pw) { struct passwd *copy = xcalloc(1, sizeof(*copy)); copy->pw_name = xstrdup(pw->pw_name); - copy->pw_passwd = xstrdup(pw->pw_passwd == NULL ? "*" : pw->pw_passwd); +#if defined(__ANDROID__) + /* FIXME: password is NULL on Android */ + copy->pw_passwd = xstrdup(pw->pw_passwd ? pw->pw_passwd : + /* fake password from auth.c */ + "$2a$06$r3.juUaHZDlIbQaO2dS9FuYxL1W9M81R1Tc92PoSNmzvpEqLkLGrK"); +#else + copy->pw_passwd = xstrdup(pw->pw_passwd); +#endif #ifdef HAVE_STRUCT_PASSWD_PW_GECOS copy->pw_gecos = xstrdup(pw->pw_gecos); #endif @@ -566,7 +616,7 @@ * * Return -1 if time string is invalid. */ -int +long convtime(const char *s) { long total, secs, multiplier; @@ -583,7 +633,7 @@ while (*p) { secs = strtol(p, &endp, 10); if (p == endp || - (errno == ERANGE && (secs == INT_MIN || secs == INT_MAX)) || + (errno == ERANGE && (secs == LONG_MIN || secs == LONG_MAX)) || secs < 0) return -1; @@ -614,10 +664,10 @@ default: return -1; } - if (secs > INT_MAX / multiplier) + if (secs >= LONG_MAX / multiplier) return -1; secs *= multiplier; - if (total > INT_MAX - secs) + if (total >= LONG_MAX - secs) return -1; total += secs; if (total < 0) @@ -628,41 +678,40 @@ return total; } -#define TF_BUFS 8 -#define TF_LEN 9 - -const char * -fmt_timeframe(time_t t) +char * +fmttime(time_t t) { - char *buf; - static char tfbuf[TF_BUFS][TF_LEN]; /* ring buffer */ - static int idx = 0; - unsigned int sec, min, hrs, day; - unsigned long long week; - - buf = tfbuf[idx++]; - if (idx == TF_BUFS) - idx = 0; - - week = t; - - sec = week % 60; - week /= 60; - min = week % 60; - week /= 60; - hrs = week % 24; - week /= 24; - day = week % 7; - week /= 7; - - if (week > 0) - snprintf(buf, TF_LEN, "%02lluw%01ud%02uh", week, day, hrs); - else if (day > 0) - snprintf(buf, TF_LEN, "%01ud%02uh%02um", day, hrs, min); + u_int s, m, h, d; + + /*seconds*/ + s = t % 60; + t /= 60; + /*minutes*/ + m = t % 60; + t /= 60; + /*hours*/ + h = t % 24; + t /= 24; + /*days*/ + d = t % 7; + t /= 7; + /*weeks*/ + +{ char *ret; + + if (t > 0) + xasprintf(&ret, "%dw%dd%dh", (u_int)t, d, h); + else if (d > 0) + xasprintf(&ret, "%dd%dh%dm", d, h, m); + else if (h > 0) + xasprintf(&ret, "%dh%dm%ds", h, m, s); + else if (m > 0) + xasprintf(&ret, "%dm%ds", m, s); else - snprintf(buf, TF_LEN, "%02u:%02u:%02u", hrs, min, sec); + xasprintf(&ret, "%ds", s); - return (buf); + return ret; +} } /* @@ -676,9 +725,9 @@ if (port == 0 || port == SSH_DEFAULT_PORT) return(xstrdup(host)); - if (asprintf(&hoststr, "[%s]:%d", host, (int)port) == -1) - fatal("put_host_port: asprintf: %s", strerror(errno)); - debug3("put_host_port: %s", hoststr); + if (asprintf(&hoststr, "[%s]:%d", host, (int)port) < 0) + fatal_f("asprintf: %s", strerror(errno)); + debug3_f("%s", hoststr); return hoststr; } @@ -875,7 +924,7 @@ tmp = cp + 1; } /* Extract mandatory hostname */ - if ((cp = hpdelim(&tmp)) == NULL || *cp == '\0') + if ((cp = hpdelim2(&tmp, NULL)) == NULL || *cp == '\0') goto out; host = xstrdup(cleanhostname(cp)); /* Convert and verify optional port */ @@ -934,16 +983,19 @@ { char *ret, *dst; int ch; - size_t srclen; - if ((srclen = strlen(src)) >= SIZE_MAX) +{ size_t srclen = strlen(src); + if (srclen >= SIZE_MAX) fatal_f("input too large"); ret = xmalloc(srclen + 1); +} for (dst = ret; *src != '\0'; src++) { switch (*src) { +#if 0 /* NOTE: '+' is not delimiter in ssh uri! */ case '+': *dst++ = ' '; break; +#endif case '%': if (!isxdigit((unsigned char)src[1]) || !isxdigit((unsigned char)src[2]) || @@ -980,7 +1032,7 @@ parse_uri(const char *scheme, const char *uri, char **userp, char **hostp, int *portp, char **pathp) { - char *uridup, *cp, *tmp, ch; + char *uridup, *cp, *tmp; char *user = NULL, *host = NULL, *path = NULL; int port = -1, ret = -1; size_t len; @@ -1020,15 +1072,16 @@ tmp = cp + 1; } +{ char delim = '\0'; /* Extract mandatory hostname */ - if ((cp = hpdelim2(&tmp, &ch)) == NULL || *cp == '\0') + if ((cp = hpdelim2(&tmp, &delim)) == NULL || *cp == '\0') goto out; host = xstrdup(cleanhostname(cp)); if (!valid_domain(host, 0, NULL)) goto out; if (tmp != NULL && *tmp != '\0') { - if (ch == ':') { + if (delim == ':') { /* Convert and verify port. */ if ((cp = strchr(tmp, '/')) != NULL) *cp = '\0'; @@ -1042,6 +1095,7 @@ goto out; } } +} /* Success */ if (userp != NULL) { @@ -1079,18 +1133,17 @@ va_start(ap, fmt); r = vasprintf(&cp, fmt, ap); va_end(ap); - if (r == -1) + if (r < 0) fatal_f("argument too long"); nalloc = args->nalloc; if (args->list == NULL) { nalloc = 32; args->num = 0; - } else if (args->num > (256 * 1024)) + } + else if (args->num > (256 * 1024)) fatal_f("too many arguments"); - else if (args->num >= args->nalloc) - fatal_f("arglist corrupt"); - else if (args->num+2 >= nalloc) + else if (args->num + 2 >= nalloc) nalloc *= 2; args->list = xrecallocarray(args->list, args->nalloc, @@ -1110,13 +1163,11 @@ va_start(ap, fmt); r = vasprintf(&cp, fmt, ap); va_end(ap); - if (r == -1) + if (r < 0) fatal_f("argument too long"); - if (args->list == NULL || args->num >= args->nalloc) - fatal_f("arglist corrupt"); if (which >= args->num) - fatal_f("tried to replace invalid arg %d >= %d", + fatal_f("tried to replace invalid arg %u >= %u", which, args->num); free(args->list[which]); args->list[which] = cp; @@ -1125,17 +1176,16 @@ void freeargs(arglist *args) { - u_int i; - if (args == NULL) return; - if (args->list != NULL && args->num < args->nalloc) { + if (args->list != NULL) { + u_int i; for (i = 0; i < args->num; i++) free(args->list[i]); free(args->list); + args->list = NULL; } args->nalloc = args->num = 0; - args->list = NULL; } /* @@ -1145,11 +1195,9 @@ int tilde_expand(const char *filename, uid_t uid, char **retp) { - char *ocopy = NULL, *copy, *s = NULL; - const char *path = NULL, *user = NULL; + char *ocopy = NULL, *copy, *path, *user, *s = NULL; struct passwd *pw; - size_t len; - int ret = -1, r, slash; + int ret = -1, slash; *retp = NULL; if (*filename != '~') { @@ -1158,6 +1206,7 @@ } ocopy = copy = xstrdup(filename + 1); + user = NULL; if (*copy == '\0') /* ~ */ path = NULL; else if (*copy == '/') { @@ -1168,9 +1217,9 @@ path = copy; /* ~/path */ } else { user = copy; - if ((path = strchr(copy, '/')) != NULL) { - copy[path - copy] = '\0'; - path++; + path = strchr(copy, '/'); + if (path != NULL) { + *path++ = '\0'; path += strspn(path, "/"); if (*path == '\0') /* ~user/ */ path = NULL; @@ -1180,24 +1229,22 @@ } if (user != NULL) { if ((pw = getpwnam(user)) == NULL) { - error_f("No such user %s", user); + error_f("no such user %s", user); goto out; } } else if ((pw = getpwuid(uid)) == NULL) { - error_f("No such uid %ld", (long)uid); + error_f("no such uid %ld", (long)uid); goto out; } - /* Make sure directory has a trailing '/' */ - slash = (len = strlen(pw->pw_dir)) == 0 || pw->pw_dir[len - 1] != '/'; +{ /* Make sure directory has a trailing '/' */ + size_t len = strlen(pw->pw_dir); + slash = len == 0 || pw->pw_dir[len - 1] != '/'; +} - if ((r = xasprintf(&s, "%s%s%s", pw->pw_dir, - slash ? "/" : "", path != NULL ? path : "")) <= 0) { - error_f("xasprintf failed"); - goto out; - } - if (r >= PATH_MAX) { - error_f("Path too long"); + if (xasprintf(&s, "%s%s%s", pw->pw_dir, slash ? "/" : "", + path != NULL ? path : "") >= PATH_MAX) { + error_f("path too long"); goto out; } /* success */ @@ -1215,7 +1262,7 @@ { char *ret; - if (tilde_expand(filename, uid, &ret) != 0) + if (tilde_expand(filename, uid, &ret) == -1) cleanup_exit(255); return ret; } @@ -1255,10 +1302,9 @@ if (keys[num_keys].key == NULL) break; keys[num_keys].repl = va_arg(ap, char *); - if (keys[num_keys].repl == NULL) { + if (keys[num_keys].repl == NULL) fatal_f("NULL replacement for token %s", keys[num_keys].key); - } } if (num_keys == EXPAND_MAX_KEYS && va_arg(ap, char *) != NULL) fatal_f("too many keys"); @@ -1421,7 +1467,7 @@ for (tun = 100; tun >= 0; tun--) { snprintf(name, sizeof(name), "/dev/%s%d", tunbase, tun); - if ((fd = open(name, O_RDWR)) >= 0) + if ((fd = open(name, O_RDWR)) != -1) break; } } else { @@ -1469,6 +1515,9 @@ close(sock); return -1; #else + UNUSED(tun); + UNUSED(mode); + UNUSED(ifname); error("Tunnel interfaces are not supported on this platform"); return (-1); #endif @@ -1658,15 +1707,6 @@ } void -ms_to_timespec(struct timespec *ts, int ms) -{ - if (ms < 0) - ms = 0; - ts->tv_sec = ms / 1000; - ts->tv_nsec = (ms % 1000) * 1000 * 1000; -} - -void monotime_ts(struct timespec *ts) { struct timeval tv; @@ -1788,6 +1828,26 @@ monotime_tv(&bw->bwstart); } +/* Make a template path for mk[sd]temp() taking into account + * environment variable TMPDIR. + * Template uses 10 "X"-es although POSIX requires six. + */ +char* +mkdtemp_template(char *prefix) { + const char *tmpdir; + char template[PATH_MAX]; + int r; + + tmpdir = getenv("TMPDIR"); + if (tmpdir == NULL) tmpdir = "/tmp"; + + r = snprintf(template, sizeof(template), "%s/%sXXXXXXXXXX", + tmpdir, prefix); + return (r < 0 || (size_t)r >= sizeof(template)) + ? NULL + : xstrdup(template); +} + /* Make a template filename for mk[sd]temp() */ void mktemp_proto(char *s, size_t len) @@ -1796,11 +1856,11 @@ int r; if ((tmpdir = getenv("TMPDIR")) != NULL) { - r = snprintf(s, len, "%s/ssh-XXXXXXXXXXXX", tmpdir); + r = snprintf(s, len, "%s/ssh-XXXXXXXXXX", tmpdir); if (r > 0 && (size_t)r < len) return; } - r = snprintf(s, len, "/tmp/ssh-XXXXXXXXXXXX"); + r = snprintf(s, len, "/tmp/ssh-XXXXXXXXXX"); if (r < 0 || (size_t)r >= len) fatal_f("template string too short"); } @@ -1903,7 +1963,7 @@ } if (unlink_first == 1) { if (unlink(path) != 0 && errno != ENOENT) - error("unlink(%s): %.100s", path, strerror(errno)); + error_f("unlink(%s): %.100s", path, strerror(errno)); } if (bind(sock, (struct sockaddr *)&sunaddr, sizeof(sunaddr)) == -1) { saved_errno = errno; @@ -1929,7 +1989,7 @@ #if defined(IPV6_V6ONLY) && !defined(__OpenBSD__) int on = 1; - debug3("%s: set socket %d IPV6_V6ONLY", __func__, s); + debug3_f("set socket %d IPV6_V6ONLY", s); if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)) == -1) error("setsockopt IPV6_V6ONLY: %s", strerror(errno)); #endif @@ -1972,13 +2032,28 @@ return 1; } +#ifdef __ANDROID__ +/* NOTE getsid syscall wrapper is not included in + * some versions of bionic C-library! + */ +#include + +static inline pid_t +android_getsid(pid_t pid) { + return syscall(__NR_getsid, pid); +} + +# define getsid android_getsid + +#endif /*def __ANDROID__*/ + /* returns 1 if process is already daemonized, 0 otherwise */ int daemonized(void) { int fd; - if ((fd = open(_PATH_TTY, O_RDONLY | O_NOCTTY)) >= 0) { + if ((fd = open(_PATH_TTY, O_RDONLY | O_NOCTTY)) != -1) { close(fd); return 0; /* have controlling terminal */ } @@ -2002,6 +2077,7 @@ int argc = 0, quote, i, j; char *arg, **argv = xcalloc(1, sizeof(*argv)); + UNUSED(terminate_on_comment); *argvp = NULL; *argcp = 0; @@ -2009,8 +2085,7 @@ /* Skip leading whitespace */ if (s[i] == ' ' || s[i] == '\t') continue; - if (terminate_on_comment && s[i] == '#') - break; + /* Start of a token */ quote = 0; @@ -2121,12 +2196,15 @@ char * argv_next(int *argcp, char ***argvp) { - char *ret = (*argvp)[0]; + char *ret; - if (*argcp > 0 && ret != NULL) { - (*argcp)--; - (*argvp)++; - } + if (*argcp <= 0) return NULL; + + ret = (*argvp)[0]; + if (ret == NULL) return NULL; + + (*argcp)--; + (*argvp)++; return ret; } @@ -2172,6 +2250,94 @@ } /* + * Conversion of signals from RFC 4254 section 6.10C, with SIGINFO as + * local extension. + */ +int +ssh_signame2code(char *name) +{ +#define SSH_SIG(x) if (strcmp(name, #x) == 0) return SIG ## x + SSH_SIG(ABRT); + SSH_SIG(ALRM); + SSH_SIG(FPE); + SSH_SIG(HUP); + SSH_SIG(ILL); + SSH_SIG(INT); + SSH_SIG(KILL); + SSH_SIG(PIPE); + SSH_SIG(QUIT); + SSH_SIG(SEGV); + SSH_SIG(TERM); + SSH_SIG(USR1); + SSH_SIG(USR2); +#undef SSH_SIG +#ifdef SIGINFO + if (strcmp(name, "INFO@openssh.com") == 0) + return SIGINFO; +#endif + return -1; +} + +int +xrename(const char *oldpath, const char *newpath) { + if (link(oldpath, newpath) == -1) { + if (errno == EOPNOTSUPP || errno == ENOSYS +#ifdef EXDEV + || errno == EXDEV +#endif +#ifdef LINK_OPNOTSUPP_ERRNO + || errno == LINK_OPNOTSUPP_ERRNO +#endif + ) { + struct stat st; + /* + * If file-system does not support links or + * hard links are disabled or etc. + * So fall back to stat+rename (race). + */ + if (stat(newpath, &st) == -1) + return rename(oldpath, newpath); + + /* simplified error reason */ + errno = EEXIST; + } + return -1; + } + if (unlink(oldpath) == -1) { + int oerrno = errno; + /* clean spare link */ + (void)unlink(newpath); + errno = oerrno; + return -1; + } + return 0; +} + +static inline int +check_mode(struct stat *st, uid_t uid, int is_dir, const char *name, + char *err, size_t errlen +) { + const char *type = is_dir ? "directory" : "file"; + + if (!platform_sys_dir_uid(st->st_uid) && st->st_uid != uid) { + snprintf(err, errlen, "bad ownership for %s %s", type, name); + return -1; + } + +{ int mask = 022; +#ifdef __ANDROID__ + /* application is installed uid == gid */ + if (is_dir) mask = 002; +#endif + if ((st->st_mode & mask) != 0) { + snprintf(err, errlen, "bad modes for %s %s", type, name); + return -1; + } +} + return 0; +} + +/* * Check a given path for security. This is defined as all components * of the path to the file must be owned by either the owner of * of the file or root and no directories must be group or world writable. @@ -2205,12 +2371,8 @@ snprintf(err, errlen, "%s is not a regular file", buf); return -1; } - if ((!platform_sys_dir_uid(stp->st_uid) && stp->st_uid != uid) || - (stp->st_mode & 022) != 0) { - snprintf(err, errlen, "bad ownership or modes for file %s", - buf); + if (check_mode(stp, uid, 0, buf, err, errlen) == -1) return -1; - } /* for each component of the canonical path, walking upwards */ for (;;) { @@ -2221,12 +2383,8 @@ strlcpy(buf, cp, sizeof(buf)); if (stat(buf, &st) == -1 || - (!platform_sys_dir_uid(st.st_uid) && st.st_uid != uid) || - (st.st_mode & 022) != 0) { - snprintf(err, errlen, - "bad ownership or modes for directory %s", buf); + check_mode(&st, uid, 1, buf, err, errlen) == -1) return -1; - } /* If are past the homedir then we can stop */ if (comparehome && strcmp(homedir, buf) == 0) @@ -2264,6 +2422,21 @@ } /* + * Returns 0 on success and -1 on failure + */ +int +safe_usr_fileno(int fd, const char *filename, char *err, size_t errlen) { + struct stat st; + + if (fstat(fd, &st) == -1) { + snprintf(err, errlen, "cannot stat file %s: %s", + filename, strerror(errno)); + return -1; + } + return check_mode(&st, getuid(), 0, filename, err, errlen); +} + +/* * Sets the value of the given variable in the environment. If the variable * already exists, its value is overridden. */ @@ -2284,9 +2457,9 @@ * If we're passed an uninitialized list, allocate a single null * entry before continuing. */ - if ((*envp == NULL) != (*envsizep == 0)) - fatal_f("environment size mismatch"); - if (*envp == NULL && *envsizep == 0) { + if (*envp == NULL) { + if (*envsizep != 0) + fatal_f("environment size mismatch"); *envp = xmalloc(sizeof(char *)); *envp[0] = NULL; *envsizep = 1; @@ -2310,7 +2483,7 @@ envsize = *envsizep; if (i >= envsize - 1) { if (envsize >= 1000) - fatal("child_set_env: too many env vars"); + fatal_f("too many env vars"); envsize += 50; env = (*envp) = xreallocarray(env, envsize, sizeof(char *)); *envsizep = envsize; @@ -2592,13 +2765,14 @@ sshsig_t ssh_signal(int signum, sshsig_t handler) { +#ifdef HAVE_SIGACTION struct sigaction sa, osa; /* mask all other signals while in handler */ memset(&sa, 0, sizeof(sa)); sa.sa_handler = handler; sigfillset(&sa.sa_mask); -#if defined(SA_RESTART) && !defined(NO_SA_RESTART) +#if defined(SA_RESTART) && !defined(BROKEN_SA_RESTART) if (signum != SIGALRM) sa.sa_flags = SA_RESTART; #endif @@ -2607,6 +2781,9 @@ return SIG_ERR; } return osa.sa_handler; +#else + return (signal(sig, handler)); +#endif } int @@ -2614,6 +2791,9 @@ { int devnull, ret = 0; + if (!do_stdin && !do_stdout && !do_stderr) + return 0; + if ((devnull = open(_PATH_DEVNULL, O_RDWR)) == -1) { error_f("open %s: %s", _PATH_DEVNULL, strerror(errno)); @@ -2625,7 +2805,7 @@ error_f("dup2: %s", strerror(errno)); ret = -1; } - if (devnull > STDERR_FILENO) + if (devnull > (do_stderr ? STDOUT_FILENO : STDERR_FILENO)) close(devnull); return ret; } @@ -2649,9 +2829,9 @@ int fd, devnull, p[2], i; pid_t pid; char *cp, errmsg[512]; - u_int nenv = 0; char **env = NULL; + UNUSED(ac); /* If dropping privs, then must specify user and restore function */ if (drop_privs != NULL && (pw == NULL || restore_privs == NULL)) { error("%s: inconsistent arguments", tag); /* XXX fatal? */ @@ -2718,7 +2898,7 @@ case 0: /* child */ /* Prepare a minimal environment for the child. */ if ((flags & SSH_SUBPROCESS_PRESERVE_ENV) == 0) { - nenv = 5; + u_int nenv = 6; env = xcalloc(sizeof(*env), nenv); child_set_env(&env, &nenv, "PATH", _PATH_STDPATH); child_set_env(&env, &nenv, "USER", pw->pw_name); @@ -2753,6 +2933,7 @@ } closefrom(STDERR_FILENO + 1); + /* Don't use permanently_set_uid() here to avoid fatal() */ if (geteuid() == 0 && initgroups(pw->pw_name, pw->pw_gid) == -1) { error("%s: initgroups(%s, %u): %s", tag, @@ -2868,8 +3049,10 @@ static void ptimeout_deadline_tsp(struct timespec *pt, struct timespec *p) { - if (pt->tv_sec == -1 || timespeccmp(pt, p, >=)) - *pt = *p; + if (pt->tv_sec == -1 || timespeccmp(pt, p, >=)) { + pt->tv_sec = p->tv_sec; + pt->tv_nsec = p->tv_nsec; + } } /* Specify a poll/ppoll deadline of at most 'ms' milliseconds */ @@ -2925,75 +3108,3 @@ { return pt->tv_sec != -1; } - -/* - * Returns zero if the library at 'path' contains symbol 's', nonzero - * otherwise. - */ -int -lib_contains_symbol(const char *path, const char *s) -{ -#ifdef HAVE_NLIST_H - struct nlist nl[2]; - int ret = -1, r; - - memset(nl, 0, sizeof(nl)); - nl[0].n_name = xstrdup(s); - nl[1].n_name = NULL; - if ((r = nlist(path, nl)) == -1) { - error_f("nlist failed for %s", path); - goto out; - } - if (r != 0 || nl[0].n_value == 0 || nl[0].n_type == 0) { - error_f("library %s does not contain symbol %s", path, s); - goto out; - } - /* success */ - ret = 0; - out: - free(nl[0].n_name); - return ret; -#else /* HAVE_NLIST_H */ - int fd, ret = -1; - struct stat st; - void *m = NULL; - size_t sz = 0; - - memset(&st, 0, sizeof(st)); - if ((fd = open(path, O_RDONLY)) < 0) { - error_f("open %s: %s", path, strerror(errno)); - return -1; - } - if (fstat(fd, &st) != 0) { - error_f("fstat %s: %s", path, strerror(errno)); - goto out; - } - if (!S_ISREG(st.st_mode)) { - error_f("%s is not a regular file", path); - goto out; - } - if (st.st_size < 0 || - (size_t)st.st_size < strlen(s) || - st.st_size >= INT_MAX/2) { - error_f("%s bad size %lld", path, (long long)st.st_size); - goto out; - } - sz = (size_t)st.st_size; - if ((m = mmap(NULL, sz, PROT_READ, MAP_PRIVATE, fd, 0)) == MAP_FAILED || - m == NULL) { - error_f("mmap %s: %s", path, strerror(errno)); - goto out; - } - if (memmem(m, sz, s, strlen(s)) == NULL) { - error_f("%s does not contain expected string %s", path, s); - goto out; - } - /* success */ - ret = 0; - out: - if (m != NULL && m != MAP_FAILED) - munmap(m, sz); - close(fd); - return ret; -#endif /* HAVE_NLIST_H */ -} diff -ruN openssh-9.4p1/misc.h openssh-9.4p1+x509-14.2.1/misc.h --- openssh-9.4p1/misc.h 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/misc.h 2023-08-20 10:07:00.000000000 +0300 @@ -1,5 +1,4 @@ -/* $OpenBSD: misc.h,v 1.103 2023/07/19 14:02:27 djm Exp $ */ - +/* $OpenBSD: misc.h,v 1.104 2023/08/18 01:37:41 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -15,10 +14,14 @@ #ifndef _MISC_H #define _MISC_H -#include +#include "includes.h" +#ifdef HAVE_SYS_TIME_H +# include +#endif #include #include #include +#include /* Data structure for representing a forwarding request. */ struct Forward { @@ -45,7 +48,6 @@ /* misc.c */ char *chop(char *); -void rtrim(char *); void skip_space(char **); char *strdelim(char **); char *strdelimw(char **); @@ -57,7 +59,7 @@ int set_rdomain(int, const char *); int get_sock_af(int); void set_sock_tos(int, int); -int waitrfd(int, int *); +int waitrfd(int, int *, volatile sig_atomic_t *); int timeout_connect(int, const struct sockaddr *, socklen_t, int *); int a2port(const char *); int a2tun(const char *, int *); @@ -69,8 +71,8 @@ int parse_user_host_path(const char *, char **, char **, char **); int parse_user_host_port(const char *, char **, char **, int *); int parse_uri(const char *, const char *, char **, char **, int *, char **); -int convtime(const char *); -const char *fmt_timeframe(time_t t); +long convtime(const char *); +char *fmttime(time_t t); int tilde_expand(const char *, uid_t, char **); char *tilde_expand_filename(const char *, uid_t); @@ -82,7 +84,6 @@ __attribute__((__format__ (printf, 3, 4))) __attribute__((__nonnull__ (3))); void sanitise_stdfd(void); void ms_subtract_diff(struct timeval *, int *); -void ms_to_timespec(struct timespec *, int); void monotime_ts(struct timespec *); void monotime_tv(struct timeval *); time_t monotime(void); @@ -96,11 +97,10 @@ void format_absolute_time(uint64_t, char *, size_t); int path_absolute(const char *); int stdfd_devnull(int, int, int); -int lib_contains_symbol(const char *, const char *); void sock_set_v6only(int); -struct passwd *pwcopy(struct passwd *); +struct passwd *pwcopy(const struct passwd *); const char *ssh_gai_strerror(int); typedef void privdrop_fn(struct passwd *); @@ -110,8 +110,9 @@ #define SSH_SUBPROCESS_STDERR_DISCARD (1<<2) /* Discard stderr */ #define SSH_SUBPROCESS_UNSAFE_PATH (1<<3) /* Don't check for safe cmd */ #define SSH_SUBPROCESS_PRESERVE_ENV (1<<4) /* Keep parent environment */ -pid_t subprocess(const char *, const char *, int, char **, FILE **, u_int, - struct passwd *, privdrop_fn *, privrestore_fn *); +pid_t subprocess(const char *tag, const char *command, + int ac, char **av, FILE **child, u_int flags, + struct passwd *pw, privdrop_fn *drop_privs, privrestore_fn *restore_privs); typedef struct arglist arglist; struct arglist { @@ -174,6 +175,7 @@ int parse_ipqos(const char *); const char *iptos2str(int); +char *mkdtemp_template(char *prefix); void mktemp_proto(char *, size_t); void child_set_env(char ***envp, u_int *envsizep, const char *name, @@ -190,12 +192,18 @@ void argv_free(char **, int); int exited_cleanly(pid_t, const char *, const char *, int); +int ssh_signame2code(char *name); + +/* atomic rename of regular files */ +int xrename(const char *oldpath, const char *newpath); struct stat; int safe_path(const char *, struct stat *, const char *, uid_t, char *, size_t); int safe_path_fd(int, const char *, struct passwd *, char *err, size_t errlen); +int safe_usr_fileno(int fd, const char *filename, + char *err, size_t errlen); /* authorized_key-style options parsing helpers */ int opt_flag(const char *opt, int allow_negate, const char **optsp); @@ -225,23 +233,10 @@ #define RP_ALLOW_EOF 0x0004 #define RP_USE_ASKPASS 0x0008 -struct notifier_ctx; - char *read_passphrase(const char *, int); int ask_permission(const char *, ...) __attribute__((format(printf, 1, 2))); -struct notifier_ctx *notify_start(int, const char *, ...) - __attribute__((format(printf, 2, 3))); -void notify_complete(struct notifier_ctx *, const char *, ...) - __attribute__((format(printf, 2, 3))); - -#define MINIMUM(a, b) (((a) < (b)) ? (a) : (b)) -#define MAXIMUM(a, b) (((a) > (b)) ? (a) : (b)) -#define ROUNDUP(x, y) ((((x)+((y)-1))/(y))*(y)) typedef void (*sshsig_t)(int); sshsig_t ssh_signal(int, sshsig_t); -/* On OpenBSD time_t is int64_t which is long long. */ -/* #define SSH_TIME_T_MAX LLONG_MAX */ - #endif /* _MISC_H */ diff -ruN openssh-9.4p1/mkinstalldirs openssh-9.4p1+x509-14.2.1/mkinstalldirs --- openssh-9.4p1/mkinstalldirs 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/mkinstalldirs 1970-01-01 02:00:00.000000000 +0200 @@ -1,38 +0,0 @@ -#! /bin/sh -# mkinstalldirs --- make directory hierarchy -# Author: Noah Friedman -# Created: 1993-05-16 -# Public domain - -errstatus=0 - -for file -do - set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'` - shift - - pathcomp= - for d - do - pathcomp="$pathcomp$d" - case "$pathcomp" in - -* ) pathcomp=./$pathcomp ;; - esac - - if test ! -d "$pathcomp"; then - echo "mkdir $pathcomp" - - mkdir "$pathcomp" || lasterr=$? - - if test ! -d "$pathcomp"; then - errstatus=$lasterr - fi - fi - - pathcomp="$pathcomp/" - done -done - -exit $errstatus - -# mkinstalldirs ends here diff -ruN openssh-9.4p1/moduli.0 openssh-9.4p1+x509-14.2.1/moduli.0 --- openssh-9.4p1/moduli.0 2023-08-10 04:11:18.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/moduli.0 2023-08-20 10:07:00.000000000 +0300 @@ -1,25 +1,25 @@ -MODULI(5) File Formats Manual MODULI(5) +MODULI(5) BSD File Formats Manual MODULI(5) NAME - moduli M-bM-^@M-^S Diffie-Hellman moduli + moduli -- Diffie-Hellman moduli DESCRIPTION The /etc/moduli file contains prime numbers and generators for use by sshd(8) in the Diffie-Hellman Group Exchange key exchange method. New moduli may be generated with ssh-keygen(1) using a two-step process. - An initial candidate generation pass, using ssh-keygen -M generate, - calculates numbers that are likely to be useful. A second primality - testing pass, using ssh-keygen -M screen, provides a high degree of - assurance that the numbers are prime and are safe for use in Diffie- - Hellman operations by sshd(8). This moduli format is used as the output - from each pass. + An initial candidate generation pass, using ssh-keygen -M generate, cal- + culates numbers that are likely to be useful. A second primality testing + pass, using ssh-keygen -M screen, provides a high degree of assurance + that the numbers are prime and are safe for use in Diffie-Hellman opera- + tions by sshd(8). This moduli format is used as the output from each + pass. - The file consists of newline-separated records, one per modulus, - containing seven space-separated fields. These fields are as follows: + The file consists of newline-separated records, one per modulus, contain- + ing seven space-separated fields. These fields are as follows: - timestamp The time that the modulus was last processed as - YYYYMMDDHHMMSS. + timestamp The time that the modulus was last processed as YYYYM- + MDDHHMMSS. type Decimal number specifying the internal structure of the prime modulus. Supported types are: @@ -39,7 +39,7 @@ bitmask of the following values: 0x00 Not tested. - 0x01 Composite number M-bM-^@M-^S not prime. + 0x01 Composite number - not prime. 0x02 Sieve of Eratosthenes. 0x04 Probabilistic Miller-Rabin primality tests. @@ -48,8 +48,8 @@ ssh-keygen(1) primality tests are Miller-Rabin tests (flag 0x04). - trials Decimal number indicating the number of primality - trials that have been performed on the modulus. + trials Decimal number indicating the number of primality tri- + als that have been performed on the modulus. size Decimal number indicating the size of the prime in bits. @@ -67,8 +67,9 @@ SEE ALSO ssh-keygen(1), sshd(8) -STANDARDS - M. Friedl, N. Provos, and W. Simpson, Diffie-Hellman Group Exchange for - the Secure Shell (SSH) Transport Layer Protocol, RFC 4419, March 2006. +CONFORMING TO + 1. M. Friedl, N. Provos, and W. Simpson, Diffie-Hellman Group Exchange + for the Secure Shell (SSH) Transport Layer Protocol, RFC 4419, March + 2006. -OpenBSD 7.3 April 16, 2022 OpenBSD 7.3 +BSD 16 April 2022 BSD diff -ruN openssh-9.4p1/moduli.5 openssh-9.4p1+x509-14.2.1/moduli.5 --- openssh-9.4p1/moduli.5 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/moduli.5 2023-08-20 10:07:00.000000000 +0300 @@ -13,6 +13,14 @@ .\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +.\" Implement .Dd with the Mdocdate RCS keyword +.rn Dd xD +.de Dd +.ie \\$1$Mdocdate: \{\ +. xD \\$3 \\$2 \\$4 +.\} +.el .xD \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 +.. .Dd $Mdocdate: April 16 2022 $ .Dt MODULI 5 .Os @@ -115,7 +123,9 @@ .Sh SEE ALSO .Xr ssh-keygen 1 , .Xr sshd 8 -.Sh STANDARDS +.Sh CONFORMING TO +.Bl -enum +.It .Rs .%A M. Friedl .%A N. Provos @@ -124,3 +134,4 @@ .%R RFC 4419 .%T Diffie-Hellman Group Exchange for the Secure Shell (SSH) Transport Layer Protocol .Re +.El diff -ruN openssh-9.4p1/moduli.c openssh-9.4p1+x509-14.2.1/moduli.c --- openssh-9.4p1/moduli.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/moduli.c 2023-08-20 10:07:01.000000000 +0300 @@ -60,7 +60,21 @@ #include "log.h" #include "misc.h" -#include "openbsd-compat/openssl-compat.h" + +static inline int +SSH_check_prime(const BIGNUM *p, int nchecks) { +#if defined(HAVE_BN_CHECK_PRIME) + /* OpenSSL 3.0+ */ + UNUSED(nchecks); + return BN_check_prime(p, NULL, NULL); +#elif defined(HAVE_BN_IS_PRIME_EX) + /* OpenSSL 0.9.8+, deprecated in 3.0 */ + return BN_is_prime_ex(p, nchecks, NULL, NULL); +#else /* OpenSSL <= 0.9.7* */ + return BN_is_prime(p, nchecks, NULL, NULL, NULL); +#endif +} + /* * File output defines @@ -188,7 +202,7 @@ { u_int64_t r, u, s = s32; - debug3("sieve_large %u", s32); + debug3("sieve_large %u", (unsigned)s32); largetries++; /* r = largebase mod s */ r = BN_mod_word(largebase, s32); @@ -452,7 +466,7 @@ { FILE *fp; char tmp[PATH_MAX]; - int r, writeok, closeok; + int r; r = snprintf(tmp, sizeof(tmp), "%s.XXXXXXXXXX", cpfile); if (r < 0 || r >= PATH_MAX) { @@ -469,9 +483,10 @@ close(r); return; } - writeok = (fprintf(fp, "%lu\n", (unsigned long)lineno) > 0); - closeok = (fclose(fp) == 0); - if (writeok && closeok && rename(tmp, cpfile) == 0) { + /* use r as flag */ + r = (fprintf(fp, "%lu\n", (unsigned long)lineno) > 0); + r = (fclose(fp) == 0) && r; + if (r && (rename(tmp, cpfile) != -1)) { debug3("wrote checkpoint line %lu to '%s'", (unsigned long)lineno, cpfile); } else { @@ -753,9 +768,9 @@ * that p is also prime. A single pass will weed out the * vast majority of composite q's. */ - is_prime = BN_is_prime_ex(q, 1, NULL, NULL); + is_prime = SSH_check_prime(q, 1); if (is_prime < 0) - fatal("BN_is_prime_ex failed"); + fatal("SSH_check_prime failed"); if (is_prime == 0) { debug("%10u: q failed first possible prime test", count_in); @@ -769,9 +784,9 @@ * will show up on the first Rabin-Miller iteration so it * doesn't hurt to specify a high iteration count. */ - is_prime = BN_is_prime_ex(p, trials, NULL, NULL); + is_prime = SSH_check_prime(p, trials); if (is_prime < 0) - fatal("BN_is_prime_ex failed"); + fatal("SSH_check_prime failed"); if (is_prime == 0) { debug("%10u: p is not prime", count_in); continue; @@ -779,9 +794,9 @@ debug("%10u: p is almost certainly prime", count_in); /* recheck q more rigorously */ - is_prime = BN_is_prime_ex(q, trials - 1, NULL, NULL); + is_prime = SSH_check_prime(q, trials - 1); if (is_prime < 0) - fatal("BN_is_prime_ex failed"); + fatal("SSH_check_prime failed"); if (is_prime == 0) { debug("%10u: q is not prime", count_in); continue; diff -ruN openssh-9.4p1/monitor.c openssh-9.4p1+x509-14.2.1/monitor.c --- openssh-9.4p1/monitor.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/monitor.c 2023-08-20 10:07:01.000000000 +0300 @@ -1,9 +1,11 @@ -/* $OpenBSD: monitor.c,v 1.236 2023/05/10 10:04:20 dtucker Exp $ */ +/* $OpenBSD: monitor.c,v 1.235 2023/02/17 04:22:50 dtucker Exp $ */ /* * Copyright 2002 Niels Provos * Copyright 2002 Markus Friedl * All rights reserved. * + * Copyright (c) 2014-2022 Roumen Petrov. All rights reserved. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -48,31 +50,24 @@ #include #include #ifdef HAVE_POLL_H -#include +# include #else # ifdef HAVE_SYS_POLL_H # include # endif #endif -#ifdef WITH_OPENSSL -#include -#endif - #include "openbsd-compat/sys-tree.h" #include "openbsd-compat/sys-queue.h" -#include "openbsd-compat/openssl-compat.h" #include "atomicio.h" #include "xmalloc.h" #include "ssh.h" -#include "sshkey.h" -#include "sshbuf.h" +#include "ssh-x509.h" #include "hostfile.h" #include "auth.h" #include "cipher.h" #include "kex.h" -#include "dh.h" #include "auth-pam.h" #include "packet.h" #include "auth-options.h" @@ -95,7 +90,6 @@ #include "authfd.h" #include "match.h" #include "ssherr.h" -#include "sk-api.h" #ifdef GSSAPI static Gssctxt *gsscontext = NULL; @@ -112,47 +106,49 @@ /* Functions on the monitor that answer unprivileged requests */ -int mm_answer_moduli(struct ssh *, int, struct sshbuf *); -int mm_answer_sign(struct ssh *, int, struct sshbuf *); -int mm_answer_pwnamallow(struct ssh *, int, struct sshbuf *); -int mm_answer_auth2_read_banner(struct ssh *, int, struct sshbuf *); -int mm_answer_authserv(struct ssh *, int, struct sshbuf *); -int mm_answer_authpassword(struct ssh *, int, struct sshbuf *); -int mm_answer_bsdauthquery(struct ssh *, int, struct sshbuf *); -int mm_answer_bsdauthrespond(struct ssh *, int, struct sshbuf *); -int mm_answer_keyallowed(struct ssh *, int, struct sshbuf *); -int mm_answer_keyverify(struct ssh *, int, struct sshbuf *); -int mm_answer_pty(struct ssh *, int, struct sshbuf *); -int mm_answer_pty_cleanup(struct ssh *, int, struct sshbuf *); -int mm_answer_term(struct ssh *, int, struct sshbuf *); -int mm_answer_sesskey(struct ssh *, int, struct sshbuf *); -int mm_answer_sessid(struct ssh *, int, struct sshbuf *); +#ifdef WITH_OPENSSL +static int mm_answer_moduli(struct ssh *, int, struct sshbuf *); +#endif +static int mm_answer_sign(struct ssh *, int, struct sshbuf *); +static int mm_answer_pwnamallow(struct ssh *, int, struct sshbuf *); +static int mm_answer_auth2_read_banner(struct ssh *, int, struct sshbuf *); +static int mm_answer_authserv(struct ssh *, int, struct sshbuf *); +static int mm_answer_authpassword(struct ssh *, int, struct sshbuf *); +#ifdef BSD_AUTH +static int mm_answer_bsdauthquery(struct ssh *, int, struct sshbuf *); +static int mm_answer_bsdauthrespond(struct ssh *, int, struct sshbuf *); +#endif +static int mm_answer_keyallowed(struct ssh *, int, struct sshbuf *); +static int mm_answer_keyverify(struct ssh *, int, struct sshbuf *); +static int mm_answer_pty(struct ssh *, int, struct sshbuf *); +static int mm_answer_pty_cleanup(struct ssh *, int, struct sshbuf *); +static int mm_answer_term(struct ssh *, int, struct sshbuf *); #ifdef USE_PAM -int mm_answer_pam_start(struct ssh *, int, struct sshbuf *); -int mm_answer_pam_account(struct ssh *, int, struct sshbuf *); -int mm_answer_pam_init_ctx(struct ssh *, int, struct sshbuf *); -int mm_answer_pam_query(struct ssh *, int, struct sshbuf *); -int mm_answer_pam_respond(struct ssh *, int, struct sshbuf *); -int mm_answer_pam_free_ctx(struct ssh *, int, struct sshbuf *); +static int mm_answer_pam_start(struct ssh *, int, struct sshbuf *); +static int mm_answer_pam_account(struct ssh *, int, struct sshbuf *); +static int mm_answer_pam_init_ctx(struct ssh *, int, struct sshbuf *); +static int mm_answer_pam_query(struct ssh *, int, struct sshbuf *); +static int mm_answer_pam_respond(struct ssh *, int, struct sshbuf *); +static int mm_answer_pam_free_ctx(struct ssh *, int, struct sshbuf *); #endif #ifdef GSSAPI -int mm_answer_gss_setup_ctx(struct ssh *, int, struct sshbuf *); -int mm_answer_gss_accept_ctx(struct ssh *, int, struct sshbuf *); -int mm_answer_gss_userok(struct ssh *, int, struct sshbuf *); -int mm_answer_gss_checkmic(struct ssh *, int, struct sshbuf *); +static int mm_answer_gss_setup_ctx(struct ssh *, int, struct sshbuf *); +static int mm_answer_gss_accept_ctx(struct ssh *, int, struct sshbuf *); +static int mm_answer_gss_userok(struct ssh *, int, struct sshbuf *); +static int mm_answer_gss_checkmic(struct ssh *, int, struct sshbuf *); #endif #ifdef SSH_AUDIT_EVENTS -int mm_answer_audit_event(struct ssh *, int, struct sshbuf *); -int mm_answer_audit_command(struct ssh *, int, struct sshbuf *); +static int mm_answer_audit_event(struct ssh *, int, struct sshbuf *); +static int mm_answer_audit_command(struct ssh *, int, struct sshbuf *); #endif static Authctxt *authctxt; /* local state for key verify */ -static u_char *key_blob = NULL; +static const u_char *key_blob = NULL; static size_t key_bloblen = 0; static u_int key_blobtype = MM_NOKEY; static struct sshauthopt *key_opts = NULL; @@ -160,8 +156,6 @@ static char *hostbased_chost = NULL; static char *auth_method = "unknown"; static char *auth_submethod = NULL; -static u_int session_id2_len = 0; -static u_char *session_id2 = NULL; static pid_t monitor_child_pid; struct mon_table { @@ -182,6 +176,7 @@ static int monitor_read(struct ssh *, struct monitor *, struct mon_table *, struct mon_table **); static int monitor_read_log(struct monitor *); +static void mm_get_keystate(struct monitor *); struct mon_table mon_dispatch_proto20[] = { #ifdef WITH_OPENSSL @@ -322,8 +317,7 @@ struct sshbuf *m; if ((m = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new failed", - __func__); + fatal_f("sshbuf_new failed"); mm_request_receive_expect(pmonitor->m_sendfd, MONITOR_REQ_PAM_ACCOUNT, m); authenticated = mm_answer_pam_account( @@ -353,7 +347,7 @@ ssh->authctxt = NULL; ssh_packet_set_log_preamble(ssh, "user %s", authctxt->user); - mm_get_keystate(ssh, pmonitor); + mm_get_keystate(pmonitor); /* Drain any buffered messages from the child */ while (pmonitor->m_log_recvfd != -1 && monitor_read_log(pmonitor) == 0) @@ -412,10 +406,11 @@ monitor_read_log(struct monitor *pmonitor) { struct sshbuf *logmsg; - u_int len, level, forced; + u_int len, level; char *msg; u_char *p; int r; + u_int32_t val; if ((logmsg = sshbuf_new()) == NULL) fatal_f("sshbuf_new"); @@ -433,8 +428,9 @@ } fatal_f("log fd read: %s", strerror(errno)); } - if ((r = sshbuf_get_u32(logmsg, &len)) != 0) + if ((r = sshbuf_get_u32(logmsg, &val)) != 0) fatal_fr(r, "parse len"); + len = val; if (len <= 4 || len > 8192) fatal_f("invalid log message length %u", len); @@ -444,15 +440,16 @@ fatal_fr(r, "reserve msg"); if (atomicio(read, pmonitor->m_log_recvfd, p, len) != len) fatal_f("log fd read: %s", strerror(errno)); - if ((r = sshbuf_get_u32(logmsg, &level)) != 0 || - (r = sshbuf_get_u32(logmsg, &forced)) != 0 || + + if ((r = sshbuf_get_u32(logmsg, &val)) != 0 || (r = sshbuf_get_cstring(logmsg, &msg, NULL)) != 0) fatal_fr(r, "parse"); + level = val; /* Log it */ if (log_level_name(level) == NULL) fatal_f("invalid log level %u (corrupted message?)", level); - sshlogdirect(level, forced, "%s [preauth]", msg); + sshlog(NULL, NULL, -1, level, "%s [preauth]", msg); sshbuf_free(logmsg); free(msg); @@ -533,7 +530,7 @@ /* allowed key state */ static int -monitor_allowed_key(const u_char *blob, u_int bloblen) +monitor_allowed_key(const u_char *blob, size_t bloblen) { /* make sure key is allowed */ if (key_blob == NULL || key_bloblen != bloblen || @@ -546,7 +543,7 @@ monitor_reset_key_state(void) { /* reset state */ - free(key_blob); + free((void*)key_blob); free(hostbased_cuser); free(hostbased_chost); sshauthopt_free(key_opts); @@ -562,40 +559,41 @@ int mm_answer_moduli(struct ssh *ssh, int sock, struct sshbuf *m) { - DH *dh; - const BIGNUM *dh_p, *dh_g; int r; - u_int min, want, max; + u_int32_t min, want, max; + UNUSED(ssh); if ((r = sshbuf_get_u32(m, &min)) != 0 || (r = sshbuf_get_u32(m, &want)) != 0 || (r = sshbuf_get_u32(m, &max)) != 0) fatal_fr(r, "parse"); - debug3_f("got parameters: %d %d %d", min, want, max); + debug3_f("got parameters: %d %d %d", (int)min, (int)want, (int)max); /* We need to check here, too, in case the child got corrupted */ - if (max < min || want < min || max < want) - fatal_f("bad parameters: %d %d %d", min, want, max); + if (max < min || want < min || max < want || + max > INT32_MAX || want > INT32_MAX || min > INT32_MAX) + fatal_f("bad parameters: %d %d %d", (int)min, (int)want, (int)max); sshbuf_reset(m); - dh = choose_dh(min, want, max); - if (dh == NULL) { +{ EVP_PKEY *pk; + + pk = kex_new_dh_group_bits(min, want, max); + if (pk == NULL) { if ((r = sshbuf_put_u8(m, 0)) != 0) fatal_fr(r, "assemble empty"); - return (0); + return 0; } else { - /* Send first bignum */ - DH_get0_pqg(dh, &dh_p, NULL, &dh_g); + /* send first bignum */ if ((r = sshbuf_put_u8(m, 1)) != 0 || - (r = sshbuf_put_bignum2(m, dh_p)) != 0 || - (r = sshbuf_put_bignum2(m, dh_g)) != 0) + (r = sshbuf_kex_write_dh_group(m, pk)) != 0) fatal_fr(r, "assemble"); - DH_free(dh); + EVP_PKEY_free(pk); } +} mm_request_send(sock, MONITOR_ANS_MODULI, m); - return (0); + return 0; } #endif @@ -604,12 +602,13 @@ { extern int auth_sock; /* XXX move to state struct? */ struct sshkey *key; + struct kex *kex = ssh->kex; struct sshbuf *sigbuf = NULL; u_char *p = NULL, *signature = NULL; char *alg = NULL; size_t datlen, siglen, alglen; int r, is_proof = 0; - u_int keyid, compat; + u_int32_t keyid; const char proof_req[] = "hostkeys-prove-00@openssh.com"; debug3_f("entering"); @@ -617,9 +616,10 @@ if ((r = sshbuf_get_u32(m, &keyid)) != 0 || (r = sshbuf_get_string(m, &p, &datlen)) != 0 || (r = sshbuf_get_cstring(m, &alg, &alglen)) != 0 || - (r = sshbuf_get_u32(m, &compat)) != 0) + (r = sshbuf_get_compat(m, &ssh->compat)) != 0) fatal_fr(r, "parse"); - if (keyid > INT_MAX) + xcompat = ssh->compat.extra; /* TODO */ + if (keyid > INT32_MAX) fatal_f("invalid key ID"); /* @@ -638,16 +638,17 @@ * Construct expected hostkey proof and compare it to what * the client sent us. */ - if (session_id2_len == 0) /* hostkeys is never first */ + /* NOTE: hostkey is never first */ + if (sshbuf_len(kex->session_id) == 0) fatal_f("bad data length: %zu", datlen); if ((key = get_hostkey_public_by_index(keyid, ssh)) == NULL) fatal_f("no hostkey for index %d", keyid); if ((sigbuf = sshbuf_new()) == NULL) fatal_f("sshbuf_new"); if ((r = sshbuf_put_cstring(sigbuf, proof_req)) != 0 || - (r = sshbuf_put_string(sigbuf, session_id2, - session_id2_len)) != 0 || - (r = sshkey_puts(key, sigbuf)) != 0) + (r = sshbuf_put_stringb(sigbuf, + kex->session_id)) != 0 || + (r = Xkey_puts(alg, key, sigbuf)) != 0) fatal_fr(r, "assemble private key proof"); if (datlen != sshbuf_len(sigbuf) || memcmp(p, sshbuf_ptr(sigbuf), sshbuf_len(sigbuf)) != 0) @@ -658,20 +659,21 @@ } /* save session id, it will be passed on the first call */ - if (session_id2_len == 0) { - session_id2_len = datlen; - session_id2 = xmalloc(session_id2_len); - memcpy(session_id2, p, session_id2_len); + if (sshbuf_len(kex->session_id) == 0) { + r = sshbuf_put(kex->session_id, p, datlen); + if (r != 0) + fatal_fr(r, "session_id"); } if ((key = get_hostkey_by_index(keyid)) != NULL) { - if ((r = sshkey_sign(key, &signature, &siglen, p, datlen, alg, - options.sk_provider, NULL, compat)) != 0) + ssh_sign_ctx ctx = { alg, key, &ssh->compat, NULL, NULL }; + if ((r = Xkey_sign(&ctx, &signature, &siglen, p, datlen)) != 0) fatal_fr(r, "sign"); } else if ((key = get_hostkey_public_by_index(keyid, ssh)) != NULL && auth_sock > 0) { - if ((r = ssh_agent_sign(auth_sock, key, &signature, &siglen, - p, datlen, alg, compat)) != 0) + ssh_sign_ctx ctx = { alg, key, &ssh->compat, NULL, NULL }; + if ((r = Xssh_agent_sign(auth_sock, &ctx, &signature, &siglen, + p, datlen)) != 0) fatal_fr(r, "agent sign"); } else fatal_f("no hostkey from index %d", keyid); @@ -764,6 +766,14 @@ if ((r = sshbuf_put_string(m, &options, sizeof(options))) != 0) fatal_fr(r, "assemble options"); +{ /* for string options that are not set we must send empty string! */ + const char *s1 = options.hostbased_algorithms ? options.hostbased_algorithms : ""; + const char *s2 = options.pubkey_algorithms ? options.pubkey_algorithms : ""; + if ((r = sshbuf_put_cstring(m, s1)) != 0 || + (r = sshbuf_put_cstring(m, s2)) != 0) + fatal_fr(r, "assemble algorithms"); +} + #define M_CP_STROPT(x) do { \ if (options.x != NULL && \ (r = sshbuf_put_cstring(m, options.x)) != 0) \ @@ -784,7 +794,7 @@ if (auth2_setup_methods_lists(authctxt) != 0) { /* * The monitor will continue long enough to let the child - * run to its packet_disconnect(), but it must not allow any + * run to its ssh_packet_disconnect(), but it must not allow any * authentication to succeed. */ debug_f("no valid authentication method lists"); @@ -805,11 +815,13 @@ return (0); } -int mm_answer_auth2_read_banner(struct ssh *ssh, int sock, struct sshbuf *m) +int +mm_answer_auth2_read_banner(struct ssh *ssh, int sock, struct sshbuf *m) { char *banner; int r; + UNUSED(ssh); sshbuf_reset(m); banner = auth2_read_banner(); if ((r = sshbuf_put_cstring(m, banner != NULL ? banner : "")) != 0) @@ -825,6 +837,8 @@ { int r; + UNUSED(ssh); + UNUSED(sock); monitor_permit_authentications(1); if ((r = sshbuf_get_cstring(m, &authctxt->service, NULL)) != 0 || @@ -840,35 +854,6 @@ return (0); } -/* - * Check that the key type appears in the supplied pattern list, ignoring - * mismatches in the signature algorithm. (Signature algorithm checks are - * performed in the unprivileged authentication code). - * Returns 1 on success, 0 otherwise. - */ -static int -key_base_type_match(const char *method, const struct sshkey *key, - const char *list) -{ - char *s, *l, *ol = xstrdup(list); - int found = 0; - - l = ol; - for ((s = strsep(&l, ",")); s && *s != '\0'; (s = strsep(&l, ","))) { - if (sshkey_type_from_name(s) == key->type) { - found = 1; - break; - } - } - if (!found) { - error("%s key type %s is not in permitted list %s", method, - sshkey_ssh_name(key), list); - } - - free(ol); - return found; -} - int mm_answer_authpassword(struct ssh *ssh, int sock, struct sshbuf *m) { @@ -894,7 +879,6 @@ fatal_fr(r, "assemble PAM"); #endif - debug3("%s: sending result %d", __func__, authenticated); debug3_f("sending result %d", authenticated); mm_request_send(sock, MONITOR_ANS_AUTHPASSWORD, m); @@ -917,6 +901,7 @@ char **prompts; int r; + UNUSED(ssh); if (!options.kbd_interactive_authentication) fatal_f("kbd-int authentication not enabled"); success = bsdauth_query(authctxt, &name, &infotxt, &numprompts, @@ -949,6 +934,7 @@ char *response; int r, authok; + UNUSED(ssh); if (!options.kbd_interactive_authentication) fatal_f("kbd-int authentication not enabled"); if (authctxt->as == NULL) @@ -956,8 +942,7 @@ if ((r = sshbuf_get_cstring(m, &response, NULL)) != 0) fatal_fr(r, "parse"); - authok = options.kbd_interactive_authentication && - auth_userresponse(authctxt->as, response, 0); + authok = auth_userresponse(authctxt->as, response, 0); authctxt->as = NULL; debug3_f("<%s> = <%d>", response, authok); free(response); @@ -980,8 +965,10 @@ int mm_answer_pam_start(struct ssh *ssh, int sock, struct sshbuf *m) { + UNUSED(sock); + UNUSED(m); if (!options.use_pam) - fatal("UsePAM not set, but ended up in %s anyway", __func__); + fatal_f("PAM not enabled"); start_pam(ssh); @@ -998,14 +985,15 @@ u_int ret; int r; + UNUSED(ssh); if (!options.use_pam) - fatal("%s: PAM not enabled", __func__); + fatal_f("PAM not enabled"); ret = do_pam_account(); if ((r = sshbuf_put_u32(m, ret)) != 0 || (r = sshbuf_put_stringb(m, loginmsg)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "assemble"); mm_request_send(sock, MONITOR_ANS_PAM_ACCOUNT, m); @@ -1021,11 +1009,12 @@ u_int ok = 0; int r; - debug3("%s", __func__); + UNUSED(ssh); + debug3_f("entering"); if (!options.kbd_interactive_authentication) - fatal("%s: kbd-int authentication not enabled", __func__); + fatal_f("kbd-int authentication not enabled"); if (sshpam_ctxt != NULL) - fatal("%s: already called", __func__); + fatal_f("already called"); sshpam_ctxt = (sshpam_device.init_ctx)(authctxt); sshpam_authok = NULL; sshbuf_reset(m); @@ -1035,7 +1024,7 @@ ok = 1; } if ((r = sshbuf_put_u32(m, ok)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "assemble"); mm_request_send(sock, MONITOR_ANS_PAM_INIT_CTX, m); return (0); } @@ -1047,10 +1036,11 @@ u_int i, num = 0, *echo_on = 0; int r, ret; - debug3("%s", __func__); + UNUSED(ssh); + debug3_f("entering"); sshpam_authok = NULL; if (sshpam_ctxt == NULL) - fatal("%s: no context", __func__); + fatal_f("no context"); ret = (sshpam_device.query)(sshpam_ctxt, &name, &info, &num, &prompts, &echo_on); if (ret == 0 && num == 0) @@ -1064,13 +1054,13 @@ (r = sshbuf_put_cstring(m, info)) != 0 || (r = sshbuf_put_u32(m, sshpam_get_maxtries_reached())) != 0 || (r = sshbuf_put_u32(m, num)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "assemble"); free(name); free(info); for (i = 0; i < num; ++i) { if ((r = sshbuf_put_cstring(m, prompts[i])) != 0 || (r = sshbuf_put_u32(m, echo_on[i])) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "assemble prompt %u", i); free(prompts[i]); } free(prompts); @@ -1085,25 +1075,26 @@ mm_answer_pam_respond(struct ssh *ssh, int sock, struct sshbuf *m) { char **resp; - u_int i, num; + u_int num; + u_int32_t i, val; int r, ret; - debug3("%s", __func__); + UNUSED(ssh); + debug3_f("entering"); if (sshpam_ctxt == NULL) - fatal("%s: no context", __func__); + fatal_f("no context"); sshpam_authok = NULL; - if ((r = sshbuf_get_u32(m, &num)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); - if (num > PAM_MAX_NUM_MSG) { + if ((r = sshbuf_get_u32(m, &val)) != 0) /*num*/ + fatal_fr(r, "parse"); + num = val; + if (num > PAM_MAX_NUM_MSG) fatal_f("Too many PAM messages, got %u, expected <= %u", num, (unsigned)PAM_MAX_NUM_MSG); - } if (num > 0) { resp = xcalloc(num, sizeof(char *)); for (i = 0; i < num; ++i) { if ((r = sshbuf_get_cstring(m, &(resp[i]), NULL)) != 0) - fatal("%s: buffer error: %s", - __func__, ssh_err(r)); + fatal_fr(r, "parse respond %u", i); } ret = (sshpam_device.respond)(sshpam_ctxt, num, resp); for (i = 0; i < num; ++i) @@ -1114,7 +1105,7 @@ } sshbuf_reset(m); if ((r = sshbuf_put_u32(m, ret)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "assemble"); mm_request_send(sock, MONITOR_ANS_PAM_RESPOND, m); auth_method = "keyboard-interactive"; auth_submethod = "pam"; @@ -1128,9 +1119,10 @@ { int r = sshpam_authok != NULL && sshpam_authok == sshpam_ctxt; - debug3("%s", __func__); + UNUSED(ssh); + debug3_f("entering"); if (sshpam_ctxt == NULL) - fatal("%s: no context", __func__); + fatal_f("no context"); (sshpam_device.free_ctx)(sshpam_ctxt); sshpam_ctxt = sshpam_authok = NULL; sshbuf_reset(m); @@ -1148,8 +1140,10 @@ { struct sshkey *key = NULL; char *cuser, *chost; - u_int pubkey_auth_attempt; - u_int type = 0; + char *pkalg; + u_char *blob; + size_t bloblen; + u_int32_t type, pubkey_auth_attempt; int r, allowed = 0; struct sshauthopt *opts = NULL; @@ -1157,10 +1151,18 @@ if ((r = sshbuf_get_u32(m, &type)) != 0 || (r = sshbuf_get_cstring(m, &cuser, NULL)) != 0 || (r = sshbuf_get_cstring(m, &chost, NULL)) != 0 || - (r = sshkey_froms(m, &key)) != 0 || + (r = sshbuf_get_cstring(m, &pkalg, NULL)) != 0 || + (r = sshbuf_get_string(m, &blob, &bloblen)) != 0 || (r = sshbuf_get_u32(m, &pubkey_auth_attempt)) != 0) fatal_fr(r, "parse"); + if ((r = Xkey_from_blob(pkalg, blob, bloblen, &key)) != 0) + fatal_fr(r, "Xkey_from_blob"); + + debug3_f("Xkey_from_blob: %s", pkalg); + +{ ssh_verify_ctx ctx = { pkalg, key, &ssh->compat }; + if (key != NULL && authctxt->valid) { switch (type) { case MM_USERKEY: @@ -1169,10 +1171,10 @@ break; if (auth2_key_already_used(authctxt, key)) break; - if (!key_base_type_match(auth_method, key, - options.pubkey_accepted_algos)) - break; - allowed = user_key_allowed(ssh, authctxt->pw, key, + /* NOTE: algorithm is already allowed + in user authentication request. */ + /* TODO: cast to int, but auth_attempt is unused */ + allowed = user_xkey_allowed(ssh, authctxt->pw, &ctx, pubkey_auth_attempt, &opts); break; case MM_HOSTKEY: @@ -1181,20 +1183,20 @@ break; if (auth2_key_already_used(authctxt, key)) break; - if (!key_base_type_match(auth_method, key, - options.hostbased_accepted_algos)) - break; - allowed = hostbased_key_allowed(ssh, authctxt->pw, - cuser, chost, key); + /* NOTE: algorithm is already allowed + in user authentication request. */ + allowed = hostbased_xkey_allowed(ssh, authctxt->pw, + &ctx, cuser, chost); auth2_record_info(authctxt, "client user \"%.100s\", client host \"%.100s\"", cuser, chost); break; default: - fatal_f("unknown key type %u", type); + fatal_f("unknown key type %u", (u_int)type); break; } } +} debug3_f("%s authentication%s: %s key is %s", auth_method, pubkey_auth_attempt ? "" : " test", @@ -1202,14 +1204,15 @@ allowed ? "allowed" : "not allowed"); auth2_record_key(authctxt, 0, key); + sshkey_free(key); /* clear temporarily storage (used by verify) */ monitor_reset_key_state(); if (allowed) { /* Save temporarily for comparison in verify */ - if ((r = sshkey_to_blob(key, &key_blob, &key_bloblen)) != 0) - fatal_fr(r, "sshkey_to_blob"); + key_blob = blob; + key_bloblen = bloblen; key_blobtype = type; key_opts = opts; hostbased_cuser = cuser; @@ -1217,15 +1220,17 @@ } else { /* Log failed attempt */ auth_log(ssh, 0, 0, auth_method, NULL); + free(blob); free(cuser); free(chost); } - sshkey_free(key); + free(pkalg); sshbuf_reset(m); if ((r = sshbuf_put_u32(m, allowed)) != 0) fatal_fr(r, "assemble"); - if (opts != NULL && (r = sshauthopt_serialise(opts, m, 1)) != 0) + if (opts != NULL && + (r = sshauthopt_serialise(opts, m, 1)) != 0) fatal_fr(r, "sshauthopt_serialise"); mm_request_send(sock, MONITOR_ANS_KEYALLOWED, m); @@ -1236,36 +1241,39 @@ } static int -monitor_valid_userblob(struct ssh *ssh, const u_char *data, u_int datalen) +monitor_valid_userblob(struct ssh *ssh, const u_char *data, size_t datalen) { struct sshbuf *b; - struct sshkey *hostkey = NULL; const u_char *p; char *userstyle, *cp; size_t len; u_char type; - int hostbound = 0, r, fail = 0; + int r, fail = 0; if ((b = sshbuf_from(data, datalen)) == NULL) fatal_f("sshbuf_from"); - if (ssh->compat & SSH_OLD_SESSIONID) { +{ struct kex *kex = ssh->kex; + if (ssh_compat_fellows(ssh, SSH_OLD_SESSIONID)) { p = sshbuf_ptr(b); len = sshbuf_len(b); - if ((session_id2 == NULL) || - (len < session_id2_len) || - (timingsafe_bcmp(p, session_id2, session_id2_len) != 0)) + if ((len < sshbuf_len(kex->session_id)) || + (timingsafe_bcmp(p, + sshbuf_ptr(kex->session_id), + sshbuf_len(kex->session_id)) != 0)) fail++; - if ((r = sshbuf_consume(b, session_id2_len)) != 0) + if ((r = sshbuf_consume(b, sshbuf_len(kex->session_id))) != 0) fatal_fr(r, "consume"); } else { if ((r = sshbuf_get_string_direct(b, &p, &len)) != 0) fatal_fr(r, "parse sessionid"); - if ((session_id2 == NULL) || - (len != session_id2_len) || - (timingsafe_bcmp(p, session_id2, session_id2_len) != 0)) + if ((len != sshbuf_len(kex->session_id)) || + (timingsafe_bcmp(p, + sshbuf_ptr(kex->session_id), + sshbuf_len(kex->session_id)) != 0)) fail++; } +} if ((r = sshbuf_get_u8(b, &type)) != 0) fatal_fr(r, "parse type"); if (type != SSH2_MSG_USERAUTH_REQUEST) @@ -1285,39 +1293,24 @@ if ((r = sshbuf_skip_string(b)) != 0 || /* service */ (r = sshbuf_get_cstring(b, &cp, NULL)) != 0) fatal_fr(r, "parse method"); - if (strcmp("publickey", cp) != 0) { - if (strcmp("publickey-hostbound-v00@openssh.com", cp) == 0) - hostbound = 1; - else - fail++; - } + if (strcmp("publickey", cp) != 0) + fail++; free(cp); if ((r = sshbuf_get_u8(b, &type)) != 0) fatal_fr(r, "parse pktype"); if (type == 0) fail++; if ((r = sshbuf_skip_string(b)) != 0 || /* pkalg */ - (r = sshbuf_skip_string(b)) != 0 || /* pkblob */ - (hostbound && (r = sshkey_froms(b, &hostkey)) != 0)) + (r = sshbuf_skip_string(b)) != 0) /* pkblob */ fatal_fr(r, "parse pk"); if (sshbuf_len(b) != 0) fail++; sshbuf_free(b); - if (hostkey != NULL) { - /* - * Ensure this is actually one of our hostkeys; unfortunately - * can't check ssh->kex->initial_hostkey directly at this point - * as packet state has not yet been exported to monitor. - */ - if (get_hostkey_index(hostkey, 1, ssh) == -1) - fatal_f("hostbound hostkey does not match"); - sshkey_free(hostkey); - } return (fail == 0); } static int -monitor_valid_hostbasedblob(const u_char *data, u_int datalen, +monitor_valid_hostbasedblob(struct ssh *ssh, const u_char *data, size_t datalen, const char *cuser, const char *chost) { struct sshbuf *b; @@ -1328,13 +1321,14 @@ u_char type; if ((b = sshbuf_from(data, datalen)) == NULL) - fatal_f("sshbuf_new"); + fatal_f("sshbuf_from"); if ((r = sshbuf_get_string_direct(b, &p, &len)) != 0) fatal_fr(r, "parse sessionid"); - if ((session_id2 == NULL) || - (len != session_id2_len) || - (timingsafe_bcmp(p, session_id2, session_id2_len) != 0)) + if ((len != sshbuf_len(ssh->kex->session_id)) || + (timingsafe_bcmp(p, + sshbuf_ptr(ssh->kex->session_id), + sshbuf_len(ssh->kex->session_id)) != 0)) fail++; if ((r = sshbuf_get_u8(b, &type)) != 0) @@ -1388,33 +1382,25 @@ int mm_answer_keyverify(struct ssh *ssh, int sock, struct sshbuf *m) { + u_char *pkalg = NULL; struct sshkey *key; - const u_char *signature, *data, *blob; - char *sigalg = NULL, *fp = NULL; + u_char *signature, *data, *blob; size_t signaturelen, datalen, bloblen; - int r, ret, req_presence = 0, req_verify = 0, valid_data = 0; - int encoded_ret; - struct sshkey_sig_details *sig_details = NULL; - - if ((r = sshbuf_get_string_direct(m, &blob, &bloblen)) != 0 || - (r = sshbuf_get_string_direct(m, &signature, &signaturelen)) != 0 || - (r = sshbuf_get_string_direct(m, &data, &datalen)) != 0 || - (r = sshbuf_get_cstring(m, &sigalg, NULL)) != 0) + int r, ret, valid_data = 0; + + if ((r = sshbuf_get_string(m, &pkalg, NULL)) != 0 || + (r = sshbuf_get_string(m, &blob, &bloblen)) != 0 || + (r = sshbuf_get_string(m, &signature, &signaturelen)) != 0 || + (r = sshbuf_get_string(m, &data, &datalen)) != 0) fatal_fr(r, "parse"); if (hostbased_cuser == NULL || hostbased_chost == NULL || !monitor_allowed_key(blob, bloblen)) fatal_f("bad key, not previously allowed"); - /* Empty signature algorithm means NULL. */ - if (*sigalg == '\0') { - free(sigalg); - sigalg = NULL; - } - - /* XXX use sshkey_froms here; need to change key_blob, etc. */ - if ((r = sshkey_from_blob(blob, bloblen, &key)) != 0) - fatal_fr(r, "parse key"); + key = xkey_from_blob(pkalg, blob, bloblen); + if (key == NULL) + fatal_f("parse key"); switch (key_blobtype) { case MM_USERKEY: @@ -1422,7 +1408,7 @@ auth_method = "publickey"; break; case MM_HOSTKEY: - valid_data = monitor_valid_hostbasedblob(data, datalen, + valid_data = monitor_valid_hostbasedblob(ssh, data, datalen, hostbased_cuser, hostbased_chost); auth_method = "hostbased"; break; @@ -1431,49 +1417,15 @@ break; } if (!valid_data) - fatal_f("bad %s signature data blob", - key_blobtype == MM_USERKEY ? "userkey" : - (key_blobtype == MM_HOSTKEY ? "hostkey" : "unknown")); - - if ((fp = sshkey_fingerprint(key, options.fingerprint_hash, - SSH_FP_DEFAULT)) == NULL) - fatal_f("sshkey_fingerprint failed"); - - ret = sshkey_verify(key, signature, signaturelen, data, datalen, - sigalg, ssh->compat, &sig_details); - debug3_f("%s %s signature using %s %s%s%s", auth_method, - sshkey_type(key), sigalg == NULL ? "default" : sigalg, + fatal_f("bad signature data blob"); + +{ ssh_verify_ctx ctx = { pkalg, key, &ssh->compat }; + + ret = Xkey_verify(&ctx, signature, signaturelen, data, datalen); + debug3_f("%s %s signature %s%s%s", auth_method, pkalg, (ret == 0) ? "verified" : "unverified", (ret != 0) ? ": " : "", (ret != 0) ? ssh_err(ret) : ""); - - if (ret == 0 && key_blobtype == MM_USERKEY && sig_details != NULL) { - req_presence = (options.pubkey_auth_options & - PUBKEYAUTH_TOUCH_REQUIRED) || - !key_opts->no_require_user_presence; - if (req_presence && - (sig_details->sk_flags & SSH_SK_USER_PRESENCE_REQD) == 0) { - error("public key %s %s signature for %s%s from %.128s " - "port %d rejected: user presence " - "(authenticator touch) requirement not met ", - sshkey_type(key), fp, - authctxt->valid ? "" : "invalid user ", - authctxt->user, ssh_remote_ipaddr(ssh), - ssh_remote_port(ssh)); - ret = SSH_ERR_SIGNATURE_INVALID; - } - req_verify = (options.pubkey_auth_options & - PUBKEYAUTH_VERIFY_REQUIRED) || key_opts->require_verify; - if (req_verify && - (sig_details->sk_flags & SSH_SK_USER_VERIFICATION_REQD) == 0) { - error("public key %s %s signature for %s%s from %.128s " - "port %d rejected: user verification requirement " - "not met ", sshkey_type(key), fp, - authctxt->valid ? "" : "invalid user ", - authctxt->user, ssh_remote_ipaddr(ssh), - ssh_remote_port(ssh)); - ret = SSH_ERR_SIGNATURE_INVALID; - } - } +} auth2_record_key(authctxt, ret == 0, key); if (key_blobtype == MM_USERKEY) @@ -1482,21 +1434,17 @@ sshbuf_reset(m); - /* encode ret != 0 as positive integer, since we're sending u32 */ - encoded_ret = (ret != 0); - if ((r = sshbuf_put_u32(m, encoded_ret)) != 0 || - (r = sshbuf_put_u8(m, sig_details != NULL)) != 0) +{ /* encode ret != 0 as positive integer, since we're sending u32 */ + int encoded_ret = (ret != 0); + if ((r = sshbuf_put_u32(m, encoded_ret)) != 0) fatal_fr(r, "assemble"); - if (sig_details != NULL) { - if ((r = sshbuf_put_u32(m, sig_details->sk_counter)) != 0 || - (r = sshbuf_put_u8(m, sig_details->sk_flags)) != 0) - fatal_fr(r, "assemble sk"); - } - sshkey_sig_details_free(sig_details); +} mm_request_send(sock, MONITOR_ANS_KEYVERIFY, m); - free(sigalg); - free(fp); + free(pkalg); + free(blob); + free(signature); + free(data); sshkey_free(key); return ret == 0; @@ -1564,7 +1512,7 @@ fatal_fr(r, "assemble"); /* We need to trick ttyslot */ - if (dup2(s->ttyfd, 0) == -1) + if (dup2(s->ttyfd, STDIN_FILENO) == -1) fatal_f("dup2"); mm_record_login(ssh, s, authctxt->pw); @@ -1603,7 +1551,7 @@ if (s != NULL) mm_session_close(s); if ((r = sshbuf_put_u32(m, 0)) != 0) - fatal_fr(r, "assemble 0"); + fatal_fr(r, "assemble"); mm_request_send(sock, MONITOR_ANS_PTY, m); return (0); } @@ -1615,6 +1563,8 @@ char *tty; int r; + UNUSED(ssh); + UNUSED(sock); debug3_f("entering"); if ((r = sshbuf_get_cstring(m, &tty, NULL)) != 0) @@ -1627,11 +1577,13 @@ } int -mm_answer_term(struct ssh *ssh, int sock, struct sshbuf *req) +mm_answer_term(struct ssh *ssh, int sock, struct sshbuf *m) { extern struct monitor *pmonitor; int res, status; + UNUSED(sock); + UNUSED(m); debug3_f("tearing down sessions"); /* The child is terminating */ @@ -1655,16 +1607,17 @@ #ifdef SSH_AUDIT_EVENTS /* Report that an audit event occurred */ int -mm_answer_audit_event(struct ssh *ssh, int socket, struct sshbuf *m) +mm_answer_audit_event(struct ssh *ssh, int sock, struct sshbuf *m) { - u_int n; + u_int32_t n; ssh_audit_event_t event; int r; - debug3("%s entering", __func__); + UNUSED(sock); + debug3_f("entering"); if ((r = sshbuf_get_u32(m, &n)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "parse"); event = (ssh_audit_event_t)n; switch (event) { case SSH_AUTH_FAIL_PUBKEY: @@ -1684,14 +1637,16 @@ } int -mm_answer_audit_command(struct ssh *ssh, int socket, struct sshbuf *m) +mm_answer_audit_command(struct ssh *ssh, int sock, struct sshbuf *m) { char *cmd; int r; - debug3("%s entering", __func__); + UNUSED(ssh); + UNUSED(sock); + debug3_f("entering"); if ((r = sshbuf_get_cstring(m, &cmd, NULL)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "parse"); /* sanity check command, if so how? */ audit_run_command(cmd); free(cmd); @@ -1700,7 +1655,7 @@ #endif /* SSH_AUDIT_EVENTS */ void -monitor_clear_keystate(struct ssh *ssh, struct monitor *pmonitor) +monitor_clear_keystate(struct ssh *ssh) { ssh_clear_newkeys(ssh, MODE_IN); ssh_clear_newkeys(ssh, MODE_OUT); @@ -1709,58 +1664,39 @@ } void -monitor_apply_keystate(struct ssh *ssh, struct monitor *pmonitor) +monitor_apply_keystate(struct ssh *ssh) { struct kex *kex; int r; - debug3_f("packet_set_state"); + debug3_f("entering"); if ((r = ssh_packet_set_state(ssh, child_state)) != 0) - fatal_fr(r, "packet_set_state"); + fatal_fr(r, "ssh_packet_set_state"); sshbuf_free(child_state); child_state = NULL; - if ((kex = ssh->kex) == NULL) - fatal_f("internal error: ssh->kex == NULL"); - if (session_id2_len != sshbuf_len(ssh->kex->session_id)) { - fatal_f("incorrect session id length %zu (expected %u)", - sshbuf_len(ssh->kex->session_id), session_id2_len); - } - if (memcmp(sshbuf_ptr(ssh->kex->session_id), session_id2, - session_id2_len) != 0) - fatal_f("session ID mismatch"); - /* XXX set callbacks */ -#ifdef WITH_OPENSSL - kex->kex[KEX_DH_GRP1_SHA1] = kex_gen_server; - kex->kex[KEX_DH_GRP14_SHA1] = kex_gen_server; - kex->kex[KEX_DH_GRP14_SHA256] = kex_gen_server; - kex->kex[KEX_DH_GRP16_SHA512] = kex_gen_server; - kex->kex[KEX_DH_GRP18_SHA512] = kex_gen_server; - kex->kex[KEX_DH_GEX_SHA1] = kexgex_server; - kex->kex[KEX_DH_GEX_SHA256] = kexgex_server; -# ifdef OPENSSL_HAS_ECC - kex->kex[KEX_ECDH_SHA2] = kex_gen_server; -# endif -#endif /* WITH_OPENSSL */ - kex->kex[KEX_C25519_SHA256] = kex_gen_server; - kex->kex[KEX_KEM_SNTRUP761X25519_SHA512] = kex_gen_server; - kex->load_host_public_key=&get_hostkey_public_by_type; - kex->load_host_private_key=&get_hostkey_private_by_type; + + kex = ssh->kex; + if (kex == NULL) return; + + kex_set_callbacks_server(kex); + kex->find_host_public_key=&get_hostkey_public_by_alg; + kex->find_host_private_key=&get_hostkey_private_by_alg; kex->host_key_index=&get_hostkey_index; - kex->sign = sshd_hostkey_sign; + kex->xsign = Xsshd_hostkey_sign; } /* This function requires careful sanity checking */ -void -mm_get_keystate(struct ssh *ssh, struct monitor *pmonitor) +static void +mm_get_keystate(struct monitor *pmonitor) { - debug3_f("Waiting for new keys"); + debug3_f("waiting for new keys"); if ((child_state = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); mm_request_receive_expect(pmonitor->m_sendfd, MONITOR_REQ_KEYEXPORT, child_state); - debug3_f("GOT new keys"); + debug3_f("got new keys"); } @@ -1832,6 +1768,7 @@ u_char *p; int r; + UNUSED(ssh); if (!options.gss_authentication) fatal_f("GSSAPI authentication not enabled"); @@ -1865,6 +1802,7 @@ OM_uint32 flags = 0; /* GSI needs this */ int r; + UNUSED(ssh); if (!options.gss_authentication) fatal_f("GSSAPI authentication not enabled"); @@ -1897,6 +1835,7 @@ OM_uint32 ret; int r; + UNUSED(ssh); if (!options.gss_authentication) fatal_f("GSSAPI authentication not enabled"); @@ -1927,6 +1866,7 @@ int r, authenticated; const char *displayname; + UNUSED(ssh); if (!options.gss_authentication) fatal_f("GSSAPI authentication not enabled"); diff -ruN openssh-9.4p1/monitor_fdpass.c openssh-9.4p1+x509-14.2.1/monitor_fdpass.c --- openssh-9.4p1/monitor_fdpass.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/monitor_fdpass.c 2023-08-20 10:07:01.000000000 +0300 @@ -103,7 +103,7 @@ } return 0; #else - error("%s: file descriptor passing not supported", __func__); + error_f("file descriptor passing not supported"); return -1; #endif } diff -ruN openssh-9.4p1/monitor.h openssh-9.4p1+x509-14.2.1/monitor.h --- openssh-9.4p1/monitor.h 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/monitor.h 2023-08-20 10:07:00.000000000 +0300 @@ -3,6 +3,7 @@ /* * Copyright 2002 Niels Provos * All rights reserved. + * Copyright (c) 2018-2019 Roumen Petrov. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -44,17 +45,11 @@ MONITOR_REQ_KEYEXPORT = 26, MONITOR_REQ_PTY = 28, MONITOR_ANS_PTY = 29, MONITOR_REQ_PTYCLEANUP = 30, - MONITOR_REQ_SESSKEY = 32, MONITOR_ANS_SESSKEY = 33, - MONITOR_REQ_SESSID = 34, - MONITOR_REQ_RSAKEYALLOWED = 36, MONITOR_ANS_RSAKEYALLOWED = 37, - MONITOR_REQ_RSACHALLENGE = 38, MONITOR_ANS_RSACHALLENGE = 39, - MONITOR_REQ_RSARESPONSE = 40, MONITOR_ANS_RSARESPONSE = 41, MONITOR_REQ_GSSSETUP = 42, MONITOR_ANS_GSSSETUP = 43, MONITOR_REQ_GSSSTEP = 44, MONITOR_ANS_GSSSTEP = 45, MONITOR_REQ_GSSUSEROK = 46, MONITOR_ANS_GSSUSEROK = 47, MONITOR_REQ_GSSCHECKMIC = 48, MONITOR_ANS_GSSCHECKMIC = 49, MONITOR_REQ_TERM = 50, - MONITOR_REQ_PAM_START = 100, MONITOR_REQ_PAM_ACCOUNT = 102, MONITOR_ANS_PAM_ACCOUNT = 103, MONITOR_REQ_PAM_INIT_CTX = 104, MONITOR_ANS_PAM_INIT_CTX = 105, @@ -83,13 +78,12 @@ void monitor_child_preauth(struct ssh *, struct monitor *); void monitor_child_postauth(struct ssh *, struct monitor *); -void monitor_clear_keystate(struct ssh *, struct monitor *); -void monitor_apply_keystate(struct ssh *, struct monitor *); +void monitor_clear_keystate(struct ssh *); +void monitor_apply_keystate(struct ssh *); /* Prototypes for request sending and receiving */ void mm_request_send(int, enum monitor_reqtype, struct sshbuf *); void mm_request_receive(int, struct sshbuf *); void mm_request_receive_expect(int, enum monitor_reqtype, struct sshbuf *); -void mm_get_keystate(struct ssh *, struct monitor *); #endif /* _MONITOR_H_ */ diff -ruN openssh-9.4p1/monitor_wrap.c openssh-9.4p1+x509-14.2.1/monitor_wrap.c --- openssh-9.4p1/monitor_wrap.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/monitor_wrap.c 2023-08-20 10:07:01.000000000 +0300 @@ -4,6 +4,8 @@ * Copyright 2002 Markus Friedl * All rights reserved. * + * Copyright (c) 2007-2022 Roumen Petrov. All rights reserved. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -47,11 +49,7 @@ #include "openbsd-compat/sys-queue.h" #include "xmalloc.h" #include "ssh.h" -#ifdef WITH_OPENSSL -#include "dh.h" -#endif -#include "sshbuf.h" -#include "sshkey.h" +#include "ssh-x509.h" #include "cipher.h" #include "kex.h" #include "hostfile.h" @@ -82,7 +80,7 @@ extern ServerOptions options; void -mm_log_handler(LogLevel level, int forced, const char *msg, void *ctx) +mm_log_handler(LogLevel level, const char *msg, void *ctx) { struct sshbuf *log_msg; struct monitor *mon = (struct monitor *)ctx; @@ -97,7 +95,6 @@ if ((r = sshbuf_put_u32(log_msg, 0)) != 0 || /* length; filled below */ (r = sshbuf_put_u32(log_msg, level)) != 0 || - (r = sshbuf_put_u32(log_msg, forced)) != 0 || (r = sshbuf_put_cstring(log_msg, msg)) != 0) fatal_fr(r, "assemble"); if ((len = sshbuf_len(log_msg)) < 4 || len > 0xffffffff) @@ -177,10 +174,9 @@ } #ifdef WITH_OPENSSL -DH * -mm_choose_dh(int min, int nbits, int max) +EVP_PKEY* +mm_kex_new_dh_group_bits(int min, int nbits, int max) { - BIGNUM *p, *g; int r; u_char success = 0; struct sshbuf *m; @@ -202,6 +198,8 @@ if (success == 0) fatal_f("MONITOR_ANS_MODULI failed"); +{ BIGNUM *p, *g; + if ((r = sshbuf_get_bignum2(m, &p)) != 0 || (r = sshbuf_get_bignum2(m, &g)) != 0) fatal_fr(r, "parse group"); @@ -209,15 +207,17 @@ debug3_f("remaining %zu", sshbuf_len(m)); sshbuf_free(m); - return (dh_new_group(g, p)); + return kex_new_dh_group(p, g); +} } #endif int -mm_sshkey_sign(struct ssh *ssh, struct sshkey *key, u_char **sigp, size_t *lenp, - const u_char *data, size_t datalen, const char *hostkey_alg, - const char *sk_provider, const char *sk_pin, u_int compat) -{ +mm_Xkey_sign(struct ssh *ssh, ssh_sign_ctx *ctx, u_char **sigp, size_t *lenp, + const u_char *data, size_t datalen +) { + const char *hostkey_alg = ctx->alg; + struct sshkey *key = ctx->key; struct kex *kex = *pmonitor->m_pkex; struct sshbuf *m; u_int ndx = kex->host_key_index(key, 0, ssh); @@ -229,7 +229,7 @@ if ((r = sshbuf_put_u32(m, ndx)) != 0 || (r = sshbuf_put_string(m, data, datalen)) != 0 || (r = sshbuf_put_cstring(m, hostkey_alg)) != 0 || - (r = sshbuf_put_u32(m, compat)) != 0) + (r = sshbuf_put_compat(m, ctx->compat)) != 0) fatal_fr(r, "assemble"); mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_SIGN, m); @@ -248,7 +248,7 @@ if ((r = sshbuf_get_string_direct(b, &p, &len)) != 0) \ fatal_fr(r, "parse pw %s", #id); \ if (len != sizeof(pw->id)) \ - fatal_fr(r, "bad length for %s", #id); \ + fatal_f("bad length for %s", #id); \ memcpy(&pw->id, p, len); \ } while (0) @@ -283,7 +283,6 @@ goto out; } - /* XXX don't like passing struct passwd like this */ pw = xcalloc(sizeof(*pw), 1); GETPW(m, pw_uid); GETPW(m, pw_gid); @@ -314,6 +313,22 @@ newopts = xcalloc(sizeof(*newopts), 1); memcpy(newopts, p, sizeof(*newopts)); + r = sshbuf_get_cstring(m, &newopts->hostbased_algorithms, NULL); + if (r != 0) + fatal_fr(r, "parse hostbased_algorithms"); + if (*newopts->hostbased_algorithms == '\0') { + free(newopts->hostbased_algorithms); + newopts->hostbased_algorithms = xstrdup("*"); + } + + r = sshbuf_get_cstring(m, &newopts->pubkey_algorithms, NULL); + if (r != 0) + fatal_fr(r, "parse pubkey_algorithms"); + if (*newopts->pubkey_algorithms == '\0') { + free(newopts->pubkey_algorithms); + newopts->pubkey_algorithms = xstrdup("*"); + } + #define M_CP_STROPT(x) do { \ if (newopts->x != NULL && \ (r = sshbuf_get_cstring(m, &newopts->x, NULL)) != 0) \ @@ -330,14 +345,13 @@ } while (0) /* See comment in servconf.h */ COPY_MATCH_STRING_OPTS(); + #undef M_CP_STROPT #undef M_CP_STRARRAYOPT copy_set_server_options(&options, newopts, 1); log_change_level(options.log_level); - log_verbose_reset(); - for (i = 0; i < options.num_log_verbose; i++) - log_verbose_add(options.log_verbose[i]); + log_verbose_init(options.log_verbose, options.num_log_verbose); process_permitopen(ssh, &options); process_channel_timeouts(ssh, &options); free(newopts); @@ -403,9 +417,11 @@ struct sshbuf *m; int r, authenticated = 0; #ifdef USE_PAM - u_int maxtries = 0; + int maxtries = 0; #endif + u_int32_t val; + UNUSED(ssh); debug3_f("entering"); if ((m = sshbuf_new()) == NULL) @@ -418,13 +434,15 @@ mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_AUTHPASSWORD, m); - if ((r = sshbuf_get_u32(m, &authenticated)) != 0) + if ((r = sshbuf_get_u32(m, &val)) != 0) /*authenticated*/ fatal_fr(r, "parse"); + authenticated = val; #ifdef USE_PAM - if ((r = sshbuf_get_u32(m, &maxtries)) != 0) + if ((r = sshbuf_get_u32(m, &val)) != 0) /*maxtries*/ fatal_fr(r, "parse PAM"); + maxtries = val; if (maxtries > INT_MAX) - fatal_fr(r, "bad maxtries"); + fatal_f("bad maxtries"); sshpam_set_maxtries_reached(maxtries); #endif @@ -434,40 +452,30 @@ return (authenticated); } -int -mm_user_key_allowed(struct ssh *ssh, struct passwd *pw, struct sshkey *key, - int pubkey_auth_attempt, struct sshauthopt **authoptp) -{ - return (mm_key_allowed(MM_USERKEY, NULL, NULL, key, - pubkey_auth_attempt, authoptp)); -} - -int -mm_hostbased_key_allowed(struct ssh *ssh, struct passwd *pw, - const char *user, const char *host, struct sshkey *key) -{ - return (mm_key_allowed(MM_HOSTKEY, user, host, key, 0, NULL)); -} - -int -mm_key_allowed(enum mm_keytype type, const char *user, const char *host, - struct sshkey *key, int pubkey_auth_attempt, struct sshauthopt **authoptp) +static int +mm_xkey_allowed(enum mm_keytype type, const char *user, const char *host, + ssh_verify_ctx *ctx, int pubkey_auth_attempt, struct sshauthopt **authoptp) { + const char *pkalg = ctx->alg; struct sshbuf *m; int r, allowed = 0; struct sshauthopt *opts = NULL; + u_int32_t val; debug3_f("entering"); if (authoptp != NULL) *authoptp = NULL; + if (pkalg == NULL) pkalg = sshkey_ssh_name(ctx->key); + if ((m = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); if ((r = sshbuf_put_u32(m, type)) != 0 || (r = sshbuf_put_cstring(m, user ? user : "")) != 0 || (r = sshbuf_put_cstring(m, host ? host : "")) != 0 || - (r = sshkey_puts(key, m)) != 0 || + (r = sshbuf_put_cstring(m, pkalg)) != 0 || + (r = Xkey_puts(pkalg, ctx->key, m)) != 0 || (r = sshbuf_put_u32(m, pubkey_auth_attempt)) != 0) fatal_fr(r, "assemble"); @@ -477,8 +485,9 @@ mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_KEYALLOWED, m); - if ((r = sshbuf_get_u32(m, &allowed)) != 0) + if ((r = sshbuf_get_u32(m, &val)) != 0) /*allowed*/ fatal_fr(r, "parse"); + allowed = val; if (allowed && type == MM_USERKEY && (r = sshauthopt_deserialise(m, &opts)) != 0) fatal_fr(r, "sshauthopt_deserialise"); @@ -493,6 +502,27 @@ return allowed; } +int +mm_user_xkey_allowed( + struct ssh *ssh, struct passwd *pw, ssh_verify_ctx *ctx, + int pubkey_auth_attempt, struct sshauthopt **authoptp +) { + UNUSED(ssh); + UNUSED(pw); + return (mm_xkey_allowed(MM_USERKEY, NULL, NULL, ctx, + pubkey_auth_attempt, authoptp)); +} + +int +mm_hostbased_xkey_allowed( + struct ssh *ssh, struct passwd *pw, ssh_verify_ctx *ctx, + const char *user, const char *host +) { + UNUSED(ssh); + UNUSED(pw); + return (mm_xkey_allowed(MM_HOSTKEY, user, host, ctx, 0, NULL)); +} + /* * This key verify needs to send the key type along, because the * privileged parent makes the decision if the key is allowed @@ -500,26 +530,26 @@ */ int -mm_sshkey_verify(const struct sshkey *key, const u_char *sig, size_t siglen, - const u_char *data, size_t datalen, const char *sigalg, u_int compat, - struct sshkey_sig_details **sig_detailsp) -{ +mm_Xkey_verify( + ssh_verify_ctx *ctx, + const u_char *sig, size_t siglen, + const u_char *data, size_t datalen +) { + const char *pkalg = ctx->alg; struct sshbuf *m; - u_int encoded_ret = 0; + u_int32_t encoded_ret = 0; int r; - u_char sig_details_present, flags; - u_int counter; debug3_f("entering"); - if (sig_detailsp != NULL) - *sig_detailsp = NULL; + if (pkalg == NULL) pkalg = sshkey_ssh_name(ctx->key); + if ((m = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); - if ((r = sshkey_puts(key, m)) != 0 || + if ((r = sshbuf_put_cstring(m, pkalg)) != 0 || + (r = Xkey_puts(pkalg, ctx->key, m)) != 0 || (r = sshbuf_put_string(m, sig, siglen)) != 0 || - (r = sshbuf_put_string(m, data, datalen)) != 0 || - (r = sshbuf_put_cstring(m, sigalg == NULL ? "" : sigalg)) != 0) + (r = sshbuf_put_string(m, data, datalen)) != 0) fatal_fr(r, "assemble"); mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_KEYVERIFY, m); @@ -528,19 +558,8 @@ mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_KEYVERIFY, m); - if ((r = sshbuf_get_u32(m, &encoded_ret)) != 0 || - (r = sshbuf_get_u8(m, &sig_details_present)) != 0) + if ((r = sshbuf_get_u32(m, &encoded_ret)) != 0) fatal_fr(r, "parse"); - if (sig_details_present && encoded_ret == 0) { - if ((r = sshbuf_get_u32(m, &counter)) != 0 || - (r = sshbuf_get_u8(m, &flags)) != 0) - fatal_fr(r, "parse sig_details"); - if (sig_detailsp != NULL) { - *sig_detailsp = xcalloc(1, sizeof(**sig_detailsp)); - (*sig_detailsp)->sk_counter = counter; - (*sig_detailsp)->sk_flags = flags; - } - } sshbuf_free(m); @@ -560,7 +579,7 @@ if ((r = ssh_packet_get_state(ssh, m)) != 0) fatal_fr(r, "ssh_packet_get_state"); mm_request_send(monitor->m_recvfd, MONITOR_REQ_KEYEXPORT, m); - debug3_f("Finished sending state"); + debug3_f("finished sending state"); sshbuf_free(m); } @@ -569,7 +588,8 @@ { struct sshbuf *m; char *p, *msg; - int success = 0, tmp1 = -1, tmp2 = -1, r; + int tmp1 = -1, tmp2 = -1, r; + u_int32_t success = 0; /* Kludge: ensure there are fds free to receive the pty/tty */ if ((tmp1 = dup(pmonitor->m_recvfd)) == -1 || @@ -627,7 +647,7 @@ if ((m = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); if ((r = sshbuf_put_cstring(m, s->tty)) != 0) - fatal_fr(r, "assmble"); + fatal_fr(r, "assemble"); mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PTYCLEANUP, m); sshbuf_free(m); @@ -646,11 +666,12 @@ { struct sshbuf *m; - debug3("%s entering", __func__); + UNUSED(ssh); + debug3_f("entering"); if (!options.use_pam) fatal("UsePAM=no, but ended up in %s anyway", __func__); if ((m = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new failed", __func__); + fatal_f("sshbuf_new failed"); mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_START, m); sshbuf_free(m); @@ -660,17 +681,17 @@ mm_do_pam_account(void) { struct sshbuf *m; - u_int ret; + u_int32_t ret; char *msg; size_t msglen; int r; - debug3("%s entering", __func__); + debug3_f("entering"); if (!options.use_pam) fatal("UsePAM=no, but ended up in %s anyway", __func__); if ((m = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new failed", __func__); + fatal_f("sshbuf_new failed"); mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_ACCOUNT, m); mm_request_receive_expect(pmonitor->m_recvfd, @@ -678,12 +699,12 @@ if ((r = sshbuf_get_u32(m, &ret)) != 0 || (r = sshbuf_get_cstring(m, &msg, &msglen)) != 0 || (r = sshbuf_put(loginmsg, msg, msglen)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "assemble message"); free(msg); sshbuf_free(m); - debug3("%s returning %d", __func__, ret); + debug3_f("returning %d", ret); return (ret); } @@ -692,19 +713,20 @@ mm_sshpam_init_ctx(Authctxt *authctxt) { struct sshbuf *m; - int r, success; + u_int32_t success; + int r; - debug3("%s", __func__); + debug3_f("entering"); if ((m = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new failed", __func__); + fatal_f("sshbuf_new failed"); mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_INIT_CTX, m); - debug3("%s: waiting for MONITOR_ANS_PAM_INIT_CTX", __func__); + debug3_f("waiting for MONITOR_ANS_PAM_INIT_CTX"); mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PAM_INIT_CTX, m); if ((r = sshbuf_get_u32(m, &success)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "parse"); if (success == 0) { - debug3("%s: pam_init_ctx failed", __func__); + debug3_f("pam_init_ctx failed"); sshbuf_free(m); return (NULL); } @@ -717,32 +739,36 @@ u_int *num, char ***prompts, u_int **echo_on) { struct sshbuf *m; - u_int i, n; - int r, ret; + u_int i; + u_int32_t ret, n, val; + int r; - debug3("%s", __func__); + UNUSED(ctx); + debug3_f("entering"); if ((m = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new failed", __func__); + fatal_f("sshbuf_new failed"); mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_QUERY, m); - debug3("%s: waiting for MONITOR_ANS_PAM_QUERY", __func__); + debug3_f("waiting for MONITOR_ANS_PAM_QUERY"); mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PAM_QUERY, m); if ((r = sshbuf_get_u32(m, &ret)) != 0 || (r = sshbuf_get_cstring(m, name, NULL)) != 0 || (r = sshbuf_get_cstring(m, info, NULL)) != 0 || (r = sshbuf_get_u32(m, &n)) != 0 || - (r = sshbuf_get_u32(m, num)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); - debug3("%s: pam_query returned %d", __func__, ret); + (r = sshbuf_get_u32(m, &val)) != 0) /*num*/ + fatal_fr(r, "parse"); + *num = val; + debug3_f("pam_query returned %d", (int)ret); sshpam_set_maxtries_reached(n); if (*num > PAM_MAX_NUM_MSG) - fatal("%s: received %u PAM messages, expected <= %u", - __func__, *num, PAM_MAX_NUM_MSG); + fatal_f("received %u PAM messages, expected <= %u", + *num, PAM_MAX_NUM_MSG); *prompts = xcalloc((*num + 1), sizeof(char *)); *echo_on = xcalloc((*num + 1), sizeof(u_int)); for (i = 0; i < *num; ++i) { if ((r = sshbuf_get_cstring(m, &((*prompts)[i]), NULL)) != 0 || - (r = sshbuf_get_u32(m, &((*echo_on)[i]))) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + (r = sshbuf_get_u32(m, &val)) != 0) /*echo_on*/ + fatal_fr(r, "parse prompt %u", i); + (*echo_on)[i] = val; } sshbuf_free(m); return (ret); @@ -752,26 +778,28 @@ mm_sshpam_respond(void *ctx, u_int num, char **resp) { struct sshbuf *m; - u_int n, i; + u_int i; + u_int32_t n; int r, ret; - debug3("%s", __func__); + UNUSED(ctx); + debug3_f("entering"); if ((m = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new failed", __func__); + fatal_f("sshbuf_new failed"); if ((r = sshbuf_put_u32(m, num)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "assemble"); for (i = 0; i < num; ++i) { if ((r = sshbuf_put_cstring(m, resp[i])) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "assemble respond %u", i); } mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_RESPOND, m); - debug3("%s: waiting for MONITOR_ANS_PAM_RESPOND", __func__); + debug3_f("waiting for MONITOR_ANS_PAM_RESPOND"); mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PAM_RESPOND, m); if ((r = sshbuf_get_u32(m, &n)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "parse"); ret = (int)n; /* XXX */ - debug3("%s: pam_respond returned %d", __func__, ret); + debug3_f("pam_respond returned %d", ret); sshbuf_free(m); return (ret); } @@ -781,11 +809,12 @@ { struct sshbuf *m; - debug3("%s", __func__); + UNUSED(ctxtp); + debug3_f("entering"); if ((m = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new failed", __func__); + fatal_f("sshbuf_new failed"); mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_FREE_CTX, m); - debug3("%s: waiting for MONITOR_ANS_PAM_FREE_CTX", __func__); + debug3_f("waiting for MONITOR_ANS_PAM_FREE_CTX"); mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PAM_FREE_CTX, m); sshbuf_free(m); @@ -822,10 +851,11 @@ u_int *numprompts, char ***prompts, u_int **echo_on) { struct sshbuf *m; - u_int success; + u_int32_t success; char *challenge; int r; + UNUSED(ctx); debug3_f("entering"); if ((m = sshbuf_new()) == NULL) @@ -859,8 +889,10 @@ mm_bsdauth_respond(void *ctx, u_int numresponses, char **responses) { struct sshbuf *m; - int r, authok; + u_int32_t authok; + int r; + UNUSED(ctx); debug3_f("entering"); if (numresponses != 1) return (-1); @@ -888,12 +920,13 @@ struct sshbuf *m; int r; - debug3("%s entering", __func__); + UNUSED(ssh); + debug3_f("entering"); if ((m = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new failed", __func__); + fatal_f("sshbuf_new failed"); if ((r = sshbuf_put_u32(m, event)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "assemble"); mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUDIT_EVENT, m); sshbuf_free(m); @@ -905,12 +938,12 @@ struct sshbuf *m; int r; - debug3("%s entering command %s", __func__, command); + debug3_f("entering command %s", command); if ((m = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new failed", __func__); + fatal_f("sshbuf_new failed"); if ((r = sshbuf_put_cstring(m, command)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "assemble"); mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUDIT_COMMAND, m); sshbuf_free(m); @@ -922,7 +955,7 @@ mm_ssh_gssapi_server_ctx(Gssctxt **ctx, gss_OID goid) { struct sshbuf *m; - OM_uint32 major; + u_int32_t major; int r; /* Client doesn't get to see the context */ @@ -948,10 +981,10 @@ gss_buffer_desc *out, OM_uint32 *flagsp) { struct sshbuf *m; - OM_uint32 major; - u_int flags; + u_int32_t major, flags; int r; + UNUSED(ctx); if ((m = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); if ((r = sshbuf_put_string(m, in->value, in->length)) != 0) @@ -978,9 +1011,10 @@ mm_ssh_gssapi_checkmic(Gssctxt *ctx, gss_buffer_t gssbuf, gss_buffer_t gssmic) { struct sshbuf *m; - OM_uint32 major; + u_int32_t major; int r; + UNUSED(ctx); if ((m = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); if ((r = sshbuf_put_string(m, gssbuf->value, gssbuf->length)) != 0 || @@ -1001,8 +1035,10 @@ mm_ssh_gssapi_userok(char *user) { struct sshbuf *m; - int r, authenticated = 0; + u_int32_t authenticated = 0; + int r; + UNUSED(user); if ((m = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); diff -ruN openssh-9.4p1/monitor_wrap.h openssh-9.4p1+x509-14.2.1/monitor_wrap.h --- openssh-9.4p1/monitor_wrap.h 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/monitor_wrap.h 2023-08-20 10:07:00.000000000 +0300 @@ -1,9 +1,12 @@ +#ifndef _MM_WRAP_H_ +#define _MM_WRAP_H_ /* $OpenBSD: monitor_wrap.h,v 1.49 2022/06/15 16:08:25 djm Exp $ */ - /* * Copyright 2002 Niels Provos * All rights reserved. * + * Copyright (c) 2017-2022 Roumen Petrov. All rights reserved. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -25,8 +28,12 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef _MM_WRAP_H_ -#define _MM_WRAP_H_ +#include "includes.h" + +#include "evp-compat.h" +#ifdef GSSAPI +#include "ssh-gss.h" +#endif extern int use_privsep; #define PRIVSEP(x) (use_privsep ? mm_##x : x) @@ -38,28 +45,23 @@ struct Authctxt; struct sshkey; struct sshauthopt; -struct sshkey_sig_details; -void mm_log_handler(LogLevel, int, const char *, void *); +void mm_log_handler(LogLevel level, const char *msg, void *ctx); int mm_is_monitor(void); -#ifdef WITH_OPENSSL -DH *mm_choose_dh(int, int, int); -#endif -int mm_sshkey_sign(struct ssh *, struct sshkey *, u_char **, size_t *, - const u_char *, size_t, const char *, const char *, - const char *, u_int compat); +EVP_PKEY* mm_kex_new_dh_group_bits(int, int, int); +int mm_Xkey_sign(struct ssh *ssh, ssh_sign_ctx *ctx, u_char **sigp, size_t *lenp, + const u_char *data, size_t datalen); void mm_inform_authserv(char *, char *); struct passwd *mm_getpwnamallow(struct ssh *, const char *); char *mm_auth2_read_banner(void); int mm_auth_password(struct ssh *, char *); -int mm_key_allowed(enum mm_keytype, const char *, const char *, struct sshkey *, - int, struct sshauthopt **); -int mm_user_key_allowed(struct ssh *ssh, struct passwd *, struct sshkey *, int, - struct sshauthopt **); -int mm_hostbased_key_allowed(struct ssh *, struct passwd *, const char *, - const char *, struct sshkey *); -int mm_sshkey_verify(const struct sshkey *, const u_char *, size_t, - const u_char *, size_t, const char *, u_int, struct sshkey_sig_details **); +int mm_user_xkey_allowed(struct ssh *, struct passwd *, ssh_verify_ctx *, int, + struct sshauthopt **); +int mm_hostbased_xkey_allowed(struct ssh *, struct passwd *, + ssh_verify_ctx *, const char *, const char *); +int mm_Xkey_verify(ssh_verify_ctx *ctx, + const u_char *sig, size_t siglen, + const u_char *data, size_t datalen); #ifdef GSSAPI OM_uint32 mm_ssh_gssapi_server_ctx(Gssctxt **, gss_OID); diff -ruN openssh-9.4p1/msg.c openssh-9.4p1+x509-14.2.1/msg.c --- openssh-9.4p1/msg.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/msg.c 2023-08-20 10:07:01.000000000 +0300 @@ -35,7 +35,6 @@ #include #include "sshbuf.h" -#include "ssherr.h" #include "log.h" #include "atomicio.h" #include "msg.h" @@ -66,10 +65,10 @@ ssh_msg_recv(int fd, struct sshbuf *m) { u_char buf[4], *p; - u_int msg_len; + size_t msg_len; int r; - debug3("ssh_msg_recv entering"); + debug3_f("entering"); if (atomicio(read, fd, buf, sizeof(buf)) != sizeof(buf)) { if (errno != EPIPE) @@ -78,7 +77,7 @@ } msg_len = get_u32(buf); if (msg_len > sshbuf_max_size(m)) { - error_f("read: bad msg_len %u", msg_len); + error_f("read: bad msg_len %zu", msg_len); return (-1); } sshbuf_reset(m); diff -ruN openssh-9.4p1/mux.c openssh-9.4p1+x509-14.2.1/mux.c --- openssh-9.4p1/mux.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/mux.c 2023-08-20 10:07:01.000000000 +0300 @@ -1,6 +1,7 @@ -/* $OpenBSD: mux.c,v 1.99 2023/08/04 06:32:40 dtucker Exp $ */ +/* $OpenBSD: mux.c,v 1.100 2023/08/18 01:37:41 djm Exp $ */ /* * Copyright (c) 2002-2008 Damien Miller + * Copyright (c) 2018-2023 Roumen Petrov. All rights reserved. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -39,7 +40,7 @@ #endif #ifdef HAVE_POLL_H -#include +# include #else # ifdef HAVE_SYS_POLL_H # include @@ -64,11 +65,8 @@ #include "packet.h" #include "monitor_fdpass.h" #include "sshpty.h" -#include "sshkey.h" #include "readconf.h" #include "clientloop.h" -#include "ssherr.h" -#include "misc.h" /* from ssh.c */ extern int tty_flag; @@ -189,13 +187,15 @@ /* Cleanup callback fired on closure of mux client _session_ channel */ static void -mux_master_session_cleanup_cb(struct ssh *ssh, int cid, int force, void *unused) +mux_master_session_cleanup_cb(struct ssh *ssh, int cid, int force, void *arg) { Channel *cc, *c = channel_by_id(ssh, cid); + UNUSED(force); + UNUSED(arg); debug3_f("entering for channel %d", cid); if (c == NULL) - fatal_f("channel_by_id(%i) == NULL", cid); + fatal_f("channel_by_id(%d) == NULL", cid); if (c->ctl_chan != -1) { if ((cc = channel_by_id(ssh, c->ctl_chan)) == NULL) fatal_f("channel %d missing control channel %d", @@ -210,13 +210,15 @@ /* Cleanup callback fired on closure of mux client _control_ channel */ static void -mux_master_control_cleanup_cb(struct ssh *ssh, int cid, int force, void *unused) +mux_master_control_cleanup_cb(struct ssh *ssh, int cid, int force, void *arg) { Channel *sc, *c = channel_by_id(ssh, cid); + UNUSED(force); + UNUSED(arg); debug3_f("entering for channel %d", cid); if (c == NULL) - fatal_f("channel_by_id(%i) == NULL", cid); + fatal_f("channel_by_id(%d) == NULL", cid); if (c->have_remote_id) { if ((sc = channel_by_id(ssh, c->remote_id)) == NULL) fatal_f("channel %d missing session channel %u", @@ -243,7 +245,7 @@ env_permitted(const char *env) { u_int i; - int ret; + int matched, ret; char name[1024], *cp; if ((cp = strchr(env, '=')) == NULL || cp == env) @@ -254,11 +256,12 @@ return 0; } - for (i = 0; i < options.num_send_env; i++) - if (match_pattern(name, options.send_env[i])) - return 1; - - return 0; + matched = 0; + for (i = 0; i < options.num_send_env; i++) { + matched = match_pattern_list(name, options.send_env[i], 0); + if (matched != 0) break; + } + return matched == 1; } /* Mux master protocol message handlers */ @@ -267,10 +270,13 @@ mux_master_process_hello(struct ssh *ssh, u_int rid, Channel *c, struct sshbuf *m, struct sshbuf *reply) { - u_int ver; + u_int32_t ver; struct mux_master_state *state = (struct mux_master_state *)c->mux_ctx; int r; + UNUSED(ssh); + UNUSED(rid); + UNUSED(reply); if (state == NULL) fatal_f("channel %d: c->mux_ctx == NULL", c->self); if (state->hello_rcvd) { @@ -283,10 +289,10 @@ } if (ver != SSHMUX_VER) { error_f("unsupported multiplexing protocol version %u " - "(expected %u)", ver, SSHMUX_VER); + "(expected %u)", (int)ver, SSHMUX_VER); return -1; } - debug2_f("channel %d client version %u", c->self, ver); + debug2_f("channel %d client version %u", c->self, (unsigned)ver); /* No extensions are presently defined */ while (sshbuf_len(m) > 0) { @@ -296,9 +302,10 @@ if ((r = sshbuf_get_cstring(m, &name, NULL)) != 0 || (r = sshbuf_get_string_direct(m, NULL, &value_len)) != 0) { error_fr(r, "parse extension"); + free(name); return -1; } - debug2_f("Unrecognised extension \"%s\" length %zu", + debug2_f("unrecognised extension \"%s\" length %zu", name, value_len); free(name); } @@ -473,8 +480,7 @@ client_new_escape_filter_ctx((int)escape_char)); } - debug2_f("channel_new: %d linked to control channel %d", - nc->self, nc->ctl_chan); + debug2_f("channel %d, control %d", nc->self, nc->ctl_chan); channel_send_open(ssh, nc->self); channel_register_open_confirm(ssh, nc->self, mux_session_confirm, cctx); @@ -492,6 +498,8 @@ { int r; + UNUSED(ssh); + UNUSED(m); debug2_f("channel %d: alive check", c->self); /* prepare reply */ @@ -507,6 +515,8 @@ mux_master_process_terminate(struct ssh *ssh, u_int rid, Channel *c, struct sshbuf *m, struct sshbuf *reply) { + UNUSED(ssh); + UNUSED(m); debug2_f("channel %d: terminate request", c->self); if (options.control_master == SSHCTL_MASTER_ASK || @@ -599,9 +609,9 @@ struct Forward *rfwd; Channel *c; struct sshbuf *out; - u_int port; int r; + UNUSED(seq); if ((c = channel_by_id(ssh, fctx->cid)) == NULL) { /* no channel for reply */ error_f("unknown channel"); @@ -622,11 +632,12 @@ rfwd->connect_host, rfwd->connect_port); if (type == SSH2_MSG_REQUEST_SUCCESS) { if (rfwd->listen_port == 0) { + u_int32_t port; if ((r = sshpkt_get_u32(ssh, &port)) != 0) fatal_fr(r, "parse port"); if (port > 65535) { fatal("Invalid allocated port %u for " - "mux remote forward to %s:%d", port, + "mux remote forward to %s:%d", (unsigned)port, rfwd->connect_host, rfwd->connect_port); } rfwd->allocated_port = (int)port; @@ -686,8 +697,7 @@ struct Forward fwd; char *fwd_desc = NULL; char *listen_addr, *connect_addr; - u_int ftype; - u_int lport, cport; + u_int32_t ftype, lport, cport; int r, i, ret = 0, freefwd = 1; memset(&fwd, 0, sizeof(fwd)); @@ -698,8 +708,8 @@ (r = sshbuf_get_u32(m, &lport)) != 0 || (r = sshbuf_get_cstring(m, &connect_addr, NULL)) != 0 || (r = sshbuf_get_u32(m, &cport)) != 0 || - (lport != (u_int)PORT_STREAMLOCAL && lport > 65535) || - (cport != (u_int)PORT_STREAMLOCAL && cport > 65535)) { + (lport != (u_int32_t)PORT_STREAMLOCAL && lport > 65535) || + (cport != (u_int32_t)PORT_STREAMLOCAL && cport > 65535)) { error_f("malformed message"); ret = -1; goto out; @@ -713,7 +723,6 @@ connect_addr = NULL; } - memset(&fwd, 0, sizeof(fwd)); fwd.listen_port = lport; if (fwd.listen_port == PORT_STREAMLOCAL) fwd.listen_path = listen_addr; @@ -730,7 +739,7 @@ if (ftype != MUX_FWD_LOCAL && ftype != MUX_FWD_REMOTE && ftype != MUX_FWD_DYNAMIC) { - logit_f("invalid forwarding type %u", ftype); + error_f("invalid forwarding type %u", (unsigned)ftype); invalid: free(listen_addr); free(connect_addr); @@ -739,25 +748,24 @@ return 0; } if (ftype == MUX_FWD_DYNAMIC && fwd.listen_path) { - logit_f("streamlocal and dynamic forwards " + error_f("streamlocal and dynamic forwards " "are mutually exclusive"); goto invalid; } if (fwd.listen_port != PORT_STREAMLOCAL && fwd.listen_port >= 65536) { - logit_f("invalid listen port %u", fwd.listen_port); + error_f("invalid listen port %u", fwd.listen_port); goto invalid; } if ((fwd.connect_port != PORT_STREAMLOCAL && fwd.connect_port >= 65536) || (ftype != MUX_FWD_DYNAMIC && ftype != MUX_FWD_REMOTE && fwd.connect_port == 0)) { - logit_f("invalid connect port %u", - fwd.connect_port); + error_f("invalid connect port %u", fwd.connect_port); goto invalid; } if (ftype != MUX_FWD_DYNAMIC && fwd.connect_host == NULL && fwd.connect_path == NULL) { - logit_f("missing connect host"); + error_f("missing connect host"); goto invalid; } @@ -807,7 +815,7 @@ if (!channel_setup_local_fwd_listener(ssh, &fwd, &options.fwd_opts)) { fail: - logit_f("requested %s failed", fwd_desc); + error_f("requested %s failed", fwd_desc); reply_error(reply, MUX_S_FAILURE, rid, "Port forwarding failed"); goto out; @@ -852,9 +860,8 @@ char *fwd_desc = NULL; const char *error_reason = NULL; char *listen_addr = NULL, *connect_addr = NULL; - u_int ftype; + u_int32_t ftype, lport, cport; int r, i, ret = 0; - u_int lport, cport; memset(&fwd, 0, sizeof(fwd)); @@ -863,8 +870,8 @@ (r = sshbuf_get_u32(m, &lport)) != 0 || (r = sshbuf_get_cstring(m, &connect_addr, NULL)) != 0 || (r = sshbuf_get_u32(m, &cport)) != 0 || - (lport != (u_int)PORT_STREAMLOCAL && lport > 65535) || - (cport != (u_int)PORT_STREAMLOCAL && cport > 65535)) { + (lport != (u_int32_t)PORT_STREAMLOCAL && lport > 65535) || + (cport != (u_int32_t)PORT_STREAMLOCAL && cport > 65535)) { error_f("malformed message"); ret = -1; goto out; @@ -879,7 +886,6 @@ connect_addr = NULL; } - memset(&fwd, 0, sizeof(fwd)); fwd.listen_port = lport; if (fwd.listen_port == PORT_STREAMLOCAL) fwd.listen_path = listen_addr; @@ -962,8 +968,9 @@ { Channel *nc; char *chost = NULL; - u_int _cport, i, j; - int ok = 0, cport, r, new_fd[2]; + u_int32_t _cport; + u_int i, j; + int cport, r, new_fd[2]; struct mux_stdio_confirm_ctx *cctx; if ((r = sshbuf_skip_string(m)) != 0 || /* reserved */ @@ -1016,6 +1023,7 @@ if (options.control_master == SSHCTL_MASTER_ASK || options.control_master == SSHCTL_MASTER_AUTO_ASK) { + int ok; if (cport == PORT_STREAMLOCAL) { ok = ask_permission("Allow forward to path %s", chost); } else { @@ -1038,7 +1046,7 @@ c->remote_id = nc->self; /* link control -> session channel */ c->have_remote_id = 1; - debug2_f("channel_new: %d control %d", nc->self, nc->ctl_chan); + debug2_f("channel %d, control %d", nc->self, nc->ctl_chan); channel_register_cleanup(ssh, nc->self, mux_master_session_cleanup_cb, 1); @@ -1103,6 +1111,7 @@ mux_master_process_stop_listening(struct ssh *ssh, u_int rid, Channel *c, struct sshbuf *m, struct sshbuf *reply) { + UNUSED(m); debug_f("channel %d: stop listening", c->self); if (options.control_master == SSHCTL_MASTER_ASK || @@ -1135,6 +1144,8 @@ { int r; + UNUSED(ssh); + UNUSED(m); debug_f("channel %d: proxy request", c->self); c->mux_rcb = channel_proxy_downstream; @@ -1151,7 +1162,8 @@ { struct mux_master_state *state = (struct mux_master_state *)c->mux_ctx; struct sshbuf *in = NULL, *out = NULL; - u_int type, rid, i; + u_int32_t type, rid; + u_int i; int r, ret = -1; if ((out = sshbuf_new()) == NULL) @@ -1193,7 +1205,7 @@ else { if (!state->hello_rcvd) { error_f("expected MUX_MSG_HELLO(0x%08x), " - "received 0x%08x", MUX_MSG_HELLO, type); + "received 0x%08x", MUX_MSG_HELLO, (unsigned)type); goto out; } if ((r = sshbuf_get_u32(in, &rid)) != 0) @@ -1208,7 +1220,7 @@ } } if (mux_master_handlers[i].handler == NULL) { - error_f("unsupported mux message 0x%08x", type); + error_f("unsupported mux message 0x%08x", (unsigned)type); reply_error(out, MUX_S_FAILURE, rid, "unsupported request"); ret = 0; } @@ -1323,9 +1335,7 @@ cleanup_exit(255); } } - - /* Now atomically "move" the mux socket into position */ - if (link(options.control_path, orig_control_path) != 0) { + if (xrename(options.control_path, orig_control_path) == -1) { if (errno != EEXIST) { fatal_f("link mux listener %s => %s: %s", options.control_path, orig_control_path, @@ -1336,7 +1346,6 @@ unlink(options.control_path); goto disable_mux_master; } - unlink(options.control_path); free(options.control_path); options.control_path = orig_control_path; @@ -1345,7 +1354,7 @@ mux_listener_channel = channel_new(ssh, "mux listener", SSH_CHANNEL_MUX_LISTENER, muxserver_sock, muxserver_sock, -1, CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, - 0, options.control_path, 1); + 0, options.control_path, CHANNEL_NONBLOCK_SET); mux_listener_channel->mux_rcb = mux_master_read_cb; debug3_f("mux listener channel %d fd %d", mux_listener_channel->self, mux_listener_channel->sock); @@ -1480,7 +1489,9 @@ case EWOULDBLOCK: #endif case EAGAIN: - if (waitrfd(fd, &timeout_ms) == -1) + if (waitrfd(fd, &timeout_ms, + &muxclient_terminate) == -1 && + errno != EINTR) return -1; /* timeout */ /* FALLTHROUGH */ case EINTR: @@ -1595,7 +1606,7 @@ mux_client_hello_exchange(int fd, int timeout_ms) { struct sshbuf *m; - u_int type, ver; + u_int32_t type, ver; int r, ret = -1; if ((m = sshbuf_new()) == NULL) @@ -1621,17 +1632,17 @@ if ((r = sshbuf_get_u32(m, &type)) != 0) fatal_fr(r, "parse type"); if (type != MUX_MSG_HELLO) { - error_f("expected HELLO (%u) got %u", MUX_MSG_HELLO, type); + error_f("expected HELLO (%u) got %u", MUX_MSG_HELLO, (unsigned)type); goto out; } if ((r = sshbuf_get_u32(m, &ver)) != 0) fatal_fr(r, "parse version"); if (ver != SSHMUX_VER) { error("Unsupported multiplexing protocol version %d " - "(expected %d)", ver, SSHMUX_VER); + "(expected %d)", (int)ver, SSHMUX_VER); goto out; } - debug2_f("master version %u", ver); + debug2_f("master version %u", (unsigned)ver); /* No extensions are presently defined */ while (sshbuf_len(m) > 0) { char *name = NULL; @@ -1641,7 +1652,7 @@ error_fr(r, "parse extension"); goto out; } - debug2("Unrecognised master extension \"%s\"", name); + debug2_f("unrecognised master extension \"%s\"", name); free(name); } /* success */ @@ -1656,7 +1667,7 @@ { struct sshbuf *m; char *e; - u_int pid, type, rid; + u_int32_t pid, type, rid; int r; debug3_f("entering"); @@ -1690,12 +1701,12 @@ fatal_fr(r, "parse remote ID"); if (rid != muxclient_request_id) fatal_f("out of sequence reply: my id %u theirs %u", - muxclient_request_id, rid); + muxclient_request_id, (unsigned)rid); if ((r = sshbuf_get_u32(m, &pid)) != 0) fatal_fr(r, "parse PID"); sshbuf_free(m); - debug3_f("done pid = %u", pid); + debug3_f("done pid = %u", (unsigned)pid); muxclient_request_id++; @@ -1707,7 +1718,7 @@ { struct sshbuf *m; char *e; - u_int type, rid; + u_int32_t type, rid; int r; debug3_f("entering"); @@ -1738,7 +1749,7 @@ fatal_fr(r, "parse"); if (rid != muxclient_request_id) fatal_f("out of sequence reply: my id %u theirs %u", - muxclient_request_id, rid); + muxclient_request_id, (unsigned)rid); switch (type) { case MUX_S_OK: break; @@ -1751,7 +1762,7 @@ fatal_fr(r, "parse error message"); fatal_f("termination request failed: %s", e); default: - fatal_f("unexpected response from master 0x%08x", type); + fatal_f("unexpected response from master 0x%08x", (unsigned)type); } sshbuf_free(m); muxclient_request_id++; @@ -1763,7 +1774,7 @@ struct sshbuf *m; char *e, *fwd_desc; const char *lhost, *chost; - u_int type, rid; + u_int32_t type, rid; int r; fwd_desc = format_forward(ftype, fwd); @@ -1815,7 +1826,7 @@ fatal_fr(r, "parse"); if (rid != muxclient_request_id) fatal_f("out of sequence reply: my id %u theirs %u", - muxclient_request_id, rid); + muxclient_request_id, (unsigned)rid); switch (type) { case MUX_S_OK: @@ -1823,14 +1834,17 @@ case MUX_S_REMOTE_PORT: if (cancel_flag) fatal_f("got MUX_S_REMOTE_PORT for cancel"); - if ((r = sshbuf_get_u32(m, &fwd->allocated_port)) != 0) + { u_int32_t val; + if ((r = sshbuf_get_u32(m, &val)) != 0) fatal_fr(r, "parse port"); + fwd->allocated_port = val; + } verbose("Allocated port %u for remote forward to %s:%d", fwd->allocated_port, fwd->connect_host ? fwd->connect_host : "", fwd->connect_port); if (muxclient_command == SSHMUX_COMMAND_FORWARD) - fprintf(stdout, "%i\n", fwd->allocated_port); + fprintf(stdout, "%d\n", fwd->allocated_port); break; case MUX_S_PERMISSION_DENIED: if ((r = sshbuf_get_cstring(m, &e, NULL)) != 0) @@ -1845,7 +1859,7 @@ error_f("forwarding request failed: %s", e); return -1; default: - fatal_f("unexpected response from master 0x%08x", type); + fatal_f("unexpected response from master 0x%08x", (unsigned)type); } sshbuf_free(m); @@ -1883,10 +1897,11 @@ { struct sshbuf *m; char *e; - const char *term = NULL; - u_int i, echar, rid, sid, esid, exitval, type, exitval_seen; + const char *term; + u_int32_t echar, type, rid, sid, esid, exitval; extern char **environ; - int r, rawmode = 0; + u_int i; + int r, rawmode, exitval_seen; debug3_f("entering"); @@ -1897,7 +1912,7 @@ ssh_signal(SIGPIPE, SIG_IGN); - if (options.stdin_null && stdfd_devnull(1, 0, 0) == -1) + if (stdfd_devnull(options.stdin_null, 0, 0) == -1) fatal_f("stdfd_devnull failed"); if ((term = lookup_env_in_list("TERM", options.setenv, @@ -1906,7 +1921,7 @@ echar = 0xffffffff; if (options.escape_char != SSH_ESCAPECHAR_NONE) - echar = (u_int)options.escape_char; + echar = (u_int32_t)options.escape_char; if ((m = sshbuf_new()) == NULL) fatal_f("sshbuf_new"); @@ -1918,7 +1933,7 @@ (r = sshbuf_put_u32(m, options.forward_agent)) != 0 || (r = sshbuf_put_u32(m, options.session_type == SESSION_TYPE_SUBSYSTEM)) != 0 || (r = sshbuf_put_u32(m, echar)) != 0 || - (r = sshbuf_put_cstring(m, term == NULL ? "" : term)) != 0 || + (r = sshbuf_put_cstring(m, term)) != 0 || (r = sshbuf_put_stringb(m, command)) != 0) fatal_fr(r, "request"); @@ -1960,13 +1975,13 @@ fatal_fr(r, "parse"); if (rid != muxclient_request_id) fatal_f("out of sequence reply: my id %u theirs %u", - muxclient_request_id, rid); + muxclient_request_id, (unsigned)rid); switch (type) { case MUX_S_SESSION_OPENED: if ((r = sshbuf_get_u32(m, &sid)) != 0) fatal_fr(r, "parse session ID"); - debug_f("master session id: %u", sid); + debug_f("master session id: %u", (unsigned)sid); break; case MUX_S_PERMISSION_DENIED: if ((r = sshbuf_get_cstring(m, &e, NULL)) != 0) @@ -1982,7 +1997,7 @@ return -1; default: sshbuf_free(m); - error_f("unexpected response from master 0x%08x", type); + error_f("unexpected response from master 0x%08x", (unsigned)type); return -1; } muxclient_request_id++; @@ -1996,18 +2011,19 @@ ssh_signal(SIGTERM, control_client_sighandler); ssh_signal(SIGWINCH, control_client_sigrelay); - if (options.fork_after_authentication) - daemon(1, 1); - else { + if (options.fork_after_authentication) { + if (daemon(1, 1) == -1) { + error_f("daemon() failed: %.200s", strerror(errno)); + rawmode = tty_flag; + } else + rawmode = 0; + } else rawmode = tty_flag; - if (tty_flag) { - enter_raw_mode( - options.request_tty == REQUEST_TTY_FORCE); - } - } + if (rawmode) + enter_raw_mode(options.request_tty == REQUEST_TTY_FORCE); /* - * Stick around until the controlee closes the client_fd. + * Stick around until the controler closes the client_fd. * Before it does, it is expected to write an exit message. * This process must read the value and wait for the closure of * the client_fd; if this one closes early, the multiplex master will @@ -2025,7 +2041,7 @@ fatal_fr(r, "parse session ID"); if (esid != sid) fatal_f("tty alloc fail on unknown session: " - "my id %u theirs %u", sid, esid); + "my id %u theirs %u", (unsigned)sid, (unsigned)esid); leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE); rawmode = 0; @@ -2035,7 +2051,7 @@ fatal_fr(r, "parse session ID"); if (esid != sid) fatal_f("exit on unknown session: " - "my id %u theirs %u", sid, esid); + "my id %u theirs %u", (unsigned)sid, (unsigned)esid); if (exitval_seen) fatal_f("exitval sent twice"); if ((r = sshbuf_get_u32(m, &exitval)) != 0) @@ -2060,7 +2076,7 @@ debug2("Control master terminated unexpectedly"); exitval = 255; } else - debug2("Received exit status from master %d", exitval); + debug2("Received exit status from master %d", (int)exitval); if (tty_flag && options.log_level >= SYSLOG_LEVEL_INFO) fprintf(stderr, "Shared connection to %s closed.\r\n", host); @@ -2073,7 +2089,7 @@ { struct sshbuf *m; char *e; - u_int type, rid; + u_int32_t type, rid; int r; if ((m = sshbuf_new()) == NULL) @@ -2096,7 +2112,7 @@ fatal_fr(r, "parse"); if (rid != muxclient_request_id) fatal_f("out of sequence reply: my id %u theirs %u", - muxclient_request_id, rid); + muxclient_request_id, (unsigned)rid); if (type != MUX_S_PROXY) { if ((r = sshbuf_get_cstring(m, &e, NULL)) != 0) fatal_fr(r, "parse error message"); @@ -2114,7 +2130,7 @@ { struct sshbuf *m; char *e; - u_int type, rid, sid; + u_int32_t type, rid, sid; int r; debug3_f("entering"); @@ -2126,7 +2142,7 @@ ssh_signal(SIGPIPE, SIG_IGN); - if (options.stdin_null && stdfd_devnull(1, 0, 0) == -1) + if (stdfd_devnull(options.stdin_null, 0, 0) == -1) fatal_f("stdfd_devnull failed"); if ((m = sshbuf_new()) == NULL) @@ -2166,12 +2182,12 @@ fatal_fr(r, "parse"); if (rid != muxclient_request_id) fatal_f("out of sequence reply: my id %u theirs %u", - muxclient_request_id, rid); + muxclient_request_id, (unsigned)rid); switch (type) { case MUX_S_SESSION_OPENED: if ((r = sshbuf_get_u32(m, &sid)) != 0) fatal_fr(r, "parse session ID"); - debug_f("master session id: %u", sid); + debug_f("master session id: %u", (unsigned)sid); break; case MUX_S_PERMISSION_DENIED: if ((r = sshbuf_get_cstring(m, &e, NULL)) != 0) @@ -2185,7 +2201,7 @@ fatal("Stdio forwarding request failed: %s", e); default: sshbuf_free(m); - error_f("unexpected response from master 0x%08x", type); + error_f("unexpected response from master 0x%08x", (unsigned)type); return -1; } muxclient_request_id++; @@ -2213,7 +2229,7 @@ { struct sshbuf *m; char *e; - u_int type, rid; + u_int32_t type, rid; int r; debug3_f("entering"); @@ -2238,7 +2254,7 @@ fatal_fr(r, "parse"); if (rid != muxclient_request_id) fatal_f("out of sequence reply: my id %u theirs %u", - muxclient_request_id, rid); + muxclient_request_id, (unsigned)rid); switch (type) { case MUX_S_OK: @@ -2252,7 +2268,7 @@ fatal_fr(r, "parse error message"); fatal_f("stop listening request failed: %s", e); default: - fatal_f("unexpected response from master 0x%08x", type); + fatal_f("unexpected response from master 0x%08x", (unsigned)type); } sshbuf_free(m); muxclient_request_id++; diff -ruN openssh-9.4p1/myproposal.h openssh-9.4p1+x509-14.2.1/myproposal.h --- openssh-9.4p1/myproposal.h 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/myproposal.h 2023-08-20 10:07:00.000000000 +0300 @@ -1,4 +1,4 @@ -/* $OpenBSD: myproposal.h,v 1.71 2022/03/30 21:13:23 djm Exp $ */ +/* $OpenBSD: myproposal.h,v 1.68 2020/10/03 04:15:06 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. @@ -24,8 +24,15 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#define KEX_SERVER_KEX \ - "sntrup761x25519-sha512@openssh.com," \ +#include "includes.h" + +#ifdef ENABLE_KEX_SNTRUP761X25519 +# define KEX_SNTRUP761X25519 "sntrup761x25519-sha512@openssh.com," +#else +# define KEX_SNTRUP761X25519 +#endif + +#define KEX_SERVER_KEX \ "curve25519-sha256," \ "curve25519-sha256@libssh.org," \ "ecdh-sha2-nistp256," \ @@ -34,7 +41,9 @@ "diffie-hellman-group-exchange-sha256," \ "diffie-hellman-group16-sha512," \ "diffie-hellman-group18-sha512," \ - "diffie-hellman-group14-sha256" + "diffie-hellman-group14-sha256," \ + KEX_SNTRUP761X25519 \ + "diffie-hellman-group14-sha1" #define KEX_CLIENT_KEX KEX_SERVER_KEX @@ -43,18 +52,16 @@ "ecdsa-sha2-nistp256-cert-v01@openssh.com," \ "ecdsa-sha2-nistp384-cert-v01@openssh.com," \ "ecdsa-sha2-nistp521-cert-v01@openssh.com," \ - "sk-ssh-ed25519-cert-v01@openssh.com," \ - "sk-ecdsa-sha2-nistp256-cert-v01@openssh.com," \ - "rsa-sha2-512-cert-v01@openssh.com," \ "rsa-sha2-256-cert-v01@openssh.com," \ + "rsa-sha2-512-cert-v01@openssh.com," \ + "ssh-rsa-cert-v01@openssh.com," \ "ssh-ed25519," \ "ecdsa-sha2-nistp256," \ "ecdsa-sha2-nistp384," \ "ecdsa-sha2-nistp521," \ - "sk-ssh-ed25519@openssh.com," \ - "sk-ecdsa-sha2-nistp256@openssh.com," \ + "rsa-sha2-256," \ "rsa-sha2-512," \ - "rsa-sha2-256" + "ssh-rsa" #define KEX_SERVER_ENCRYPT \ "chacha20-poly1305@openssh.com," \ @@ -83,12 +90,15 @@ "ecdsa-sha2-nistp256," \ "ecdsa-sha2-nistp384," \ "ecdsa-sha2-nistp521," \ - "sk-ssh-ed25519@openssh.com," \ - "sk-ecdsa-sha2-nistp256@openssh.com," \ + "rsa-sha2-256," \ "rsa-sha2-512," \ - "rsa-sha2-256" + "ssh-rsa" +#ifdef WITH_ZLIB #define KEX_DEFAULT_COMP "none,zlib@openssh.com" +#else +#define KEX_DEFAULT_COMP "none" +#endif #define KEX_DEFAULT_LANG "" #define KEX_CLIENT \ diff -ruN openssh-9.4p1/nchan.c openssh-9.4p1+x509-14.2.1/nchan.c --- openssh-9.4p1/nchan.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/nchan.c 2023-08-20 10:07:01.000000000 +0300 @@ -1,6 +1,7 @@ /* $OpenBSD: nchan.c,v 1.74 2022/02/01 23:32:51 djm Exp $ */ /* * Copyright (c) 1999, 2000, 2001, 2002 Markus Friedl. All rights reserved. + * Copyright (c) 2019-2021 Roumen Petrov. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -35,12 +36,13 @@ #include "openbsd-compat/sys-queue.h" #include "ssh2.h" #include "sshbuf.h" -#include "ssherr.h" #include "packet.h" #include "channels.h" #include "compat.h" #include "log.h" +extern int channel_close_fd(struct ssh *, Channel *, int); + /* * SSH Protocol 1.5 aka New Channel Protocol * Thanks to Martina, Axel and everyone who left Erlangen, leaving me bored. @@ -93,7 +95,7 @@ chan_set_istate(Channel *c, u_int next) { if (c->istate > CHAN_INPUT_CLOSED || next > CHAN_INPUT_CLOSED) - fatal("chan_set_istate: bad state %d -> %d", c->istate, next); + fatal_f("bad state %d -> %d", c->istate, next); debug2("channel %d: input %s -> %s", c->self, istates[c->istate], istates[next]); c->istate = next; @@ -103,7 +105,7 @@ chan_set_ostate(Channel *c, u_int next) { if (c->ostate > CHAN_OUTPUT_CLOSED || next > CHAN_OUTPUT_CLOSED) - fatal("chan_set_ostate: bad state %d -> %d", c->ostate, next); + fatal_f("bad state %d -> %d", c->ostate, next); debug2("channel %d: output %s -> %s", c->self, ostates[c->ostate], ostates[next]); c->ostate = next; @@ -237,7 +239,7 @@ c->self); return; } - if (!(ssh->compat & SSH_NEW_OPENSSH)) + if (!ssh_compat_fellows(ssh, SSH_NEW_OPENSSH)) return; if (!c->have_remote_id) fatal_f("channel %d: no remote_id", c->self); @@ -326,6 +328,7 @@ void chan_mark_dead(struct ssh *ssh, Channel *c) { + UNUSED(ssh); c->type = SSH_CHANNEL_ZOMBIE; } @@ -338,7 +341,7 @@ } if (c->istate != CHAN_INPUT_CLOSED || c->ostate != CHAN_OUTPUT_CLOSED) return 0; - if ((ssh->compat & SSH_BUG_EXTEOF) && + if (ssh_compat_fellows(ssh, SSH_BUG_EXTEOF) && c->extended_usage == CHAN_EXTENDED_WRITE && c->efd != -1 && sshbuf_len(c->extended) > 0) { @@ -349,7 +352,7 @@ if (c->flags & CHAN_LOCAL) { debug2("channel %d: is dead (local)", c->self); return 1; - } + } if (!(c->flags & CHAN_CLOSE_SENT)) { if (do_send) { chan_send_close2(ssh, c); @@ -384,13 +387,13 @@ if (c->sock != -1) { if (shutdown(c->sock, SHUT_WR) == -1) { debug2_f("channel %d: shutdown() failed for " - "fd %d [i%d o%d]: %.100s", c->self, c->sock, + "socket fd %d [i%d o%d]: %.100s", c->self, c->sock, c->istate, c->ostate, strerror(errno)); } } else { - if (channel_close_fd(ssh, c, &c->wfd) < 0) { - logit_f("channel %d: close() failed for " - "fd %d [i%d o%d]: %.100s", c->self, c->wfd, + if (channel_close_fd(ssh, c, SSH_CHANNEL_FD_OUTPUT) < 0) { + error_f("channel %d: close() failed for " + "write fd %d [i%d o%d]: %.100s", c->self, c->wfd, c->istate, c->ostate, strerror(errno)); } } @@ -412,13 +415,13 @@ */ if (shutdown(c->sock, SHUT_RD) == -1 && errno != ENOTCONN) { error_f("channel %d: shutdown() failed for " - "fd %d [i%d o%d]: %.100s", c->self, c->sock, + "socket fd %d [i%d o%d]: %.100s", c->self, c->sock, c->istate, c->ostate, strerror(errno)); } } else { - if (channel_close_fd(ssh, c, &c->rfd) < 0) { - logit_f("channel %d: close() failed for " - "fd %d [i%d o%d]: %.100s", c->self, c->rfd, + if (channel_close_fd(ssh, c, SSH_CHANNEL_FD_INPUT) < 0) { + error_f("channel %d: close() failed for " + "read fd %d [i%d o%d]: %.100s", c->self, c->rfd, c->istate, c->ostate, strerror(errno)); } } @@ -432,11 +435,11 @@ if (c->extended_usage != CHAN_EXTENDED_READ && c->extended_usage != CHAN_EXTENDED_IGNORE) return; - debug_f("channel %d: (i%d o%d sock %d wfd %d efd %d [%s])", + debug2_f("channel %d: (i%d o%d sock %d wfd %d efd %d [%s])", c->self, c->istate, c->ostate, c->sock, c->rfd, c->efd, channel_format_extended_usage(c)); - if (channel_close_fd(ssh, c, &c->efd) < 0) { - logit_f("channel %d: close() failed for " + if (channel_close_fd(ssh, c, SSH_CHANNEL_FD_ERROR) < 0) { + error_f("channel %d: close() failed for " "extended fd %d [i%d o%d]: %.100s", c->self, c->efd, c->istate, c->ostate, strerror(errno)); } diff -ruN openssh-9.4p1/openbsd-compat/arc4random.c openssh-9.4p1+x509-14.2.1/openbsd-compat/arc4random.c --- openssh-9.4p1/openbsd-compat/arc4random.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/openbsd-compat/arc4random.c 2023-08-20 10:07:01.000000000 +0300 @@ -1,10 +1,10 @@ /* $OpenBSD: arc4random.c,v 1.58 2022/07/31 13:41:45 tb Exp $ */ - /* * Copyright (c) 1996, David Mazieres * Copyright (c) 2008, Damien Miller * Copyright (c) 2013, Markus Friedl * Copyright (c) 2014, Theo de Raadt + * Copyright (c) 2014-2023, Roumen Petrov. All rights reserved. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -19,53 +19,102 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* - * ChaCha based random number generator for OpenBSD. - */ - -/* OPENBSD ORIGINAL: lib/libc/crypt/arc4random.c */ - #include "includes.h" #include #include -#include #include #ifdef HAVE_STDINT_H -#include +# include #endif #include #include #include -#include -#include +#include "log.h" -#ifndef HAVE_ARC4RANDOM +extern int _ssh_compat_getentropy(void *, size_t); -/* - * Always use the getentropy implementation from bsd-getentropy.c, which - * will call a native getentropy if available then fall back as required. - * We use a different name so that OpenSSL cannot call the wrong getentropy. - */ -int _ssh_compat_getentropy(void *, size_t); -#ifdef getentropy -# undef getentropy +#ifdef OPENSSL_FIPS +/* for FIPS build always use functions from "compat" library */ +# undef HAVE_ARC4RANDOM +# undef HAVE_ARC4RANDOM_STIR +# undef HAVE_ARC4RANDOM_BUF +# undef HAVE_ARC4RANDOM_UNIFORM #endif -#define getentropy(x, y) (_ssh_compat_getentropy((x), (y))) + +#if !defined(HAVE_ARC4RANDOM) || !defined(HAVE_ARC4RANDOM_STIR) + +#ifdef OPENSSL_FIPS +# include +# include +# ifdef HAVE_OPENSSL_FIPS_H +# include /* for FIPS_mode() */ +# endif +/* define to avoid use of 'efficient' arc4random_buf() */ +# define HAVE_ARC4RANDOM_BUF + +/* Size of key to use */ +#define SEED_SIZE 20 +static int rc4_ready = 0; + +void fips_arc4random_stir(void); +uint32_t fips_arc4random(void); +void save_arc4random_stir(void); +uint32_t save_arc4random(void); + +/* FIXME: based on readhat/fedora fips patch */ +void +fips_arc4random_stir(void) { + unsigned char rand_buf[SEED_SIZE]; + + if (RAND_bytes(rand_buf, sizeof(rand_buf)) <= 0) + fatal("Couldn't obtain random bytes (error %ld)", + ERR_get_error()); + rc4_ready = 1; +} +uint32_t +fips_arc4random(void) { + unsigned int r = 0; + void *rp = &r; + + if (!rc4_ready) { + fips_arc4random_stir(); + } + RAND_bytes(rp, sizeof(r)); + + return(r); +} + +void +arc4random_stir(void) { + if (FIPS_mode()) + fips_arc4random_stir(); + else + save_arc4random_stir(); +} + +uint32_t +arc4random(void) { + return FIPS_mode() + ? fips_arc4random() + : save_arc4random(); +} + +# define arc4random_stir save_arc4random_stir +# define arc4random save_arc4random +#endif /*def OPENSSL_FIPS*/ + #include "log.h" #define KEYSTREAM_ONLY #include "chacha_private.h" -#define minimum(a, b) ((a) < (b) ? (a) : (b)) - -#if defined(__GNUC__) || defined(_MSC_VER) -#define inline __inline -#else /* __GNUC__ || _MSC_VER */ -#define inline -#endif /* !__GNUC__ && !_MSC_VER */ +/* OpenSSH isn't multithreaded */ +#define _ARC4_LOCK() +#define _ARC4_UNLOCK() +#define _ARC4_ATFORK(f) #define KEYSZ 32 #define IVSZ 8 @@ -74,21 +123,71 @@ #define REKEY_BASE (1024*1024) /* NB. should be a power of 2 */ -/* Marked MAP_INHERIT_ZERO, so zero'd out in fork children. */ static struct _rs { size_t rs_have; /* valid bytes at end of rs_buf */ size_t rs_count; /* bytes till reseed */ -} *rs; +} *rs = NULL; /* Maybe be preserved in fork children, if _rs_allocate() decides. */ static struct _rsx { chacha_ctx rs_chacha; /* chacha context for random keystream */ u_char rs_buf[RSBUFSZ]; /* keystream blocks */ -} *rsx; +} *rsx = NULL; + +static volatile sig_atomic_t _rs_forked; + +#if 0 /* UNUSED */ +static inline void +_rs_forkhandler(void) +{ + _rs_forked = 1; +} +#endif + +# ifndef HAVE_ARC4RANDOM +static inline void +_rs_forkdetect(void) +{ + static pid_t _rs_pid = 0; + pid_t pid = getpid(); + + if (_rs_pid == 0 || _rs_pid == 1 || _rs_pid != pid || _rs_forked) { + _rs_pid = pid; + _rs_forked = 0; + if (rs != NULL) + memset(rs, 0, sizeof(*rs)); + } +} +#endif + +static inline int +_rs_allocate(struct _rs **rsp, struct _rsx **rsxp) +{ +#if defined(MAP_ANON) && defined(MAP_PRIVATE) + if ((*rsp = mmap(NULL, sizeof(**rsp), PROT_READ|PROT_WRITE, + MAP_ANON|MAP_PRIVATE, -1, 0)) == MAP_FAILED) + return (-1); + + if ((*rsxp = mmap(NULL, sizeof(**rsxp), PROT_READ|PROT_WRITE, + MAP_ANON|MAP_PRIVATE, -1, 0)) == MAP_FAILED) { + munmap(*rsp, sizeof(**rsp)); + *rsp = NULL; + return (-1); + } +#else + if ((*rsp = calloc(1, sizeof(**rsp))) == NULL) + return (-1); + if ((*rsxp = calloc(1, sizeof(**rsxp))) == NULL) { + free(*rsp); + *rsp = NULL; + return (-1); + } +#endif + + _ARC4_ATFORK(_rs_forkhandler); + return (0); +} -static inline int _rs_allocate(struct _rs **, struct _rsx **); -static inline void _rs_forkdetect(void); -#include "arc4random.h" static inline void _rs_rekey(u_char *dat, size_t datlen); @@ -113,10 +212,10 @@ u_char rnd[KEYSZ + IVSZ]; uint32_t rekey_fuzz = 0; - if (getentropy(rnd, sizeof rnd) == -1) - _getentropy_fail(); + if (_ssh_compat_getentropy(rnd, sizeof rnd) == -1) + fatal("getentropy failed"); - if (!rs) + if (rs == NULL) _rs_init(rnd, sizeof(rnd)); else _rs_rekey(rnd, sizeof(rnd)); @@ -132,17 +231,19 @@ rs->rs_count = REKEY_BASE + (rekey_fuzz % REKEY_BASE); } +# ifndef HAVE_ARC4RANDOM static inline void _rs_stir_if_needed(size_t len) { _rs_forkdetect(); - if (!rs || rs->rs_count <= len) + if (rs == NULL || rs->rs_count <= len) _rs_stir(); if (rs->rs_count <= len) rs->rs_count = 0; else rs->rs_count -= len; } +# endif /*ndef HAVE_ARC4RANDOM*/ static inline void _rs_rekey(u_char *dat, size_t datlen) @@ -157,7 +258,7 @@ if (dat) { size_t i, m; - m = minimum(datlen, KEYSZ + IVSZ); + m = MINIMUM(datlen, KEYSZ + IVSZ); for (i = 0; i < m; i++) rsx->rs_buf[i] ^= dat[i]; } @@ -167,44 +268,73 @@ rs->rs_have = sizeof(rsx->rs_buf) - KEYSZ - IVSZ; } +# ifndef HAVE_ARC4RANDOM +static inline void +_rsx_to_buf(void *buf, size_t len) +{ + u_char *keystream; + + keystream = rsx->rs_buf + sizeof(rsx->rs_buf) - rs->rs_have; + memcpy(buf, keystream, len); + memset(keystream, 0, len); + rs->rs_have -= len; +} +#endif + +# if !defined(HAVE_ARC4RANDOM_BUF) && !defined(HAVE_ARC4RANDOM) static inline void _rs_random_buf(void *_buf, size_t n) { u_char *buf = (u_char *)_buf; - u_char *keystream; size_t m; _rs_stir_if_needed(n); while (n > 0) { if (rs->rs_have > 0) { - m = minimum(n, rs->rs_have); - keystream = rsx->rs_buf + sizeof(rsx->rs_buf) - - rs->rs_have; - memcpy(buf, keystream, m); - memset(keystream, 0, m); + m = MINIMUM(n, rs->rs_have); + _rsx_to_buf(buf, m); buf += m; n -= m; - rs->rs_have -= m; } if (rs->rs_have == 0) _rs_rekey(NULL, 0); } } +# endif /*!defined(HAVE_ARC4RANDOM_BUF) && !defined(HAVE_ARC4RANDOM)*/ -static inline void +# ifndef HAVE_ARC4RANDOM +static void _rs_random_u32(uint32_t *val) { - u_char *keystream; + size_t m = sizeof(*val); - _rs_stir_if_needed(sizeof(*val)); - if (rs->rs_have < sizeof(*val)) + _rs_stir_if_needed(m); + if (rs->rs_have < m) _rs_rekey(NULL, 0); - keystream = rsx->rs_buf + sizeof(rsx->rs_buf) - rs->rs_have; - memcpy(val, keystream, sizeof(*val)); - memset(keystream, 0, sizeof(*val)); - rs->rs_have -= sizeof(*val); + _rsx_to_buf(val, m); +} +# endif /*ndef HAVE_ARC4RANDOM*/ + +# ifndef HAVE_ARC4RANDOM_STIR +void +arc4random_stir(void) +{ +# if (defined(HAVE_ARC4RANDOM) && defined(HAVE_ARC4RANDOM_UNIFORM)) \ + || defined(OPENSSL_FIPS) + /* platforms that have arc4random_uniform() and not + * arc4random_stir() should not need the latter. + * also exclude in FIPS build as there is no need to call + * arc4random_stir() before using arc4random_buf(). + */ +# else + _ARC4_LOCK(); + _rs_stir(); + _ARC4_UNLOCK(); +# endif } +# endif /*ndef HAVE_ARC4RANDOM_STIR*/ +# ifndef HAVE_ARC4RANDOM uint32_t arc4random(void) { @@ -216,12 +346,13 @@ return val; } DEF_WEAK(arc4random); +# endif /*ndef HAVE_ARC4RANDOM*/ /* * If we are providing arc4random, then we can provide a more efficient * arc4random_buf(). */ -# ifndef HAVE_ARC4RANDOM_BUF +# if !defined(HAVE_ARC4RANDOM_BUF) && !defined(HAVE_ARC4RANDOM) void arc4random_buf(void *buf, size_t n) { @@ -230,8 +361,15 @@ _ARC4_UNLOCK(); } DEF_WEAK(arc4random_buf); -# endif /* !HAVE_ARC4RANDOM_BUF */ -#endif /* !HAVE_ARC4RANDOM */ +# endif /*!defined(HAVE_ARC4RANDOM_BUF) && !defined(HAVE_ARC4RANDOM)*/ + +#ifdef OPENSSL_FIPS +/* redefine to use arc4random_buf() based on arc4random() */ +# define HAVE_ARC4RANDOM +# undef HAVE_ARC4RANDOM_BUF +#endif + +#endif /*!defined(HAVE_ARC4RANDOM) || !defined(HAVE_ARC4RANDOM_STIR)*/ /* arc4random_buf() that uses platform arc4random() */ #if !defined(HAVE_ARC4RANDOM_BUF) && defined(HAVE_ARC4RANDOM) @@ -239,7 +377,7 @@ arc4random_buf(void *_buf, size_t n) { size_t i; - u_int32_t r = 0; + uint32_t r = 0; char *buf = (char *)_buf; for (i = 0; i < n; i++) { @@ -251,4 +389,3 @@ explicit_bzero(&r, sizeof(r)); } #endif /* !defined(HAVE_ARC4RANDOM_BUF) && defined(HAVE_ARC4RANDOM) */ - diff -ruN openssh-9.4p1/openbsd-compat/arc4random.h openssh-9.4p1+x509-14.2.1/openbsd-compat/arc4random.h --- openssh-9.4p1/openbsd-compat/arc4random.h 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/openbsd-compat/arc4random.h 1970-01-01 02:00:00.000000000 +0200 @@ -1,89 +0,0 @@ -/* $OpenBSD: arc4random_linux.h,v 1.12 2019/07/11 10:37:28 inoguchi Exp $ */ - -/* - * Copyright (c) 1996, David Mazieres - * Copyright (c) 2008, Damien Miller - * Copyright (c) 2013, Markus Friedl - * Copyright (c) 2014, Theo de Raadt - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -/* - * Stub functions for portability. From LibreSSL with some adaptations. - */ - -#include - -#include - -/* OpenSSH isn't multithreaded */ -#define _ARC4_LOCK() -#define _ARC4_UNLOCK() -#define _ARC4_ATFORK(f) - -static inline void -_getentropy_fail(void) -{ - fatal("getentropy failed"); -} - -static volatile sig_atomic_t _rs_forked; - -static inline void -_rs_forkhandler(void) -{ - _rs_forked = 1; -} - -static inline void -_rs_forkdetect(void) -{ - static pid_t _rs_pid = 0; - pid_t pid = getpid(); - - if (_rs_pid == 0 || _rs_pid == 1 || _rs_pid != pid || _rs_forked) { - _rs_pid = pid; - _rs_forked = 0; - if (rs) - memset(rs, 0, sizeof(*rs)); - } -} - -static inline int -_rs_allocate(struct _rs **rsp, struct _rsx **rsxp) -{ -#if defined(MAP_ANON) && defined(MAP_PRIVATE) - if ((*rsp = mmap(NULL, sizeof(**rsp), PROT_READ|PROT_WRITE, - MAP_ANON|MAP_PRIVATE, -1, 0)) == MAP_FAILED) - return (-1); - - if ((*rsxp = mmap(NULL, sizeof(**rsxp), PROT_READ|PROT_WRITE, - MAP_ANON|MAP_PRIVATE, -1, 0)) == MAP_FAILED) { - munmap(*rsp, sizeof(**rsp)); - *rsp = NULL; - return (-1); - } -#else - if ((*rsp = calloc(1, sizeof(**rsp))) == NULL) - return (-1); - if ((*rsxp = calloc(1, sizeof(**rsxp))) == NULL) { - free(*rsp); - *rsp = NULL; - return (-1); - } -#endif - - _ARC4_ATFORK(_rs_forkhandler); - return (0); -} diff -ruN openssh-9.4p1/openbsd-compat/arc4random_uniform.c openssh-9.4p1+x509-14.2.1/openbsd-compat/arc4random_uniform.c --- openssh-9.4p1/openbsd-compat/arc4random_uniform.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/openbsd-compat/arc4random_uniform.c 2023-08-20 10:07:01.000000000 +0300 @@ -1,7 +1,7 @@ /* $OpenBSD: arc4random_uniform.c,v 1.3 2019/01/20 02:59:07 bcook Exp $ */ - /* * Copyright (c) 2008, Damien Miller + * Copyright (c) 2014-2022, Roumen Petrov. All rights reserved. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -16,8 +16,6 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* OPENBSD ORIGINAL: lib/libc/crypto/arc4random_uniform.c */ - #include "includes.h" #ifdef HAVE_STDINT_H @@ -25,6 +23,11 @@ #endif #include +#ifdef OPENSSL_FIPS +/* for FIPS build always use functions from "compat" library */ +# undef HAVE_ARC4RANDOM_UNIFORM +#endif + #ifndef HAVE_ARC4RANDOM_UNIFORM /* * Calculate a uniformly distributed random number less than upper_bound diff -ruN openssh-9.4p1/openbsd-compat/base64.c openssh-9.4p1+x509-14.2.1/openbsd-compat/base64.c --- openssh-9.4p1/openbsd-compat/base64.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/openbsd-compat/base64.c 2023-08-20 10:07:01.000000000 +0300 @@ -48,7 +48,6 @@ #if (!defined(HAVE_B64_NTOP) && !defined(HAVE___B64_NTOP)) || (!defined(HAVE_B64_PTON) && !defined(HAVE___B64_PTON)) -#include #include #include #include diff -ruN openssh-9.4p1/openbsd-compat/bcrypt_pbkdf.c openssh-9.4p1+x509-14.2.1/openbsd-compat/bcrypt_pbkdf.c --- openssh-9.4p1/openbsd-compat/bcrypt_pbkdf.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/openbsd-compat/bcrypt_pbkdf.c 2023-08-20 10:07:01.000000000 +0300 @@ -23,8 +23,6 @@ #ifndef HAVE_BCRYPT_PBKDF -#include - #ifdef HAVE_STDLIB_H # include #endif @@ -40,8 +38,6 @@ #endif #define SHA512_DIGEST_LENGTH crypto_hash_sha512_BYTES -#define MINIMUM(a,b) (((a) < (b)) ? (a) : (b)) - /* * pkcs #5 pbkdf2 implementation using the "bcrypt" hash * @@ -49,7 +45,7 @@ * function with the following modifications: * 1. The input password and salt are preprocessed with SHA512. * 2. The output length is expanded to 256 bits. - * 3. Subsequently the magic string to be encrypted is lengthened and modifed + * 3. Subsequently the magic string to be encrypted is lengthened and modified * to "OxychromaticBlowfishSwatDynamite" * 4. The hash function is defined to perform 64 rounds of initial state * expansion. (More rounds are performed by iterating the hash.) @@ -93,6 +89,12 @@ for (i = 0; i < BCRYPT_WORDS; i++) cdata[i] = Blowfish_stream2word(ciphertext, sizeof(ciphertext), &j); +/* NOTE +bcrypt_pbkdf.c:94:40: error: expression does not compute the number of + elements in this array; element type is 'uint32_t'... + place parentheses around the 'sizeof(uint64_t)' expression to + silence this warning +*/ for (i = 0; i < 64; i++) blf_enc(&state, cdata, BCRYPT_WORDS / 2); @@ -182,7 +184,7 @@ bad: /* overwrite with random in case caller doesn't check return code */ - arc4random_buf(key, keylen); + arc4random_buf(key, origkeylen); return -1; } #endif /* HAVE_BCRYPT_PBKDF */ diff -ruN openssh-9.4p1/openbsd-compat/bindresvport.c openssh-9.4p1+x509-14.2.1/openbsd-compat/bindresvport.c --- openssh-9.4p1/openbsd-compat/bindresvport.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/openbsd-compat/bindresvport.c 2023-08-20 10:07:01.000000000 +0300 @@ -40,8 +40,8 @@ #include #include -#include #include +#include /*for arc4random_uniform*/ #define STARTPORT 600 #define ENDPORT (IPPORT_RESERVED - 1) @@ -102,11 +102,11 @@ error = bind(sd, sa, salen); /* Terminate on success */ - if (error == 0) + if (error != -1) break; /* Terminate on errors, except "address already in use" */ - if ((error < 0) && !((errno == EADDRINUSE) || (errno == EINVAL))) + if (!((errno == EADDRINUSE) || (errno == EINVAL))) break; port++; diff -ruN openssh-9.4p1/openbsd-compat/blowfish.c openssh-9.4p1+x509-14.2.1/openbsd-compat/blowfish.c --- openssh-9.4p1/openbsd-compat/blowfish.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/openbsd-compat/blowfish.c 2023-08-20 10:07:01.000000000 +0300 @@ -51,13 +51,6 @@ #include #endif -#undef inline -#ifdef __GNUC__ -#define inline __inline -#else /* !__GNUC__ */ -#define inline -#endif /* !__GNUC__ */ - /* Function for Feistel Networks */ #define F(s, x) ((((s)[ (((x)>>24)&0xFF)] \ diff -ruN openssh-9.4p1/openbsd-compat/bsd-closefrom.c openssh-9.4p1+x509-14.2.1/openbsd-compat/bsd-closefrom.c --- openssh-9.4p1/openbsd-compat/bsd-closefrom.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/openbsd-compat/bsd-closefrom.c 2023-08-20 10:07:01.000000000 +0300 @@ -1,5 +1,6 @@ /* * Copyright (c) 2004-2005 Todd C. Miller + * Copyright (c) 2021 Roumen Petrov * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -16,9 +17,18 @@ #include "includes.h" -#if !defined(HAVE_CLOSEFROM) || defined(BROKEN_CLOSEFROM) +#if defined(HAVE_CLOSEFROM) && defined(__GLIBC__) +/* + * GNU C Library (2.34+) closefrom implementation aborts on failure. + * Also on Linux it tries to read from /proc/self/fd as failback + * and when that fails also aborts. + * Instead library function, activate closefrom from here. + */ +# undef HAVE_CLOSEFROM +#endif + +#ifndef HAVE_CLOSEFROM -#include #include #include #ifdef HAVE_FCNTL_H @@ -57,10 +67,10 @@ __unused static const char rcsid[] = "$Sudo: closefrom.c,v 1.11 2006/08/17 15:26:54 millert Exp $"; #endif /* lint */ -#ifndef HAVE_FCNTL_CLOSEM /* * Close all file descriptors greater than or equal to lowfd. */ +#ifndef HAVE_FCNTL_CLOSEM static void closefrom_fallback(int lowfd) { @@ -82,7 +92,7 @@ for (fd = lowfd; fd < maxfd; fd++) (void) close((int) fd); } -#endif /* HAVE_FCNTL_CLOSEM */ +#endif /* ndef HAVE_FCNTL_CLOSEM */ #ifdef HAVE_FCNTL_CLOSEM void @@ -128,18 +138,33 @@ struct dirent *dent; DIR *dirp; int len; +#ifdef __ANDROID__ + int pws_fd = -1; +#endif +#ifdef __ANDROID__ +{ + /* keep android property workspace open */ + char *pws_env = getenv("ANDROID_PROPERTY_WORKSPACE"); + if (pws_env) { + /* format "int,int" */ + pws_fd = atoi(pws_env); + } +} +#endif #ifdef HAVE_CLOSE_RANGE - if (close_range(lowfd, INT_MAX, 0) == 0) - return; + if (close_range(lowfd, INT_MAX, 0) != -1) + return; #endif - /* Check for a /proc/$$/fd directory. */ len = snprintf(fdpath, sizeof(fdpath), "/proc/%ld/fd", (long)getpid()); if (len > 0 && (size_t)len < sizeof(fdpath) && (dirp = opendir(fdpath))) { while ((dent = readdir(dirp)) != NULL) { fd = strtol(dent->d_name, &endp, 10); if (dent->d_name != endp && *endp == '\0' && + #ifdef __ANDROID__ + (fd != pws_fd) && + #endif fd >= 0 && fd < INT_MAX && fd >= lowfd && fd != dirfd(dirp)) (void) close((int) fd); } diff -ruN openssh-9.4p1/openbsd-compat/bsd-cygwin_util.c openssh-9.4p1+x509-14.2.1/openbsd-compat/bsd-cygwin_util.c --- openssh-9.4p1/openbsd-compat/bsd-cygwin_util.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/openbsd-compat/bsd-cygwin_util.c 2023-08-20 10:07:01.000000000 +0300 @@ -194,11 +194,11 @@ size_t len; int ret; - if ((len = mbstowcs(NULL, s, 0)) == (size_t) -1) + if ((len = mbstowcs(NULL, s, 0)) == (size_t)-1) return 0; ws = (wchar_t *) xcalloc(len + 1, sizeof (wchar_t)); mbstowcs(ws, s, len + 1); - if ((len = mbstowcs(NULL, pattern, 0)) == (size_t) -1) + if ((len = mbstowcs(NULL, pattern, 0)) == (size_t)-1) return 0; wpattern = (wchar_t *) xcalloc(len + 1, sizeof (wchar_t)); mbstowcs(wpattern, pattern, len + 1); diff -ruN openssh-9.4p1/openbsd-compat/bsd-flock.c openssh-9.4p1+x509-14.2.1/openbsd-compat/bsd-flock.c --- openssh-9.4p1/openbsd-compat/bsd-flock.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/openbsd-compat/bsd-flock.c 2023-08-20 10:07:01.000000000 +0300 @@ -69,7 +69,7 @@ fl.l_whence = SEEK_SET; rc = fcntl(fd, op & LOCK_NB ? F_SETLK : F_SETLKW, &fl); - if (rc && (errno == EAGAIN)) + if (rc == -1 && (errno == EAGAIN)) errno = EWOULDBLOCK; #else rc = -1; diff -ruN openssh-9.4p1/openbsd-compat/bsd-getentropy.c openssh-9.4p1+x509-14.2.1/openbsd-compat/bsd-getentropy.c --- openssh-9.4p1/openbsd-compat/bsd-getentropy.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/openbsd-compat/bsd-getentropy.c 2023-08-20 10:07:01.000000000 +0300 @@ -2,6 +2,7 @@ * Copyright (c) 1996, David Mazieres * Copyright (c) 2008, Damien Miller * Copyright (c) 2013, Markus Friedl + * Copyright (c) 2014-2023, Roumen Petrov. All rights reserved. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -31,6 +32,7 @@ #include #include #include + #ifdef WITH_OPENSSL #include #include @@ -38,6 +40,10 @@ #include "log.h" +extern int seed_from_prngd(unsigned char *, size_t); + +int _ssh_compat_getentropy(void *, size_t); + int _ssh_compat_getentropy(void *s, size_t len) { @@ -46,10 +52,11 @@ fatal("Couldn't obtain random bytes (error 0x%lx)", (unsigned long)ERR_get_error()); #else - int fd, save_errno; + int fd; ssize_t r; size_t o = 0; + /* Prefer OpenSSL random functionality */ #ifdef WITH_OPENSSL if (RAND_bytes(s, len) == 1) return 0; @@ -57,6 +64,8 @@ #ifdef HAVE_GETENTROPY if ((r = getentropy(s, len)) == 0) return 0; + if (errno != ENOSYS) + return -1; #endif /* HAVE_GETENTROPY */ #ifdef HAVE_GETRANDOM if ((r = getrandom(s, len, 0)) > 0 && (size_t)r == len) @@ -64,24 +73,26 @@ #endif /* HAVE_GETRANDOM */ if ((fd = open(SSH_RANDOM_DEV, O_RDONLY)) == -1) { - save_errno = errno; + int save_errno = errno; /* Try egd/prngd before giving up. */ if (seed_from_prngd(s, len) == 0) return 0; - fatal("Couldn't open %s: %s", SSH_RANDOM_DEV, + error("Couldn't open %s: %s", SSH_RANDOM_DEV, strerror(save_errno)); + return -1; } while (o < len) { r = read(fd, (u_char *)s + o, len - o); - if (r < 0) { + if (r == -1) { if (errno == EAGAIN || errno == EINTR || errno == EWOULDBLOCK) continue; - fatal("read %s: %s", SSH_RANDOM_DEV, strerror(errno)); + error("read %s: %s", SSH_RANDOM_DEV, strerror(errno)); + return -1; } o += r; } close(fd); -#endif /* WITH_OPENSSL */ +#endif return 0; } diff -ruN openssh-9.4p1/openbsd-compat/bsd-getline.c openssh-9.4p1+x509-14.2.1/openbsd-compat/bsd-getline.c --- openssh-9.4p1/openbsd-compat/bsd-getline.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/openbsd-compat/bsd-getline.c 2023-08-20 10:07:01.000000000 +0300 @@ -46,7 +46,7 @@ #include #include -static ssize_t +ssize_t getdelim(char **buf, size_t *bufsiz, int delimiter, FILE *fp) { char *ptr, *eptr; diff -ruN openssh-9.4p1/openbsd-compat/bsd-getpagesize.c openssh-9.4p1+x509-14.2.1/openbsd-compat/bsd-getpagesize.c --- openssh-9.4p1/openbsd-compat/bsd-getpagesize.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/openbsd-compat/bsd-getpagesize.c 2023-08-20 10:07:01.000000000 +0300 @@ -5,7 +5,6 @@ #ifndef HAVE_GETPAGESIZE #include -#include int getpagesize(void) diff -ruN openssh-9.4p1/openbsd-compat/bsd-getpeereid.c openssh-9.4p1+x509-14.2.1/openbsd-compat/bsd-getpeereid.c --- openssh-9.4p1/openbsd-compat/bsd-getpeereid.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/openbsd-compat/bsd-getpeereid.c 2023-08-20 10:07:01.000000000 +0300 @@ -50,9 +50,9 @@ if (getpeerucred(s, &ucred) == -1) return (-1); - if ((*euid = ucred_geteuid(ucred)) == -1) + if ((*euid = ucred_geteuid(ucred)) == (uid_t)-1) return (-1); - if ((*gid = ucred_getrgid(ucred)) == -1) + if ((*gid = ucred_getrgid(ucred)) == (gid_t)-1) return (-1); ucred_free(ucred); diff -ruN openssh-9.4p1/openbsd-compat/bsd-malloc.c openssh-9.4p1+x509-14.2.1/openbsd-compat/bsd-malloc.c --- openssh-9.4p1/openbsd-compat/bsd-malloc.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/openbsd-compat/bsd-malloc.c 2023-08-20 10:07:01.000000000 +0300 @@ -22,7 +22,7 @@ #include #include -#if defined(HAVE_MALLOC) && HAVE_MALLOC == 0 +#if !HAVE_MALLOC void * rpl_malloc(size_t size) { @@ -32,7 +32,7 @@ } #endif -#if defined(HAVE_CALLOC) && HAVE_CALLOC == 0 +#if !HAVE_CALLOC void * rpl_calloc(size_t nmemb, size_t size) { @@ -44,13 +44,13 @@ } #endif -#if defined (HAVE_REALLOC) && HAVE_REALLOC == 0 +#if !HAVE_REALLOC void * rpl_realloc(void *ptr, size_t size) { if (size == 0) size = 1; - if (ptr == 0) + if (ptr == NULL) return malloc(size); return realloc(ptr, size); } diff -ruN openssh-9.4p1/openbsd-compat/bsd-misc.c openssh-9.4p1+x509-14.2.1/openbsd-compat/bsd-misc.c --- openssh-9.4p1/openbsd-compat/bsd-misc.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/openbsd-compat/bsd-misc.c 2023-08-20 10:07:01.000000000 +0300 @@ -1,6 +1,7 @@ /* * Copyright (c) 1999-2004 Damien Miller + * Copyright (c) 2016-2022 Roumen Petrov. All rights reserved. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -37,6 +38,9 @@ char *__progname; #endif +#ifdef __ANDROID__ +/* see port-android.c */ +#else /* * NB. duplicate __progname in case it is an alias for argv[0] * Otherwise it may get clobbered by setproctitle() @@ -47,6 +51,7 @@ #ifdef HAVE___PROGNAME extern char *__progname; + UNUSED(argv0); p = __progname; #else if (argv0 == NULL) @@ -61,12 +66,15 @@ perror("strdup"); exit(1); } + return q; } +#endif /*ndef __ANDROID__*/ #ifndef HAVE_SETLOGIN int setlogin(const char *name) { + UNUSED(name); return (0); } #endif /* !HAVE_SETLOGIN */ @@ -75,6 +83,10 @@ int innetgr(const char *netgroup, const char *host, const char *user, const char *domain) { + UNUSED(netgroup); + UNUSED(host); + UNUSED(user); + UNUSED(domain); return (0); } #endif /* HAVE_INNETGR */ @@ -107,7 +119,7 @@ #endif #ifndef HAVE_UTIMES -int utimes(const char *filename, struct timeval *tvp) +int utimes(const char *filename, const struct timeval *tvp) { struct utimbuf ub; @@ -121,39 +133,41 @@ #ifndef HAVE_UTIMENSAT /* * A limited implementation of utimensat() that only implements the - * functionality used by OpenSSH, currently only AT_FDCWD and + * functionality used by secsh, currently only AT_FDCWD and * AT_SYMLINK_NOFOLLOW. */ int -utimensat(int fd, const char *path, const struct timespec times[2], - int flag) +utimensat(int fd, const char *pathname, const struct timespec times[2], + int flags) { struct timeval tv[2]; -# ifdef HAVE_FUTIMES - int ret, oflags = O_WRONLY; -# endif + + if (fd != AT_FDCWD) { + errno = ENOSYS; + return -1; + } tv[0].tv_sec = times[0].tv_sec; tv[0].tv_usec = times[0].tv_nsec / 1000; tv[1].tv_sec = times[1].tv_sec; tv[1].tv_usec = times[1].tv_nsec / 1000; - if (fd != AT_FDCWD) { - errno = ENOSYS; - return -1; - } -# ifndef HAVE_FUTIMES - return utimes(path, tv); -# else +# ifdef HAVE_FUTIMES +{ int ret, oflags = O_WRONLY; + # ifdef O_NOFOLLOW - if (flag & AT_SYMLINK_NOFOLLOW) + if (flags & AT_SYMLINK_NOFOLLOW) oflags |= O_NOFOLLOW; # endif /* O_NOFOLLOW */ - if ((fd = open(path, oflags)) == -1) + if ((fd = open(pathname, oflags)) == -1) return -1; ret = futimes(fd, tv); close(fd); return ret; +} +# else + UNUSED(flags); + return utimes(pathname, tv); # endif } #endif @@ -161,30 +175,32 @@ #ifndef HAVE_FCHOWNAT /* * A limited implementation of fchownat() that only implements the - * functionality used by OpenSSH, currently only AT_FDCWD and + * functionality used by secsh, currently only AT_FDCWD and * AT_SYMLINK_NOFOLLOW. */ int -fchownat(int fd, const char *path, uid_t owner, gid_t group, int flag) +fchownat(int fd, const char *pathname, uid_t owner, gid_t group, int flags) { - int ret, oflags = O_WRONLY; - if (fd != AT_FDCWD) { errno = ENOSYS; return -1; } -# ifndef HAVE_FCHOWN - return chown(path, owner, group); -# else +# ifdef HAVE_FCHOWN +{ int ret, oflags = O_WRONLY; + # ifdef O_NOFOLLOW - if (flag & AT_SYMLINK_NOFOLLOW) + if (flags & AT_SYMLINK_NOFOLLOW) oflags |= O_NOFOLLOW; # endif /* O_NOFOLLOW */ - if ((fd = open(path, oflags)) == -1) + if ((fd = open(pathname, oflags)) == -1) return -1; ret = fchown(fd, owner, group); close(fd); return ret; +} +# else + UNUSED(flags); + return chown(pathname, owner, group); # endif } #endif @@ -192,30 +208,32 @@ #ifndef HAVE_FCHMODAT /* * A limited implementation of fchmodat() that only implements the - * functionality used by OpenSSH, currently only AT_FDCWD and + * functionality used by secsh, currently only AT_FDCWD and * AT_SYMLINK_NOFOLLOW. */ int -fchmodat(int fd, const char *path, mode_t mode, int flag) +fchmodat(int fd, const char *pathname, mode_t mode, int flags) { - int ret, oflags = O_WRONLY; - if (fd != AT_FDCWD) { errno = ENOSYS; return -1; } -# ifndef HAVE_FCHMOD - return chmod(path, mode); -# else +# ifdef HAVE_FCHMOD +{ int ret, oflags = O_WRONLY; + # ifdef O_NOFOLLOW - if (flag & AT_SYMLINK_NOFOLLOW) + if (flags & AT_SYMLINK_NOFOLLOW) oflags |= O_NOFOLLOW; # endif /* O_NOFOLLOW */ - if ((fd = open(path, oflags)) == -1) + if ((fd = open(pathname, oflags)) == -1) return -1; ret = fchmod(fd, mode); close(fd); return ret; +} +# else + UNUSED(flags); + return chmod(pathname, mode); # endif } #endif @@ -226,7 +244,7 @@ int fd, ret, saverrno; fd = open(path, O_WRONLY); - if (fd < 0) + if (fd == -1) return (-1); ret = ftruncate(fd, length); @@ -342,7 +360,7 @@ pid_t getpgid(pid_t pid) { -#if defined(HAVE_GETPGRP) && !defined(GETPGRP_VOID) && GETPGRP_VOID == 0 +#if defined(HAVE_GETPGRP) && !GETPGRP_VOID return getpgrp(pid); #elif defined(HAVE_GETPGRP) if (pid == 0) @@ -358,43 +376,12 @@ int pledge(const char *promises, const char *paths[]) { + UNUSED(promises); + UNUSED(paths); return 0; } #endif -#ifndef HAVE_MBTOWC -/* a mbtowc that only supports ASCII */ -int -mbtowc(wchar_t *pwc, const char *s, size_t n) -{ - if (s == NULL || *s == '\0') - return 0; /* ASCII is not state-dependent */ - if (*s < 0 || *s > 0x7f || n < 1) { - errno = EOPNOTSUPP; - return -1; - } - if (pwc != NULL) - *pwc = *s; - return 1; -} -#endif - -#ifndef HAVE_LLABS -long long -llabs(long long j) -{ - return (j < 0 ? -j : j); -} -#endif - -#ifndef HAVE_BZERO -void -bzero(void *b, size_t n) -{ - (void)memset(b, 0, n); -} -#endif - #ifndef HAVE_RAISE int raise(int sig) @@ -442,19 +429,6 @@ localtime_r(const time_t *timep, struct tm *result) { struct tm *tm = localtime(timep); - *result = *tm; - return result; -} -#endif - -#ifdef ASAN_OPTIONS -const char *__asan_default_options(void) { - return ASAN_OPTIONS; -} -#endif - -#ifdef MSAN_OPTIONS -const char *__msan_default_options(void) { - return MSAN_OPTIONS; + return memcpy(result, tm, sizeof(*tm)); } #endif diff -ruN openssh-9.4p1/openbsd-compat/bsd-misc.h openssh-9.4p1+x509-14.2.1/openbsd-compat/bsd-misc.h --- openssh-9.4p1/openbsd-compat/bsd-misc.h 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/openbsd-compat/bsd-misc.h 2023-08-20 10:07:00.000000000 +0300 @@ -1,5 +1,6 @@ /* * Copyright (c) 1999-2004 Damien Miller + * Copyright (c) 2015-2022 Roumen Petrov. All rights reserved. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -20,7 +21,6 @@ #include "includes.h" char *ssh_get_progname(char *); -int seed_from_prngd(unsigned char *, size_t); #ifndef HAVE_SETSID #define setsid() setpgrp(0, getpid()) @@ -62,7 +62,7 @@ } #endif /* HAVE_STRUCT_TIMEVAL */ -int utimes(const char *, struct timeval *); +int utimes(const char *, const struct timeval *); #endif /* HAVE_UTIMES */ #ifndef AT_FDCWD @@ -89,12 +89,10 @@ #endif /* !HAVE_STRUCT_TIMESPEC */ #if !defined(HAVE_NANOSLEEP) && !defined(HAVE_NSLEEP) -# include int nanosleep(const struct timespec *, struct timespec *); #endif #ifndef HAVE_UTIMENSAT -# include /* start with the high bits and work down to minimise risk of overlap */ # ifndef AT_SYMLINK_NOFOLLOW # define AT_SYMLINK_NOFOLLOW 0x80000000 @@ -127,14 +125,24 @@ #endif #ifndef HAVE_PSELECT +/* may require struct timespec declared above */ int pselect(int, fd_set *, fd_set *, fd_set *, const struct timespec *, const sigset_t *); #endif +#if !HAVE_DECL_ENDGRENT +void endgrent(void); +#endif + #ifndef HAVE_ENDGRENT -# define endgrent() do { } while(0) +static inline void endgrent(void) {} #endif +#if !HAVE_DECL_ENDPWENT +void endpwent(void); +#endif + +#ifdef KRB5 #ifndef HAVE_KRB5_GET_ERROR_MESSAGE # define krb5_get_error_message krb5_get_err_text #endif @@ -142,6 +150,7 @@ #ifndef HAVE_KRB5_FREE_ERROR_MESSAGE # define krb5_free_error_message(a,b) do { } while(0) #endif +#endif /*def KRB5*/ #ifndef HAVE_PLEDGE int pledge(const char *promises, const char *paths[]); @@ -158,14 +167,6 @@ void warn(const char *, ...) __attribute__((format(printf, 1, 2))); #endif -#ifndef HAVE_LLABS -long long llabs(long long); -#endif - -#if defined(HAVE_DECL_BZERO) && HAVE_DECL_BZERO == 0 -void bzero(void *, size_t); -#endif - #ifndef HAVE_RAISE int raise(int); #endif @@ -190,8 +191,4 @@ struct tm *localtime_r(const time_t *, struct tm *); #endif -#ifndef HAVE_REALPATH -#define realpath(x, y) (sftp_realpath((x), (y))) -#endif - #endif /* _BSD_MISC_H */ diff -ruN openssh-9.4p1/openbsd-compat/bsd-openpty.c openssh-9.4p1+x509-14.2.1/openbsd-compat/bsd-openpty.c --- openssh-9.4p1/openbsd-compat/bsd-openpty.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/openbsd-compat/bsd-openpty.c 2023-08-20 10:07:01.000000000 +0300 @@ -5,6 +5,7 @@ /* * Copyright (c) 2004 Damien Miller + * Copyright (c) 2016-2022 Roumen Petrov. All rights reserved. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -42,9 +43,8 @@ #ifdef HAVE_SYS_STAT_H # include #endif -#ifdef HAVE_SYS_IOCTL_H -# include -#endif + +#include #ifdef HAVE_FCNTL_H # include @@ -118,19 +118,24 @@ /* * Try to push the appropriate streams modules, as described * in Solaris pts(7). + * Note on Android I_PUSH is not defined and + * streams modules are not supported. */ +# ifdef I_PUSH ioctl(*aslave, I_PUSH, "ptem"); ioctl(*aslave, I_PUSH, "ldterm"); # ifndef __hpux ioctl(*aslave, I_PUSH, "ttcompat"); # endif /* __hpux */ +# endif /*ndef I_PUSH*/ + return (0); } #endif -int -openpty(int *amaster, int *aslave, char *name, struct termios *termp, - struct winsize *winp) + +static int +ssh_openpty(int *amaster, int *aslave) { #if defined(HAVE__GETPTY) /* @@ -160,7 +165,7 @@ * one that will be passed back to the user process. This ensures * the second pty is not already the controlling terminal for a * different session and is available to become controlling terminal - * for the client's subprocess. See bugzilla #245 for details. + * for the client's subprocess. */ int r, fd; static int junk_ptyfd = -1, junk_ttyfd; @@ -236,5 +241,21 @@ #endif } +/* NOTE: + * Android API 23 defines function "openpty" but it is declared + * only in unified headers. + * Preferred is to use OS compatible definition - see configure.ac. + */ +int +openpty(int *amaster, int *aslave, char *name, + OPENPTY_CONST_ARG struct termios *termp, + OPENPTY_CONST_ARG struct winsize *winp +) { + UNUSED(name); + UNUSED(termp); + UNUSED(winp); + + return ssh_openpty(amaster, aslave); +} #endif /* !defined(HAVE_OPENPTY) */ diff -ruN openssh-9.4p1/openbsd-compat/bsd-poll.c openssh-9.4p1+x509-14.2.1/openbsd-compat/bsd-poll.c --- openssh-9.4p1/openbsd-compat/bsd-poll.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/openbsd-compat/bsd-poll.c 2023-08-20 10:07:01.000000000 +0300 @@ -19,9 +19,6 @@ #include #include -#ifdef HAVE_SYS_PARAM_H -# include -#endif #ifdef HAVE_SYS_SELECT_H # include #endif diff -ruN openssh-9.4p1/openbsd-compat/bsd-poll.h openssh-9.4p1+x509-14.2.1/openbsd-compat/bsd-poll.h --- openssh-9.4p1/openbsd-compat/bsd-poll.h 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/openbsd-compat/bsd-poll.h 2023-08-20 10:07:00.000000000 +0300 @@ -33,8 +33,10 @@ #include #ifdef HAVE_POLL_H # include -#elif HAVE_SYS_POLL_H -# include +#else +# ifdef HAVE_SYS_POLL_H +# include +# endif #endif #ifndef HAVE_STRUCT_POLLFD_FD @@ -76,7 +78,8 @@ #endif /* !HAVE_STRUCT_POLLFD_FD */ #ifndef HAVE_NFDS_T -typedef unsigned int nfds_t; +/* on most used systems is ...long... */ +typedef unsigned long int nfds_t; #endif #ifndef HAVE_POLL diff -ruN openssh-9.4p1/openbsd-compat/bsd-pselect.c openssh-9.4p1+x509-14.2.1/openbsd-compat/bsd-pselect.c --- openssh-9.4p1/openbsd-compat/bsd-pselect.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/openbsd-compat/bsd-pselect.c 2023-08-20 10:07:01.000000000 +0300 @@ -1,6 +1,7 @@ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. * Copyright (c) 2021 Darren Tucker (dtucker at dtucker net). + * Copyright (c) 2021 Roumen Petrov. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -24,6 +25,7 @@ */ #include "includes.h" + #ifndef HAVE_PSELECT #include @@ -40,13 +42,9 @@ #include #include "log.h" -#include "misc.h" /* for set_nonblock */ - -#ifndef HAVE_SIGHANDLER_T -typedef void (*sighandler_t)(int); -#endif +#include "misc.h" /* for set_nonblock, sshsig_t */ -static sighandler_t saved_sighandler[_NSIG]; +static sshsig_t saved_sighandler[NSIG]; /* * Set up the descriptors. Because they are close-on-exec, in the case @@ -69,12 +67,13 @@ return (*fd = r); } +static pid_t notify_pid = 0; /* * we write to this pipe if a SIGCHLD is caught in order to avoid * the race between select() and child_terminated */ -static pid_t notify_pid; -static int notify_pipe[2]; +static int notify_pipe[2] = { -1, -1 }; + static void pselect_notify_setup(void) { @@ -134,7 +133,6 @@ } } -/*ARGSUSED*/ static void pselect_sig_handler(int sig) { @@ -202,4 +200,8 @@ errno = saved_errno; return ret; } -#endif +#else /* HAVE_PSELECT */ + +typedef int bsd_pselect_empty_translation_unit; + +#endif /* HAVE_PSELECT */ diff -ruN openssh-9.4p1/openbsd-compat/bsd-setres_id.c openssh-9.4p1+x509-14.2.1/openbsd-compat/bsd-setres_id.c --- openssh-9.4p1/openbsd-compat/bsd-setres_id.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/openbsd-compat/bsd-setres_id.c 2023-08-20 10:07:01.000000000 +0300 @@ -42,13 +42,13 @@ ret = -1; } #else - if (setegid(egid) < 0) { + if (setegid(egid) == -1) { saved_errno = errno; error("setegid %lu: %.100s", (u_long)egid, strerror(errno)); errno = saved_errno; ret = -1; } - if (setgid(rgid) < 0) { + if (setgid(rgid) == -1) { saved_errno = errno; error("setgid %lu: %.100s", (u_long)rgid, strerror(errno)); errno = saved_errno; @@ -79,14 +79,14 @@ #else # ifndef SETEUID_BREAKS_SETUID - if (seteuid(euid) < 0) { + if (seteuid(euid) == -1) { saved_errno = errno; error("seteuid %lu: %.100s", (u_long)euid, strerror(errno)); errno = saved_errno; ret = -1; } # endif - if (setuid(ruid) < 0) { + if (setuid(ruid) == -1) { saved_errno = errno; error("setuid %lu: %.100s", (u_long)ruid, strerror(errno)); errno = saved_errno; diff -ruN openssh-9.4p1/openbsd-compat/bsd-signal.h openssh-9.4p1+x509-14.2.1/openbsd-compat/bsd-signal.h --- openssh-9.4p1/openbsd-compat/bsd-signal.h 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/openbsd-compat/bsd-signal.h 2023-08-20 10:07:00.000000000 +0300 @@ -19,16 +19,6 @@ #include "includes.h" -#include - -#ifndef _NSIG -# ifdef NSIG -# define _NSIG NSIG -# else -# define _NSIG 128 -# endif -#endif - #if !defined(HAVE_STRSIGNAL) char *strsignal(int); #endif diff -ruN openssh-9.4p1/openbsd-compat/bsd-snprintf.c openssh-9.4p1+x509-14.2.1/openbsd-compat/bsd-snprintf.c --- openssh-9.4p1/openbsd-compat/bsd-snprintf.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/openbsd-compat/bsd-snprintf.c 2023-08-20 10:07:01.000000000 +0300 @@ -778,7 +778,12 @@ idx = (int) ((temp -intpart +0.05)* 10.0); /* idx = (int) (((double)(temp*0.1) -intpart +0.05) *10.0); */ /* printf ("%llf, %f, %x\n", temp, intpart, idx); */ +#if 0 + iconvert[iplace++] = + (caps? "0123456789ABCDEF":"0123456789abcdef")[idx]; +#else iconvert[iplace++] = "0123456789"[idx]; +#endif } while (intpart && (iplace < 311)); if (iplace == 311) iplace--; iconvert[iplace] = 0; @@ -792,7 +797,12 @@ idx = (int) ((temp -fracpart +0.05)* 10.0); /* idx = (int) ((((temp/10) -fracpart) +0.05) *10); */ /* printf ("%lf, %lf, %ld\n", temp, fracpart, idx ); */ +#if 0 + fconvert[fplace++] = + (caps? "0123456789ABCDEF":"0123456789abcdef")[idx]; +#else fconvert[fplace++] = "0123456789"[idx]; +#endif } while(fracpart && (fplace < 311)); if (fplace == 311) fplace--; } diff -ruN openssh-9.4p1/openbsd-compat/bsd-statvfs.c openssh-9.4p1+x509-14.2.1/openbsd-compat/bsd-statvfs.c --- openssh-9.4p1/openbsd-compat/bsd-statvfs.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/openbsd-compat/bsd-statvfs.c 2023-08-20 10:07:01.000000000 +0300 @@ -1,5 +1,6 @@ /* * Copyright (c) 2008,2014 Darren Tucker + * Copyright (c) 2015-2018 Roumen Petrov. All rights reserved. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -18,21 +19,28 @@ #if !defined(HAVE_STATVFS) || !defined(HAVE_FSTATVFS) +#ifdef HAVE_SYS_STATFS_H +# include +#endif #ifdef HAVE_SYS_MOUNT_H # include #endif - +#include /*for memset*/ #include #ifndef MNAMELEN +/* OpenSSH finaly defines MNAMELEN in commit: + * "bsd-statvfs: include sys/vfs.h, check for f_flags" + * (Sun, 25 Feb 2018 11:22:57 +1100) + * but for unknow reason with so small size! + * Let keep size as defined in PKIX-SSH 8.5 since + * (Wed, 12 Aug 2015 00:18:04 +0300) # define MNAMELEN 32 + */ +# define MNAMELEN 90 #endif -#ifdef HAVE_STRUCT_STATFS_F_FILES -# define HAVE_STRUCT_STATFS -#endif - -#ifdef HAVE_STRUCT_STATFS +#ifdef USE_STRUCT_STATFS static void copy_statfs_to_statvfs(struct statvfs *to, struct statfs *from) { @@ -52,12 +60,12 @@ #endif to->f_namemax = MNAMELEN; } -#endif +#endif /*def USE_STRUCT_STATFS*/ # ifndef HAVE_STATVFS int statvfs(const char *path, struct statvfs *buf) { -# if defined(HAVE_STATFS) && defined(HAVE_STRUCT_STATFS) +# ifdef USE_STRUCT_STATFS struct statfs fs; memset(&fs, 0, sizeof(fs)); @@ -75,7 +83,7 @@ # ifndef HAVE_FSTATVFS int fstatvfs(int fd, struct statvfs *buf) { -# if defined(HAVE_FSTATFS) && defined(HAVE_STRUCT_STATFS) +# ifdef USE_STRUCT_STATFS struct statfs fs; memset(&fs, 0, sizeof(fs)); diff -ruN openssh-9.4p1/openbsd-compat/chacha_private.h openssh-9.4p1+x509-14.2.1/openbsd-compat/chacha_private.h --- openssh-9.4p1/openbsd-compat/chacha_private.h 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/openbsd-compat/chacha_private.h 2023-08-20 10:07:00.000000000 +0300 @@ -1,5 +1,3 @@ -/* OPENBSD ORIGINAL: lib/libc/crypt/chacha_private.h */ - /* chacha-merged.c version 20080118 D. J. Bernstein diff -ruN openssh-9.4p1/openbsd-compat/daemon.c openssh-9.4p1+x509-14.2.1/openbsd-compat/daemon.c --- openssh-9.4p1/openbsd-compat/daemon.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/openbsd-compat/daemon.c 2023-08-20 10:07:01.000000000 +0300 @@ -44,9 +44,7 @@ # include #endif -#ifdef HAVE_UNISTD_H -# include -#endif +#include int daemon(int nochdir, int noclose) @@ -68,7 +66,7 @@ if (!nochdir) (void)chdir("/"); - if (!noclose && (fd = open(_PATH_DEVNULL, O_RDWR, 0)) != -1) { + if (!noclose && (fd = open(_PATH_DEVNULL, O_RDWR)) != -1) { (void)dup2(fd, STDIN_FILENO); (void)dup2(fd, STDOUT_FILENO); (void)dup2(fd, STDERR_FILENO); diff -ruN openssh-9.4p1/openbsd-compat/explicit_bzero.c openssh-9.4p1+x509-14.2.1/openbsd-compat/explicit_bzero.c --- openssh-9.4p1/openbsd-compat/explicit_bzero.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/openbsd-compat/explicit_bzero.c 2023-08-20 10:07:01.000000000 +0300 @@ -3,6 +3,20 @@ /* * Public domain. * Written by Ted Unangst + * + * Copyright (c) 2016-2022 Roumen Petrov. All rights reserved. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include "includes.h" @@ -10,7 +24,7 @@ #include /* - * explicit_bzero - don't let the compiler optimize away bzero + * explicit_bzero - don't let the compiler optimize away function call */ #ifndef HAVE_EXPLICIT_BZERO @@ -25,6 +39,10 @@ #elif defined(HAVE_MEMSET_S) +# if !HAVE_DECL_MEMSET_S +void *memset_s(const void *, size_t, int, size_t); +# endif + void explicit_bzero(void *p, size_t n) { @@ -33,33 +51,23 @@ (void)memset_s(p, n, 0, n); } -#else /* HAVE_MEMSET_S */ +#else -/* - * Indirect bzero through a volatile pointer to hopefully avoid - * dead-store optimisation eliminating the call. - */ -static void (* volatile ssh_bzero)(void *, size_t) = bzero; +/* Use memset as bzero is marked as legacy in POSIX.1-2001 + * and removed on POSIX.1-2008 */ +typedef void *(*memset_t)(void *,int,size_t); +static volatile memset_t ssh_memset = memset; void explicit_bzero(void *p, size_t n) { - if (n == 0) - return; - /* - * clang -fsanitize=memory needs to intercept memset-like functions - * to correctly detect memory initialisation. Make sure one is called - * directly since our indirection trick above successfully confuses it. - */ -#if defined(__has_feature) -# if __has_feature(memory_sanitizer) - memset(p, 0, n); -# endif + ssh_memset(p, 0, n); +} + #endif - ssh_bzero(p, n); -} +#else -#endif /* HAVE_MEMSET_S */ +typedef int explicit_bzero_empty_translation_unit; #endif /* HAVE_EXPLICIT_BZERO */ diff -ruN openssh-9.4p1/openbsd-compat/fmt_scaled.c openssh-9.4p1+x509-14.2.1/openbsd-compat/fmt_scaled.c --- openssh-9.4p1/openbsd-compat/fmt_scaled.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/openbsd-compat/fmt_scaled.c 2023-08-20 10:07:01.000000000 +0300 @@ -2,6 +2,7 @@ /* * Copyright (c) 2001, 2002, 2003 Ian F. Darwin. All rights reserved. + * Copyright (c) 2013 Roumen Petrov. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -26,8 +27,6 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* OPENBSD ORIGINAL: lib/libutil/fmt_scaled.c */ - /* * fmt_scaled: Format numbers scaled for human comprehension * scan_scaled: Scan numbers in this format. @@ -49,6 +48,17 @@ #include #include +/* Avoid mixed declarations, i.e. force local definition. + * For instance on Android: + * platform-9 -> static __inline__ long long => not found by configure + * platform-21 -> extern long long + * So to be ABI compatible let use local. +*/ +static inline long long local_llabs(long long ll) { + return (ll < 0LL) ? -ll : ll; +} +#define llabs local_llabs + typedef enum { NONE = 0, KILO = 1, MEGA = 2, GIGA = 3, TERA = 4, PETA = 5, EXA = 6 } unit_type; @@ -189,8 +199,7 @@ /* truncate fpart so it doesn't overflow. * then scale fractional part. */ - while (fpart >= LLONG_MAX / scale_fact || - fpart <= LLONG_MIN / scale_fact) { + while (fpart >= LLONG_MAX / scale_fact) { fpart /= 10; fract_digits--; } diff -ruN openssh-9.4p1/openbsd-compat/fnmatch.c openssh-9.4p1+x509-14.2.1/openbsd-compat/fnmatch.c --- openssh-9.4p1/openbsd-compat/fnmatch.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/openbsd-compat/fnmatch.c 2023-08-20 10:07:01.000000000 +0300 @@ -88,9 +88,10 @@ /* OPENBSD ORIGINAL: lib/libc/gen/fnmatch.c */ #include "includes.h" + #ifndef HAVE_FNMATCH -#include +#include "fnmatch.h" #include #include diff -ruN openssh-9.4p1/openbsd-compat/fnmatch.h openssh-9.4p1+x509-14.2.1/openbsd-compat/fnmatch.h --- openssh-9.4p1/openbsd-compat/fnmatch.h 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/openbsd-compat/fnmatch.h 2023-08-20 10:07:00.000000000 +0300 @@ -35,8 +35,6 @@ /* OPENBSD ORIGINAL: include/fnmatch.h */ #ifndef HAVE_FNMATCH_H -/* Ensure we define FNM_CASEFOLD */ -#define __BSD_VISIBLE 1 #ifndef _FNMATCH_H_ #define _FNMATCH_H_ @@ -51,7 +49,7 @@ #define FNM_NOESCAPE 0x01 /* Disable backslash escaping. */ #define FNM_PATHNAME 0x02 /* Slash must be matched by slash. */ #define FNM_PERIOD 0x04 /* Period must be matched by period. */ -#if __BSD_VISIBLE +#if !defined _POSIX_C_SOURCE || _POSIX_C_SOURCE < 2 || defined _GNU_SOURCE #define FNM_LEADING_DIR 0x08 /* Ignore / after Imatch. */ #define FNM_CASEFOLD 0x10 /* Case insensitive search. */ #define FNM_IGNORECASE FNM_CASEFOLD diff -ruN openssh-9.4p1/openbsd-compat/freezero.c openssh-9.4p1+x509-14.2.1/openbsd-compat/freezero.c --- openssh-9.4p1/openbsd-compat/freezero.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/openbsd-compat/freezero.c 2023-08-20 10:07:01.000000000 +0300 @@ -24,8 +24,26 @@ void freezero(void *ptr, size_t sz) { +/* NOTE: For performance reasons PKIX-SSH uses function BIO_new_mem_buf. + * This function marks bio-buffer read-only. When bio instance is + * destroyed if buffer is read only buffer pointer is set to NULL. + * After this is called buffer is deallocated (freed). + * In above process LibreSSL 2.6* start to use freezero() and for + * deallocation is legal function to be called with NULL argument. + * LibreSSL links with internally provided freezero that checks + * for NULL argument. + * + * This project also provides function freezero. + * Because "compat"-library is linked before other libraries, + * this function is called, but function does not check for NULL + * pointer argument and result is application crash after use + * of BIO_new_mem_buf. + * So lets just check for NULL argument. + */ + /* This is legal. */ if (ptr == NULL) return; + explicit_bzero(ptr, sz); free(ptr); } diff -ruN openssh-9.4p1/openbsd-compat/getcwd.c openssh-9.4p1+x509-14.2.1/openbsd-compat/getcwd.c --- openssh-9.4p1/openbsd-compat/getcwd.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/openbsd-compat/getcwd.c 2023-08-20 10:07:01.000000000 +0300 @@ -41,7 +41,6 @@ #include #include #include -#include "includes.h" #define ISDOT(dp) \ (dp->d_name[0] == '.' && (dp->d_name[1] == '\0' || \ @@ -99,7 +98,7 @@ up[1] = '\0'; /* Save root values, so know when to stop. */ - if (stat("/", &s)) + if (stat("/", &s) == -1) goto err; root_dev = s.st_dev; root_ino = s.st_ino; @@ -108,7 +107,7 @@ for (first = 1;; first = 0) { /* Stat the current level. */ - if (lstat(up, &s)) + if (lstat(up, &s) == -1) goto err; /* Save current node values. */ @@ -147,7 +146,7 @@ *bup = '\0'; /* Open and stat parent directory. */ - if (!(dir = opendir(up)) || fstat(dirfd(dir), &s)) + if (!(dir = opendir(up)) || fstat(dirfd(dir), &s) == -1) goto err; /* Add trailing slash for next directory. */ @@ -175,7 +174,7 @@ memcpy(bup, dp->d_name, dp->d_namlen + 1); /* Save the first error for later. */ - if (lstat(up, &s)) { + if (lstat(up, &s) == -1) { if (!save_errno) save_errno = errno; errno = 0; diff -ruN openssh-9.4p1/openbsd-compat/getopt.h openssh-9.4p1+x509-14.2.1/openbsd-compat/getopt.h --- openssh-9.4p1/openbsd-compat/getopt.h 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/openbsd-compat/getopt.h 2023-08-20 10:07:00.000000000 +0300 @@ -40,7 +40,6 @@ #define required_argument 1 #define optional_argument 2 -#if 0 struct option { /* name of long option */ const char *name; @@ -59,8 +58,6 @@ const struct option *, int *); int getopt_long_only(int, char * const *, const char *, const struct option *, int *); -#endif - #ifndef _GETOPT_DEFINED_ #define _GETOPT_DEFINED_ int getopt(int, char * const *, const char *); diff -ruN openssh-9.4p1/openbsd-compat/getopt_long.c openssh-9.4p1+x509-14.2.1/openbsd-compat/getopt_long.c --- openssh-9.4p1/openbsd-compat/getopt_long.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/openbsd-compat/getopt_long.c 2023-08-20 10:07:01.000000000 +0300 @@ -72,20 +72,6 @@ #include "log.h" -struct option { - /* name of long option */ - const char *name; - /* - * one of no_argument, required_argument, and optional_argument: - * whether option takes an argument - */ - int has_arg; - /* if not NULL, set *flag to val when option found */ - int *flag; - /* if flag not NULL, value to set *flag to; else return value */ - int val; -}; - int opterr = 1; /* if error message should be printed */ int optind = 1; /* index into parent argv vector */ int optopt = '?'; /* character checked for validity */ diff -ruN openssh-9.4p1/openbsd-compat/getrrsetbyname.c openssh-9.4p1+x509-14.2.1/openbsd-compat/getrrsetbyname.c --- openssh-9.4p1/openbsd-compat/getrrsetbyname.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/openbsd-compat/getrrsetbyname.c 2023-08-20 10:07:01.000000000 +0300 @@ -2,6 +2,7 @@ /* * Copyright (c) 2001 Jakob Schlyter. All rights reserved. + * Copyright (c) 2022 Roumen Petrov. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -43,8 +44,6 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* OPENBSD ORIGINAL: lib/libc/net/getrrsetbyname.c */ - #include "includes.h" #if !defined (HAVE_GETRRSETBYNAME) && !defined (HAVE_LDNS) @@ -110,41 +109,43 @@ #endif /* - * If the system doesn't have _getshort/_getlong or that are not exactly what - * we need then use local replacements, avoiding name collisions. - */ -#if !defined(HAVE__GETSHORT) || !defined(HAVE__GETLONG) || \ - !defined(HAVE_DECL__GETSHORT) || HAVE_DECL__GETSHORT == 0 || \ - !defined(HAVE_DECL__GETLONG) || HAVE_DECL__GETLONG == 0 -# ifdef _getshort -# undef _getshort -# endif -# ifdef _getlong -# undef _getlong -# endif -# define _getshort(x) (_ssh_compat_getshort(x)) -# define _getlong(x) (_ssh_compat_getlong(x)) -/* * Routines to insert/extract short/long's. + * + * Usually resolver library (libresolv) provides _getshort interface + * but without to define. + * If the system does not provide _getshort or _get_long use compatibility + * code below. Also use project names to avoid name collisions. */ + +#ifndef HAVE__GETSHORT static u_int16_t -_getshort(const u_char *msgp) +_ssh_getshort(const u_char *msgp) { u_int16_t u; GETSHORT(u, msgp); return (u); } +#define _getshort _ssh_getshort +#endif +#if !HAVE_DECL__GETSHORT +u_int16_t _getshort(const u_char *); +#endif +#ifndef HAVE__GETLONG static u_int32_t -_getlong(const u_char *msgp) +_ssh_getlong(const u_char *msgp) { u_int32_t u; GETLONG(u, msgp); return (u); } -#endif /* missing _getshort/_getlong */ +#define _getlong _ssh_getlong +#endif +#if !HAVE_DECL__GETLONG +u_int32_t _getlong(register const u_char *); +#endif /* ************** */ diff -ruN openssh-9.4p1/openbsd-compat/glob.c openssh-9.4p1+x509-14.2.1/openbsd-compat/glob.c --- openssh-9.4p1/openbsd-compat/glob.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/openbsd-compat/glob.c 2023-08-20 10:07:01.000000000 +0300 @@ -83,9 +83,7 @@ #include "charclass.h" -#ifdef TILDE -# undef TILDE -#endif +#undef TILDE #define DOLLAR '$' #define DOT '.' @@ -651,13 +649,13 @@ *pathend = EOS; return(GLOB_NOSPACE); } - if (g_lstat(pathbuf, &sb, pglob)) + if (g_lstat(pathbuf, &sb, pglob) == -1) return(0); if (((pglob->gl_flags & GLOB_MARK) && pathend[-1] != SEP) && (S_ISDIR(sb.st_mode) || (S_ISLNK(sb.st_mode) && - (g_stat(pathbuf, &sb, pglob) == 0) && + (g_stat(pathbuf, &sb, pglob) != -1) && S_ISDIR(sb.st_mode)))) { if (pathend+1 > pathend_last) return (1); diff -ruN openssh-9.4p1/openbsd-compat/inet_aton.c openssh-9.4p1+x509-14.2.1/openbsd-compat/inet_aton.c --- openssh-9.4p1/openbsd-compat/inet_aton.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/openbsd-compat/inet_aton.c 2023-08-20 10:07:01.000000000 +0300 @@ -55,7 +55,6 @@ #if !defined(HAVE_INET_ATON) -#include #include #include #include diff -ruN openssh-9.4p1/openbsd-compat/inet_ntop.c openssh-9.4p1+x509-14.2.1/openbsd-compat/inet_ntop.c --- openssh-9.4p1/openbsd-compat/inet_ntop.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/openbsd-compat/inet_ntop.c 2023-08-20 10:07:01.000000000 +0300 @@ -22,7 +22,6 @@ #ifndef HAVE_INET_NTOP -#include #include #include #include diff -ruN openssh-9.4p1/openbsd-compat/kludge-fd_set.c openssh-9.4p1+x509-14.2.1/openbsd-compat/kludge-fd_set.c --- openssh-9.4p1/openbsd-compat/kludge-fd_set.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/openbsd-compat/kludge-fd_set.c 2023-08-20 10:07:01.000000000 +0300 @@ -16,6 +16,9 @@ # undef _FORTIFY_SOURCE # undef __USE_FORTIFY_LEVEL # include +void kludge_FD_SET(int, fd_set *); +int kludge_FD_ISSET(int, fd_set *); + void kludge_FD_SET(int n, fd_set *set) { FD_SET(n, set); } diff -ruN openssh-9.4p1/openbsd-compat/libressl-api-compat.c openssh-9.4p1+x509-14.2.1/openbsd-compat/libressl-api-compat.c --- openssh-9.4p1/openbsd-compat/libressl-api-compat.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/openbsd-compat/libressl-api-compat.c 1970-01-01 02:00:00.000000000 +0200 @@ -1,86 +0,0 @@ -/* - * Copyright (c) 2018 Damien Miller - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include "includes.h" - -#ifdef WITH_OPENSSL - -#include - -#include -#include - -#include - -#ifndef HAVE_EVP_CIPHER_CTX_GET_IV -int -EVP_CIPHER_CTX_get_iv(const EVP_CIPHER_CTX *ctx, unsigned char *iv, size_t len) -{ - if (ctx == NULL) - return 0; - if (EVP_CIPHER_CTX_iv_length(ctx) < 0) - return 0; - if (len != (size_t)EVP_CIPHER_CTX_iv_length(ctx)) - return 0; - if (len > EVP_MAX_IV_LENGTH) - return 0; /* sanity check; shouldn't happen */ - /* - * Skip the memcpy entirely when the requested IV length is zero, - * since the iv pointer may be NULL or invalid. - */ - if (len != 0) { - if (iv == NULL) - return 0; -# ifdef HAVE_EVP_CIPHER_CTX_IV - memcpy(iv, EVP_CIPHER_CTX_iv(ctx), len); -# else - memcpy(iv, ctx->iv, len); -# endif /* HAVE_EVP_CIPHER_CTX_IV */ - } - return 1; -} -#endif /* HAVE_EVP_CIPHER_CTX_GET_IV */ - -#ifndef HAVE_EVP_CIPHER_CTX_SET_IV -int -EVP_CIPHER_CTX_set_iv(EVP_CIPHER_CTX *ctx, const unsigned char *iv, size_t len) -{ - if (ctx == NULL) - return 0; - if (EVP_CIPHER_CTX_iv_length(ctx) < 0) - return 0; - if (len != (size_t)EVP_CIPHER_CTX_iv_length(ctx)) - return 0; - if (len > EVP_MAX_IV_LENGTH) - return 0; /* sanity check; shouldn't happen */ - /* - * Skip the memcpy entirely when the requested IV length is zero, - * since the iv pointer may be NULL or invalid. - */ - if (len != 0) { - if (iv == NULL) - return 0; -# ifdef HAVE_EVP_CIPHER_CTX_IV_NOCONST - memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), iv, len); -# else - memcpy(ctx->iv, iv, len); -# endif /* HAVE_EVP_CIPHER_CTX_IV_NOCONST */ - } - return 1; -} -#endif /* HAVE_EVP_CIPHER_CTX_SET_IV */ - -#endif /* WITH_OPENSSL */ diff -ruN openssh-9.4p1/openbsd-compat/Makefile.in openssh-9.4p1+x509-14.2.1/openbsd-compat/Makefile.in --- openssh-9.4p1/openbsd-compat/Makefile.in 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/openbsd-compat/Makefile.in 2023-08-20 10:07:01.000000000 +0300 @@ -1,21 +1,29 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +bindir=@bindir@ +libexecdir=@libexecdir@ sysconfdir=@sysconfdir@ -piddir=@piddir@ +sshcadir=@sshcadir@ srcdir=@srcdir@ top_srcdir=@top_srcdir@ VPATH=@srcdir@ +FIPSLD_CC=@FIPSLD_CC@ CC=@CC@ LD=@LD@ -CFLAGS=@CFLAGS@ -CFLAGS_NOPIE=@CFLAGS_NOPIE@ -CPPFLAGS=-I. -I.. -I$(srcdir) -I$(srcdir)/.. @CPPFLAGS@ @DEFS@ -PICFLAG=@PICFLAG@ +CFLAGS=@CFLAGS@ $(CFLAGS_EXTRA) +PATHDEFS=\ + -D_PATH_PREFIX=\"$(prefix)\" \ + -DSSHDIR=\"$(sysconfdir)\" \ + -DSSHCADIR=\"$(sshcadir)\" \ + -DSSHBINDIR=\"$(bindir)\" \ + -DSSHLIBEXECDIR=\"$(libexecdir)\" +CPPFLAGS=-I. -I.. -I$(srcdir) -I$(srcdir)/.. @CPPFLAGS@ @DEFS@ $(PATHDEFS) LIBS=@LIBS@ AR=@AR@ RANLIB=@RANLIB@ INSTALL=@INSTALL@ LDFLAGS=-L. @LDFLAGS@ -LDFLAGS_NOPIE=-L. -Lopenbsd-compat/ @LDFLAGS_NOPIE@ OPENBSD=arc4random.o \ arc4random_uniform.o \ @@ -66,7 +74,7 @@ timingsafe_bcmp.o \ vis.o -COMPAT= bsd-asprintf.o \ +COMPAT= bsd-asprintf.o \ bsd-closefrom.o \ bsd-cygwin_util.o \ bsd-err.o \ @@ -80,7 +88,6 @@ bsd-nextstep.o \ bsd-openpty.o \ bsd-poll.o \ - bsd-pselect.o \ bsd-setres_id.o \ bsd-signal.o \ bsd-snprintf.o \ @@ -91,19 +98,19 @@ getrrsetbyname-ldns.o \ kludge-fd_set.o \ openssl-compat.o \ - libressl-api-compat.o \ - xcrypt.o + xcrypt.o \ + xmd5crypt.o PORTS= port-aix.o \ + port-android.o \ port-irix.o \ port-linux.o \ - port-prngd.o \ port-solaris.o \ port-net.o \ port-uw.o .c.o: - $(CC) $(CFLAGS_NOPIE) $(PICFLAG) $(CPPFLAGS) -c $< + $(CC) $(CFLAGS) $(CPPFLAGS) -c $< all: libopenbsd-compat.a @@ -120,3 +127,8 @@ distclean: clean rm -f Makefile *~ + +# Usefull only if build is in source tree. +# Outside source tree (VPATH build) result is not correct. +depend: + makedepend -- $(CPPFLAGS) $(CFLAGS) -- $(srcdir)/*.c diff -ruN openssh-9.4p1/openbsd-compat/md5crypt.h openssh-9.4p1+x509-14.2.1/openbsd-compat/md5crypt.h --- openssh-9.4p1/openbsd-compat/md5crypt.h 1970-01-01 02:00:00.000000000 +0200 +++ openssh-9.4p1+x509-14.2.1/openbsd-compat/md5crypt.h 2023-08-20 10:07:00.000000000 +0300 @@ -0,0 +1,22 @@ +/* + * ---------------------------------------------------------------------------- + * "THE BEER-WARE LICENSE" (Revision 42): + * wrote this file. As long as you retain this notice you + * can do whatever you want with this stuff. If we meet some day, and you think + * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp + * ---------------------------------------------------------------------------- + */ + +#ifndef _MD5CRYPT_H +#define _MD5CRYPT_H + +#include "includes.h" + +#if defined(HAVE_MD5_PASSWORDS) && !defined(HAVE_MD5_CRYPT) + +int is_md5_salt(const char *); +char *md5_crypt(const char *, const char *); + +#endif /* defined(HAVE_MD5_PASSWORDS) && !defined(HAVE_MD5_CRYPT) */ + +#endif /* MD5CRYPT_H */ diff -ruN openssh-9.4p1/openbsd-compat/memmem.c openssh-9.4p1+x509-14.2.1/openbsd-compat/memmem.c --- openssh-9.4p1/openbsd-compat/memmem.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/openbsd-compat/memmem.c 2023-08-20 10:07:01.000000000 +0300 @@ -23,15 +23,13 @@ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* OPENBSD ORIGINAL: lib/libc/string/memmem.c */ - #include "includes.h" #ifndef HAVE_MEMMEM #include #ifdef HAVE_STDINT_H -#include +# include #endif static char * @@ -63,12 +61,6 @@ return hw == nw ? (char *)h-4 : 0; } -#if 0 -/* In -portable, defines.h ensures that these are already defined. */ -#define MAX(a,b) ((a)>(b)?(a):(b)) -#define MIN(a,b) ((a)<(b)?(a):(b)) -#endif - #define BITOP(a,b,op) \ ((a)[(size_t)(b)/(8*sizeof *(a))] op (size_t)1<<((size_t)(b)%(8*sizeof *(a)))) diff -ruN openssh-9.4p1/openbsd-compat/mktemp.c openssh-9.4p1+x509-14.2.1/openbsd-compat/mktemp.c --- openssh-9.4p1/openbsd-compat/mktemp.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/openbsd-compat/mktemp.c 2023-08-20 10:07:01.000000000 +0300 @@ -34,29 +34,6 @@ #include #include -#ifdef mkstemp -#undef mkstemp -#endif -int mkstemp(char *); - -/* - * From glibc man page: 'In glibc versions 2.06 and earlier, the file is - * created with permissions 0666, that is, read and write for all users.' - * Provide a wrapper to make sure the mask is reasonable (POSIX requires - * mode 0600, so mask off any other bits). - */ -int -_ssh_mkstemp(char *template) -{ - mode_t mask; - int ret; - - mask = umask(0177); - ret = mkstemp(template); - (void)umask(mask); - return ret; -} - #if !defined(HAVE_MKDTEMP) #define MKTEMP_NAME 0 @@ -98,7 +75,7 @@ switch (mode) { case MKTEMP_NAME: - if (lstat(path, &sb) != 0) + if (lstat(path, &sb) == -1) return(errno == ENOENT ? 0 : -1); break; case MKTEMP_FILE: diff -ruN openssh-9.4p1/openbsd-compat/openbsd-compat.h openssh-9.4p1+x509-14.2.1/openbsd-compat/openbsd-compat.h --- openssh-9.4p1/openbsd-compat/openbsd-compat.h 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/openbsd-compat/openbsd-compat.h 2023-08-20 10:07:00.000000000 +0300 @@ -2,6 +2,7 @@ * Copyright (c) 1999-2003 Damien Miller. All rights reserved. * Copyright (c) 2003 Ben Lindstrom. All rights reserved. * Copyright (c) 2002 Tim Rice. All rights reserved. + * Copyright (c) 2013-2022 Roumen Petrov. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -24,11 +25,11 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include "includes.h" + #ifndef _OPENBSD_COMPAT_H #define _OPENBSD_COMPAT_H -#include "includes.h" - #include #include @@ -48,11 +49,6 @@ #include "blf.h" #include "fnmatch.h" -#if defined(HAVE_LOGIN_CAP) && !defined(HAVE_LOGIN_GETPWCLASS) -# include -# define login_getpwclass(pw) login_getclass(pw->pw_class) -#endif - #ifndef HAVE_BASENAME char *basename(const char *path); #endif @@ -65,12 +61,13 @@ void closefrom(int); #endif -#if defined(HAVE_DECL_FTRUNCATE) && HAVE_DECL_FTRUNCATE == 0 +#if !HAVE_DECL_FTRUNCATE int ftruncate(int filedes, off_t length); #endif #ifndef HAVE_GETLINE #include +ssize_t getdelim(char **, size_t *, int, FILE *); ssize_t getline(char **, size_t *, FILE *); #endif @@ -86,7 +83,7 @@ int killpg(pid_t, int); #endif -#if defined(HAVE_DECL_MEMMEM) && HAVE_DECL_MEMMEM == 0 +#if !HAVE_DECL_MEMMEM void *memmem(const void *, size_t, const void *, size_t); #endif @@ -131,7 +128,7 @@ #endif #ifndef HAVE_STRPTIME -#include +# include char *strptime(const char *buf, const char *fmt, struct tm *tm); #endif @@ -141,9 +138,6 @@ char *mkdtemp(char *path); #endif -#define mkstemp(x) _ssh_mkstemp(x) -int _ssh_mkstemp(char *); - #ifndef HAVE_DAEMON int daemon(int nochdir, int noclose); #endif @@ -191,45 +185,50 @@ #include "openbsd-compat/getopt.h" #endif -#if ((defined(HAVE_DECL_READV) && HAVE_DECL_READV == 0) || \ - (defined(HAVE_DECL_WRITEV) && HAVE_DECL_WRITEV == 0)) +#if !HAVE_DECL_READV || !HAVE_DECL_WRITEV # include # include -# if defined(HAVE_DECL_READV) && HAVE_DECL_READV == 0 +# if !HAVE_DECL_READV int readv(int, struct iovec *, int); # endif -# if defined(HAVE_DECL_WRITEV) && HAVE_DECL_WRITEV == 0 +# if !HAVE_DECL_WRITEV int writev(int, struct iovec *, int); # endif #endif /* Home grown routines */ -#include "bsd-signal.h" #include "bsd-misc.h" #include "bsd-setres_id.h" +#include "bsd-signal.h" #include "bsd-statvfs.h" #include "bsd-waitpid.h" #include "bsd-poll.h" -#if defined(HAVE_DECL_GETPEEREID) && HAVE_DECL_GETPEEREID == 0 +#if !HAVE_DECL_GETPEEREID int getpeereid(int , uid_t *, gid_t *); #endif -#ifndef HAVE_ARC4RANDOM +#if !HAVE_DECL_ARC4RANDOM uint32_t arc4random(void); -#endif /* !HAVE_ARC4RANDOM */ +#endif + +#if !HAVE_DECL_ARC4RANDOM_STIR +void arc4random_stir(void); +#endif -#ifndef HAVE_ARC4RANDOM_BUF +#if !HAVE_DECL_ARC4RANDOM_BUF void arc4random_buf(void *, size_t); #endif -#ifndef HAVE_ARC4RANDOM_STIR -# define arc4random_stir() +#if !HAVE_DECL_ARC4RANDOM_UNIFORM +uint32_t arc4random_uniform(uint32_t); #endif -#ifndef HAVE_ARC4RANDOM_UNIFORM +#ifdef __ANDROID__ +/* defined but not declared */ +void arc4random_buf(void *, size_t); uint32_t arc4random_uniform(uint32_t); #endif @@ -239,7 +238,7 @@ #ifndef HAVE_OPENPTY # include /* for struct winsize */ -int openpty(int *, int *, char *, struct termios *, struct winsize *); +int openpty(int *, int *, char *, OPENPTY_CONST_ARG struct termios *, OPENPTY_CONST_ARG struct winsize *); #endif /* HAVE_OPENPTY */ #ifndef HAVE_SNPRINTF @@ -262,23 +261,17 @@ long long strtonum(const char *, long long, long long, const char **); #endif -/* multibyte character support */ #ifndef HAVE_MBLEN -# define mblen(x, y) (1) +int mblen(const char *s, size_t n); #endif #ifndef HAVE_WCWIDTH # define wcwidth(x) (((x) >= 0x20 && (x) <= 0x7e) ? 1 : -1) -/* force our no-op nl_langinfo and mbtowc */ +/* force our no-op nl_langinfo */ # undef HAVE_NL_LANGINFO -# undef HAVE_MBTOWC # undef HAVE_LANGINFO_H #endif -#ifndef HAVE_NL_LANGINFO -# define nl_langinfo(x) "" -#endif - #ifndef HAVE_MBTOWC int mbtowc(wchar_t *, const char*, size_t); #endif @@ -313,11 +306,11 @@ #endif #ifndef HAVE_USER_FROM_UID -char *user_from_uid(uid_t, int); +const char *user_from_uid(uid_t, int); #endif #ifndef HAVE_GROUP_FROM_GID -char *group_from_gid(gid_t, int); +const char *group_from_gid(gid_t, int); #endif #ifndef HAVE_TIMINGSAFE_BCMP @@ -337,12 +330,8 @@ void freezero(void *, size_t); #endif -#ifndef HAVE_LOCALTIME_R -struct tm *localtime_r(const time_t *, struct tm *); -#endif - #ifndef HAVE_TIMEGM -#include +# include time_t timegm(struct tm *); #endif @@ -356,6 +345,7 @@ #include "bsd-cygwin_util.h" #include "port-aix.h" +#include "port-android.h" #include "port-irix.h" #include "port-linux.h" #include "port-solaris.h" diff -ruN openssh-9.4p1/openbsd-compat/openssl-compat.c openssh-9.4p1+x509-14.2.1/openbsd-compat/openssl-compat.c --- openssh-9.4p1/openbsd-compat/openssl-compat.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/openbsd-compat/openssl-compat.c 2023-08-20 10:07:01.000000000 +0300 @@ -1,5 +1,6 @@ /* * Copyright (c) 2005 Darren Tucker + * Copyright (c) 2011-2023 Roumen Petrov. All rights reserved. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -14,7 +15,6 @@ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#define SSH_DONT_OVERLOAD_OPENSSL_FUNCS #include "includes.h" #ifdef WITH_OPENSSL @@ -26,18 +26,62 @@ # include # include #endif +#include #include "log.h" -#include "openssl-compat.h" +#include "evp-compat.h" +#ifndef HAVE_EVP_PKEY_PRINT_PARAMS +int +EVP_PKEY_print_params(BIO *out, const EVP_PKEY *pkey, + int indent, /*ASN1_PCTX*/void *pctx) +{ + int ret; + int evp_id = -1; + + UNUSED(indent); + UNUSED(pctx); + if (pkey == NULL) goto err; + + evp_id = EVP_PKEY_base_id(pkey); + switch (evp_id) { + case EVP_PKEY_DH: { + DH *dh = EVP_PKEY_get1_DH((EVP_PKEY*/*safe cast*/)pkey); + if (dh == NULL) goto err; + ret = DHparams_print(out, dh); + DH_free(dh); + } break; + /*TODO*/ + default: + goto err; + } + + return ret; + +err: + BIO_printf(out, "cannot print parameters for pkey type %d", evp_id); + return -1; +} +#endif + +/* Notes about new OpenSSL 3+ version scheme: + * Test for compatibility version is not applicable as new base version + * is assigned to all library symbols. With other words for any new major + * release, the version number for all symbols is automatically bumped + * to the new release's version number. Also minor releases should keep + * binary compatibility. + * Usable only if OS loader does not support symbol versioning. + */ /* * OpenSSL version numbers: MNNFFPPS: major minor fix patch status - * Versions >=3 require only major versions to match. - * For versions <3, we accept compatible fix versions (so we allow 1.0.1 - * to work with 1.0.0). Going backwards is only allowed within a patch series. + * Versions >= 3.0 require only major versions to match. + * For versions < 3.0, accept compatible fix versions, i.e. allow 1.0.1 + * to work with 1.0.0. + * Going backwards is only allowed within a patch series. * See https://www.openssl.org/policies/releasestrat.html */ +int ssh_compatible_openssl(long headerver, long libver); int ssh_compatible_openssl(long headerver, long libver) @@ -48,16 +92,20 @@ if (headerver == libver) return 1; - /* - * For versions >= 3.0, only the major and status must match. - */ + /* for versions >= 3.0, only the major,status must match */ if (headerver >= 0x3000000f) { mask = 0xf000000fL; /* major,status */ return (headerver & mask) == (libver & mask); } + /* for versions < 1.0.0, major,minor,fix,status must match */ + if (headerver < 0x1000000f) { + mask = 0xfffff00fL; /* major,minor,fix,status */ + return (headerver & mask) == (libver & mask); + } + /* - * For versions >= 1.0.0, but <3, major,minor,status must match and + * For versions >= 1.0.0, but < 3, major,minor,status must match and * library fix version must be equal to or newer than the header. */ mask = 0xfff0000fL; /* major,minor,status */ @@ -68,31 +116,158 @@ return 0; } + +int +ssh_FIPS_mode(int onoff) +{ +#ifdef OPENSSL_FIPS + int mode = FIPS_mode(); + + if (onoff && mode) + return(1); + + if (!onoff && !mode) + return(1); + + if (!FIPS_mode_set(onoff)) { + ssh_OpenSSL_load_error_strings(); + do_log_crypto_errors(SYSLOG_LEVEL_ERROR); + fatal("FIPS_mode_set(%s) failed", (onoff ? "on" : "off")); + } + +#if defined(OPENSSL_VERSION_NUMBER) && (OPENSSL_VERSION_NUMBER < 0x10000000L) + if(!onoff) + RAND_set_rand_method(NULL); +#endif + + return(1); + +#else /* ndef OPENSSL_FIPS */ + (void) onoff; + return(0); +#endif +} + + +#ifndef HAVE_OPENSSL_INIT_CRYPTO +# include +#endif +#ifdef OPENSSL_FIPS +# if HAVE_DECL_ERR_LOAD_FIPS_STRINGS +# ifdef HAVE_OPENSSL_FIPS_H +# include /* for ERR_load_FIPS_strings() */ +# endif +# else +void ERR_load_FIPS_strings(void); +# endif +#endif + void -ssh_libcrypto_init(void) +ssh_OpenSSL_load_error_strings(void) { +#ifdef HAVE_OPENSSL_INIT_CRYPTO + OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL); +#else + ERR_load_crypto_strings(); +#endif +#if defined(OPENSSL_FIPS) && defined(HAVE_ERR_LOAD_FIPS_STRINGS) +/* load explicitly as is not loaded in some vendor libraries */ + ERR_load_FIPS_strings(); +#endif +} + + +void +ssh_OpenSSL_startup() { -#if defined(HAVE_OPENSSL_INIT_CRYPTO) && \ - defined(OPENSSL_INIT_ADD_ALL_CIPHERS) && \ - defined(OPENSSL_INIT_ADD_ALL_DIGESTS) - OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS | - OPENSSL_INIT_ADD_ALL_DIGESTS, NULL); -#elif defined(HAVE_OPENSSL_ADD_ALL_ALGORITHMS) +#ifdef HAVE_OPENSSL_INIT_CRYPTO + OPENSSL_init_crypto( + #ifdef USE_OPENSSL_ENGINE + OPENSSL_INIT_ENGINE_ALL_BUILTIN | + #endif + OPENSSL_INIT_ADD_ALL_CIPHERS | + OPENSSL_INIT_ADD_ALL_DIGESTS | + OPENSSL_INIT_LOAD_CONFIG, NULL); + +#ifdef OPENSSL_FIPS + /* vendor OpenSSL 1.1 may support FIPS */ + if (getenv("OPENSSL_FIPS")) { + (void) ssh_FIPS_mode(1); + } +#endif +#else OpenSSL_add_all_algorithms(); + +#ifdef OPENSSL_FIPS + if (getenv("OPENSSL_FIPS")) { + (void) ssh_FIPS_mode(1); + } #endif #ifdef USE_OPENSSL_ENGINE +#if 0 +/* Next two calls are useless if link is with dynamic engine. Also + * they will initialize static engines and later OPENSSL_config load + * engines again. This double initialization could crash application, + * usually in application shutdown code (engine cleanup) even without + * use of engines. + */ /* Enable use of crypto hardware */ ENGINE_load_builtin_engines(); ENGINE_register_all_complete(); +#endif - /* Load the libcrypto config file to pick up engines defined there */ -# if defined(HAVE_OPENSSL_INIT_CRYPTO) && defined(OPENSSL_INIT_LOAD_CONFIG) - OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS | - OPENSSL_INIT_ADD_ALL_DIGESTS | OPENSSL_INIT_LOAD_CONFIG, NULL); -# else + /* OPENSSL_config will load buildin engines and engines + * specified in configuration file, i.e. method call + * ENGINE_load_builtin_engines. Latter is only for + * dynamic engines. + */ OPENSSL_config(NULL); -# endif -#endif /* USE_OPENSSL_ENGINE */ + + /* Starting from openssl 1.0.1 ENGINE_load_builtin_engines + * call ENGINE_register_all_complete internally. + * Application should request registration for compatibility + * with all previous versions and it is save to request again. + * Note that dynamic_path in openssl engine configuration + * may register engine as default. If engine methods are not + * usable as default methods use of non-engine keys may trigger + * error in sign/verify operation. + */ + ENGINE_register_all_complete(); +#endif /*def USE_OPENSSL_ENGINE*/ +#endif /*def HAVE_OPENSSL_INIT_CRYPTO*/ } + +void +ssh_OpenSSL_shuthdown() { +#ifdef HAVE_OPENSSL_CLEANUP + OPENSSL_cleanup(); +#else + /* clean configuration before engine: + * - it should clean internaly initialized engines */ + CONF_modules_unload(1); + /* engine may provide rand implementation: + * - lets clean rand before engines */ + RAND_cleanup(); +#ifndef OPENSSL_NO_ENGINE + ENGINE_cleanup(); +#endif + /* engine may use extra data so clean it after engines */ + CRYPTO_cleanup_all_ex_data(); + EVP_cleanup(); + OBJ_cleanup(); +#ifdef HAVE_ERR_REMOVE_THREAD_STATE + ERR_remove_thread_state(NULL); +#else + ERR_remove_state(0); +#endif + ERR_free_strings(); +#endif /*def HAVE_OPENSSL_INIT_CRYPTO*/ +} + +#else + +void ssh_OpenSSL_startup() {} +void ssh_OpenSSL_shuthdown() {} + #endif /* WITH_OPENSSL */ diff -ruN openssh-9.4p1/openbsd-compat/openssl-compat.h openssh-9.4p1+x509-14.2.1/openbsd-compat/openssl-compat.h --- openssh-9.4p1/openbsd-compat/openssl-compat.h 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/openbsd-compat/openssl-compat.h 2023-08-20 10:07:00.000000000 +0300 @@ -1,5 +1,6 @@ /* * Copyright (c) 2005 Darren Tucker + * Copyright (c) 2011-2021 Roumen Petrov. All rights reserved. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -23,60 +24,43 @@ #include #include #include -#include -#include -#ifdef OPENSSL_HAS_ECC -#include -#endif -#include - -int ssh_compatible_openssl(long, long); -void ssh_libcrypto_init(void); -#if (OPENSSL_VERSION_NUMBER < 0x10100000L) -# error OpenSSL 1.1.0 or greater is required -#endif -#ifdef LIBRESSL_VERSION_NUMBER -# if LIBRESSL_VERSION_NUMBER < 0x3010000fL -# error LibreSSL 3.1.0 or greater is required -# endif +#if defined(OPENSSL_VERSION_NUMBER) && (OPENSSL_VERSION_NUMBER < 0x00907000L) +# error "OpenSSL 0.9.7 or greater is required" #endif -#ifndef OPENSSL_RSA_MAX_MODULUS_BITS -# define OPENSSL_RSA_MAX_MODULUS_BITS 16384 -#endif -#ifndef OPENSSL_DSA_MAX_MODULUS_BITS -# define OPENSSL_DSA_MAX_MODULUS_BITS 10000 +#if defined(OPENSSL_VERSION_NUMBER) && (OPENSSL_VERSION_NUMBER < 0x10000000L) +# define LIBCRYPTO_EVP_INL_TYPE unsigned int +#else +# define LIBCRYPTO_EVP_INL_TYPE size_t #endif -#ifdef LIBRESSL_VERSION_NUMBER -# if LIBRESSL_VERSION_NUMBER < 0x3010000fL -# define HAVE_BROKEN_CHACHA20 -# endif -#endif -#ifdef OPENSSL_IS_BORINGSSL -/* - * BoringSSL (rightly) got rid of the BN_FLG_CONSTTIME flag, along with - * the entire BN_set_flags() interface. - * https://boringssl.googlesource.com/boringssl/+/0a211dfe9 - */ -# define BN_set_flags(a, b) +#ifndef HAVE_EVP_PKEY_PRINT_PARAMS +int EVP_PKEY_print_params(BIO *out, const EVP_PKEY *pkey, + int indent, /*ASN1_PCTX*/void *pctx); #endif -#ifndef HAVE_EVP_CIPHER_CTX_GET_IV -# ifdef HAVE_EVP_CIPHER_CTX_GET_UPDATED_IV -# define EVP_CIPHER_CTX_get_iv EVP_CIPHER_CTX_get_updated_iv -# else /* HAVE_EVP_CIPHER_CTX_GET_UPDATED_IV */ -int EVP_CIPHER_CTX_get_iv(const EVP_CIPHER_CTX *ctx, - unsigned char *iv, size_t len); -# endif /* HAVE_EVP_CIPHER_CTX_GET_UPDATED_IV */ -#endif /* HAVE_EVP_CIPHER_CTX_GET_IV */ - -#ifndef HAVE_EVP_CIPHER_CTX_SET_IV -int EVP_CIPHER_CTX_set_iv(EVP_CIPHER_CTX *ctx, - const unsigned char *iv, size_t len); -#endif /* HAVE_EVP_CIPHER_CTX_SET_IV */ +extern int ssh_FIPS_mode(int onoff); + +extern void ssh_OpenSSL_load_error_strings(void); + +extern void ssh_OpenSSL_startup(void); +extern void ssh_OpenSSL_shuthdown(void); #endif /* WITH_OPENSSL */ + +static inline const char* +ssh_OpenSSL_version_text(void) { +#ifndef WITH_OPENSSL + return "without OpenSSL"; +#else +# ifndef HAVE_OPENSSL_INIT_CRYPTO /* OpenSSL < 1.1 */ + return SSLeay_version(SSLEAY_VERSION); +# else + return OpenSSL_version(OPENSSL_VERSION); +# endif +#endif +} + #endif /* _OPENSSL_COMPAT_H */ diff -ruN openssh-9.4p1/openbsd-compat/port-aix.c openssh-9.4p1+x509-14.2.1/openbsd-compat/port-aix.c --- openssh-9.4p1/openbsd-compat/port-aix.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/openbsd-compat/port-aix.c 2023-08-20 10:07:01.000000000 +0300 @@ -31,7 +31,6 @@ #include "xmalloc.h" #include "sshbuf.h" #include "ssherr.h" -#include "sshkey.h" #include "hostfile.h" #include "auth.h" #include "ssh.h" @@ -206,8 +205,7 @@ if (msg && *msg) { if ((r = sshbuf_put(ctxt->loginmsg, msg, strlen(msg))) != 0) - fatal("%s: buffer error: %s", - __func__, ssh_err(r)); + fatal_fr(r, "buffer error"); aix_remove_embedded_newlines(msg); } debug3("AIX/passwdexpired returned %d msg %.100s", expired, msg); @@ -250,7 +248,7 @@ * loginrestrictions will always fail due to insufficient privilege). */ if (pw->pw_uid == 0 || geteuid() != 0) { - debug3("%s: not checking", __func__); + debug3_f("not checking"); return 1; } @@ -262,11 +260,11 @@ * in session.c after the nologin message is sent, so allow for now * and do not append the returned message. */ - if (result == -1 && errno == EPERM && stat(_PATH_NOLOGIN, &st) == 0) + if (result == -1 && errno == EPERM && stat(_PATH_NOLOGIN, &st) != -1) permitted = 1; else if (msg != NULL) { if ((r = sshbuf_put(loginmsg, msg, strlen(msg))) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "buffer error"); } if (msg == NULL) msg = xstrdup("(none)"); @@ -316,6 +314,8 @@ record_failed_login(struct ssh *ssh, const char *user, const char *hostname, const char *ttyname) { + UNUSED(ssh); + if (geteuid() != 0) return; @@ -343,7 +343,7 @@ char *registry; if (setuserdb(S_READ) == -1) { - debug3("%s: Could not open userdb to read", __func__); + debug3_f("could not open userdb to read"); return; } @@ -354,7 +354,7 @@ debug3("AIX/setauthdb set registry '%s' failed: %s", registry, strerror(errno)); } else - debug3("%s: Could not read S_REGISTRY for user: %s", __func__, + debug3_f("could not read S_REGISTRY for user: %s", strerror(errno)); enduserdb(); # endif /* HAVE_SETAUTHDB */ @@ -371,11 +371,9 @@ { # ifdef HAVE_SETAUTHDB if (setauthdb(old_registry, NULL) == 0) - debug3("%s: restoring old registry '%s'", __func__, - old_registry); + debug3_f("restoring old registry '%s'", old_registry); else - debug3("%s: failed to restore old registry %s", __func__, - old_registry); + debug3_f("failed to restore old registry %s", old_registry); # endif /* HAVE_SETAUTHDB */ } diff -ruN openssh-9.4p1/openbsd-compat/port-aix.h openssh-9.4p1+x509-14.2.1/openbsd-compat/port-aix.h --- openssh-9.4p1/openbsd-compat/port-aix.h 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/openbsd-compat/port-aix.h 2023-08-20 10:07:00.000000000 +0300 @@ -30,7 +30,6 @@ # include #endif -struct ssh; struct sshbuf; /* These should be in the system headers but are not. */ diff -ruN openssh-9.4p1/openbsd-compat/port-android.c openssh-9.4p1+x509-14.2.1/openbsd-compat/port-android.c --- openssh-9.4p1/openbsd-compat/port-android.c 1970-01-01 02:00:00.000000000 +0200 +++ openssh-9.4p1+x509-14.2.1/openbsd-compat/port-android.c 2023-08-20 10:07:01.000000000 +0300 @@ -0,0 +1,515 @@ +#ifdef __ANDROID__ +/* + * Copyright (c) 2016-2023 Roumen Petrov. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "includes.h" +#include +#include +#include +#include + +#include "pathnames.h" +extern char *__progname; + +#undef APP_DIR_VERSION +#if 1 +# define APP_DIR_VERSION 2 +#else +# define APP_DIR_VERSION 1 +#endif + +/* paths to application specific directories: */ +#if APP_DIR_VERSION == 1 +extern char *get_app_etcdir(void); +extern char *get_app_bindir(void); +extern char *get_app_libexecdir(void); +#endif + +#if APP_DIR_VERSION == 2 +extern char *get2_app_etcdir(const char *cmd); +extern char *get2_app_bindir(const char *cmd); +extern char *get2_app_libexecdir(const char *cmd); + +static inline char* +get_app_etcdir() { + return get2_app_etcdir(__progname); +} + +static inline char* +get_app_bindir() { + return get2_app_bindir(__progname); +} + +static inline char* +get_app_libexecdir() { + return get2_app_libexecdir(__progname); +} +#endif + +/* Obsolete package rule: + * Note it is expected binaries to be installed in $(prefix)/xbin. + * In $(prefix)/bin is installed wrapper script that set custom configuration + * like library patch and etc. and then execute real binary. + * + * API 29 requirement: untrusted application could execute binary + * located only in write protected path (SELinux rule). Only + * application library directory is write protected, so executable + * could be installed only into this directory. + * Also it must be renamed to libcmd-{name}.so for various reasons. + */ + +char* +ssh_get_progname(char *argv0) { + char *p, *q; + + UNUSED(argv0); + + q = strdup(__progname); + p = strrchr(q, '/'); + if (p != NULL) /*just in case*/ + *p++ = '\0'; + else + p = q; + + /* strip prefix */ + if (strncmp(p, "libcmd-", 7) == 0) + p += 7; + + p = strdup(p); + if (p == NULL) { + perror("strdup"); + exit(1); + } + free(q); + +{ /* strip suffix */ + size_t len = strlen(p); + if (len > 3) { + q = p + len - 3; + if (strcmp(q, ".so") == 0) + *q = '\0'; + } +} + + return p; +} + + +/* bionic stub replacement + * + * The function ttyname() returns a pointer to a pathname on success. + * On error, NULL is returned, and errno is set appropriately. + */ +char* +android_ttyname(int fd) { + static char buf[PATH_MAX]; + + return (android_ttyname_r(fd, buf, sizeof(buf)) == 0) + ? buf + : NULL; +} + + +/* bionic stub replacement + * + * The function ttyname_r() returns 0 on success, and an error number + * upon error. + */ +int +android_ttyname_r(int fd, char *buf, size_t buflen) { + ssize_t k; + + if (buf == NULL) { + errno = EINVAL; + return errno; + } + if (buflen < 6) { /* "/dev/" + NUL */ + errno = ERANGE; + return errno; + } + + if (!isatty(fd)) { + return errno; + } + +{ + char proc_fd[PATH_MAX]; + snprintf(proc_fd, sizeof(proc_fd), "/proc/self/fd/%d", fd); + /*NOTE on error content of buf is undefined*/ + k = readlink(proc_fd, buf, buflen); +} + + if (k == -1) + return errno; + + if ((size_t)k == buflen) { + errno = ERANGE; + return errno; + } + buf[k] = '\0'; + return 0; +} + + +/* Function endgrent is declared in platform header , + * but not defined until API 26. + * Unified header does not declare it before API 26. + */ +void +endgrent(void) { +} + +/* Function endpwent is declared in platform header , + * but not defined until API 26. + * Unified header does not declare it before API 26. + */ +void +endpwent(void) { +} + + +/* For untrusted applications new Android SELinux rules (API 29) + * allows execution only from write protected directories. + * Only application library directory is write protected. + * In consequence executable must be packaged into it and with + * name is a specific pattern. + * On old versions for some reasons application could install + * executable outside libdir. + * So instead to relocate executable to "lib" directory let + * relocate "bin" and "libexec". + */ +static int/*bool*/ +relocate_etcdir(const char *pathname, char *pathbuf, size_t pathlen) { + size_t len = strlen(SSHDIR); + + if (pathlen <= len) return 0; + if (strncmp(pathname, SSHDIR, len) != 0) return 0; + +{ const char *appdir = NULL; + if (appdir == NULL) appdir = get_app_etcdir(); + if (appdir == NULL) return 0; + + len = snprintf(pathbuf, pathlen, "%s%s", appdir, pathname + len); +} + + return len <= pathlen; +} + +static int/*bool*/ +relocate_bindir(const char *pathname, char *pathbuf, size_t pathlen) { + size_t len = strlen(SSHBINDIR); + + if (pathlen <= len) return 0; + if (strncmp(pathname, SSHBINDIR, len) != 0) return 0; + +{ static const char *appdir = NULL; + if (appdir == NULL) appdir = get_app_bindir(); + if (appdir == NULL) return 0; + + /* in release build package manager extract only lib*.so + * binaries. To distinguish executables let package them + * in format "libcmd-{name}.so". + */ + len = snprintf(pathbuf, pathlen, "%s/libcmd-%s.so", + appdir, pathname + len + 1/*exclude separator*/); +} + + return len <= pathlen; +} + +static int/*bool*/ +relocate_libexecdir(const char *pathname, char *pathbuf, size_t pathlen) { + size_t len = strlen(SSHLIBEXECDIR); + + if (pathlen <= len) return 0; + if (strncmp(pathname, SSHLIBEXECDIR, len) != 0) return 0; + +{ static const char *appdir = NULL; + if (appdir == NULL) appdir = get_app_libexecdir(); + if (appdir == NULL) return 0; + + /* same as bindir */ + len = snprintf(pathbuf, pathlen, "%s/libcmd-%s.so", + appdir, pathname + len + 1/*exclude separator*/); +} + + return len <= pathlen; +} + +const char* +relocate_path(const char *pathname, char *pathbuf, size_t pathlen) { + + if (relocate_etcdir(pathname, pathbuf, pathlen) || + relocate_bindir(pathname, pathbuf, pathlen) || + relocate_libexecdir(pathname, pathbuf, pathlen)) { + return pathbuf; + } + + return pathname; +} + + +extern int __real_open(const char *path, int flags, mode_t mode); + +int +__wrap_open(const char *path, int flags, mode_t mode) { + char r_path[PATH_MAX]; + + path = relocate_path(path, r_path, sizeof(r_path)); + return __real_open(path, flags, mode); +} + + +extern FILE* __real_fopen(const char *path, const char *mode); + +FILE* +__wrap_fopen(const char *path, const char *mode) { + char r_path[PATH_MAX]; + + path = relocate_path(path, r_path, sizeof(r_path)); + return __real_fopen(path, mode); +} + + +extern int __real_rename(const char *oldpath, const char *newpath); + +int +__wrap_rename(const char *oldpath, const char *newpath) { + char r_oldpath[PATH_MAX], r_newpath[PATH_MAX]; + + oldpath = relocate_path(oldpath, r_oldpath, sizeof(r_oldpath)); + newpath = relocate_path(newpath, r_newpath, sizeof(r_newpath)); + + return __real_rename(oldpath, newpath); +} + + +/* Fake user for android */ +#include "xmalloc.h" +#include +#include +#undef getpwnam +#undef getpwuid +/* Remove inappropriate definition from android unified headers! */ +#undef pw_gecos + +/* Note _PATH_PASSWD is defined in platform headers but not in unified. + * Force use of local declaration for consistency. + */ +#undef _PATH_PASSWD +#define _PATH_PASSWD "/etc/passwd" + + +static struct passwd *fake_passwd = NULL; +static char *ssh_home = NULL; +static char *ssh_shell = NULL; + + +static void +parse_fake_passwd() { + char *pw_name; + char *pw_passwd; + char *pw_uid; + char *pw_gid; + char *pw_gecos; + char *pw_dir; + char *pw_shell = NULL; + + int fd = -1; + +{ const char *path = _PATH_PREFIX _PATH_PASSWD; + + fd = open(path, O_RDONLY); + if (fd == -1) + return; +} + +{ /* parse password line */ + char buf[1024], *s; + + if (read(fd, buf, sizeof(buf)) <= 0) { + close(fd); + return; + } + + if ((s = strchr(buf, '\r')) != NULL) *s = '\0'; + if ((s = strchr(buf, '\n')) != NULL) *s = '\0'; + if ((s = strchr(buf, '\t')) != NULL) *s = '\0'; + if ((s = strchr(buf, ' ' )) != NULL) *s = '\0'; + + s = buf; + + pw_name = s; + if (*pw_name == '\0') goto parse_err; + s = strchr(s, ':'); if (s == NULL) goto parse_err; + *s = '\0'; + + pw_passwd = ++s; + if (*pw_passwd == '\0') goto parse_err; + s = strchr(s, ':'); if (s == NULL) goto parse_err; + *s = '\0'; + + pw_uid = ++s; + s = strchr(s, ':'); if (s == NULL) goto parse_err; + *s = '\0'; + + pw_gid = ++s; + s = strchr(s, ':'); if (s == NULL) goto parse_err; + *s = '\0'; + + pw_gecos = ++s; + s = strchr(s, ':'); if (s == NULL) goto parse_err; + *s = '\0'; + + pw_dir = ++s; + if (*pw_dir == '\0') goto parse_err; + s = strchr(s, ':'); if (s == NULL) goto parse_err; + *s = '\0'; + + pw_shell = ++s; + +parse_err: + close(fd); +} + + if (pw_shell == NULL) return; + +{ /* preset password data */ + char *s; + + s = strdup(pw_name); + if (s != NULL) + fake_passwd->pw_name = s; + + s = strdup(pw_passwd); + if (s != NULL) + fake_passwd->pw_passwd = s; + + (void) pw_uid; + (void) pw_gid; +#ifdef __LP64__ + fake_passwd->pw_gecos = strdup(pw_gecos); +#else + (void) pw_gecos; +#endif + + if (strcmp(pw_dir, "$HOME") == 0) + pw_dir = getenv("HOME"); + if ((pw_dir != NULL) && (*pw_dir != '\0')) + ssh_home = strdup(pw_dir); + if (ssh_home != NULL) + fake_passwd->pw_dir = ssh_home; + + if (strcmp(pw_shell, "$SHELL") == 0) + pw_shell = getenv("SHELL"); + if ((pw_shell != NULL) && (*pw_shell != '\0')) + ssh_shell = strdup(pw_shell); + if (ssh_shell != NULL) + fake_passwd->pw_shell = ssh_shell; +} +} + + +static void +init_fake_passwd() { + + if (fake_passwd != NULL) return; + +{ + struct passwd* pw; + size_t n; + + pw = getpwuid(getuid()); + if (pw == NULL) return; + + n = sizeof(*fake_passwd); + fake_passwd = calloc(1, n); + if (fake_passwd == NULL) return; + + memcpy(fake_passwd, pw, n); +} + + parse_fake_passwd(); +} + + +static struct passwd* +preset_passwd(struct passwd *pw) { + if (pw == NULL) return NULL; + +#ifdef __LP64__ + /* usually not initialized but code expect string value */ + if (pw->pw_gecos == NULL) + pw->pw_gecos = fake_passwd->pw_gecos; +#endif + + if (ssh_home != NULL) + pw->pw_dir = ssh_home; + + if (ssh_shell != NULL) + pw->pw_shell = ssh_shell; + + return pw; +} + + +/* bionic replacement */ +struct passwd* +android_getpwnam(const char* name) { + struct passwd* pw; + + init_fake_passwd(); + + if ((fake_passwd != NULL) && (strcmp(name, fake_passwd->pw_name) == 0)) + return fake_passwd; + + pw = getpwnam(name); + + return preset_passwd(pw); +} + + +/* bionic replacement */ +struct passwd* +android_getpwuid(uid_t uid) { + struct passwd* pw; + + init_fake_passwd(); + + if ((fake_passwd != NULL) && (uid == fake_passwd->pw_uid)) + return fake_passwd; + + pw = getpwuid(uid); + + return preset_passwd(pw); +} + + +#else + +static void *empty_translation_unit = &empty_translation_unit; + +#endif /*def __ANDROID__*/ diff -ruN openssh-9.4p1/openbsd-compat/port-android.h openssh-9.4p1+x509-14.2.1/openbsd-compat/port-android.h --- openssh-9.4p1/openbsd-compat/port-android.h 1970-01-01 02:00:00.000000000 +0200 +++ openssh-9.4p1+x509-14.2.1/openbsd-compat/port-android.h 2023-08-20 10:07:00.000000000 +0300 @@ -0,0 +1,47 @@ +#ifdef __ANDROID__ +/* + * Copyright (c) 2016-2019, Roumen Petrov + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef PORT_ANDROID_H + +char *android_ttyname(int fd); +#define ttyname android_ttyname +int android_ttyname_r(int fd, char *buf, size_t buflen); +#define ttyname_r android_ttyname_r + + +#include + +struct passwd* android_getpwnam(const char*); +#define getpwnam android_getpwnam +struct passwd* android_getpwuid(uid_t); +#define getpwuid android_getpwuid + +const char* relocate_path(const char *pathname, char *pathbuf, size_t pathlen); + +#endif /*ndef PORT_ANDROID_H*/ +#endif /*def __ANDROID__*/ diff -ruN openssh-9.4p1/openbsd-compat/port-linux.c openssh-9.4p1+x509-14.2.1/openbsd-compat/port-linux.c --- openssh-9.4p1/openbsd-compat/port-linux.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/openbsd-compat/port-linux.c 2023-08-20 10:07:01.000000000 +0300 @@ -56,7 +56,7 @@ } /* Return the default security context for the given username */ -static char * +static char* ssh_selinux_getctxbyname(char *pwname) { char *sc = NULL, *sename = NULL, *lvl = NULL; @@ -79,17 +79,17 @@ if (r != 0) { switch (security_getenforce()) { case -1: - fatal("%s: ssh_selinux_getctxbyname: " - "security_getenforce() failed", __func__); + fatal_f("ssh_selinux_getctxbyname: " + "security_getenforce() failed"); case 0: - error("%s: Failed to get default SELinux security " - "context for %s", __func__, pwname); + error_f("failed to get default SELinux security " + "context for %s", pwname); sc = NULL; break; default: - fatal("%s: Failed to get default SELinux security " + fatal_f("failed to get default SELinux security " "context for %s (in enforcing mode)", - __func__, pwname); + pwname); } } @@ -110,26 +110,26 @@ if (!ssh_selinux_enabled()) return; - debug3("%s: setting execution context", __func__); + debug3_f("setting execution context"); user_ctx = ssh_selinux_getctxbyname(pwname); if (setexeccon(user_ctx) != 0) { switch (security_getenforce()) { case -1: - fatal("%s: security_getenforce() failed", __func__); + fatal_f("security_getenforce() failed"); case 0: - error("%s: Failed to set SELinux execution " - "context for %s", __func__, pwname); + error_f("failed to set SELinux execution " + "context for %s", pwname); break; default: - fatal("%s: Failed to set SELinux execution context " - "for %s (in enforcing mode)", __func__, pwname); + fatal_f("failed to set SELinux execution context " + "for %s (in enforcing mode)", pwname); } } if (user_ctx != NULL) freecon(user_ctx); - debug3("%s: done", __func__); + debug3_f("done"); } /* Set the TTY context for the specified user */ @@ -142,29 +142,28 @@ if (!ssh_selinux_enabled()) return; - debug3("%s: setting TTY context on %s", __func__, tty); + debug3_f("setting TTY context on %s", tty); user_ctx = ssh_selinux_getctxbyname(pwname); /* XXX: should these calls fatal() upon failure in enforcing mode? */ if (getfilecon(tty, &old_tty_ctx) == -1) { - error("%s: getfilecon: %s", __func__, strerror(errno)); + error_f("getfilecon: %s", strerror(errno)); goto out; } if ((chrclass = string_to_security_class("chr_file")) == 0) { - error("%s: couldn't get security class for chr_file", __func__); + error_f("couldn't get security class for chr_file"); goto out; } if (security_compute_relabel(user_ctx, old_tty_ctx, chrclass, &new_tty_ctx) != 0) { - error("%s: security_compute_relabel: %s", - __func__, strerror(errno)); + error_f("security_compute_relabel: %s", strerror(errno)); goto out; } if (setfilecon(tty, new_tty_ctx) != 0) - error("%s: setfilecon: %s", __func__, strerror(errno)); + error_f("setfilecon: %s", strerror(errno)); out: if (new_tty_ctx != NULL) freecon(new_tty_ctx); @@ -172,26 +171,26 @@ freecon(old_tty_ctx); if (user_ctx != NULL) freecon(user_ctx); - debug3("%s: done", __func__); + debug3_f("done"); } void ssh_selinux_change_context(const char *newname) { - char *oldctx, *newctx, *cx, *cx2; + char *oldctx, *newctx, *cx; LogLevel log_level = SYSLOG_LEVEL_INFO; if (!ssh_selinux_enabled()) return; if (getcon(&oldctx) < 0) { - logit_f("getcon failed with %s", strerror(errno)); + error_f("getcon failed with %s", strerror(errno)); return; } if ((cx = strchr(oldctx, ':')) == NULL || (cx = strchr(cx + 1, ':')) == NULL || (cx - oldctx) >= INT_MAX) { - logit_f("unparsable context %s", oldctx); + error_f("unparsable context %s", oldctx); return; } @@ -203,10 +202,10 @@ sizeof(SSH_SELINUX_UNCONFINED_TYPE) - 1) == 0) log_level = SYSLOG_LEVEL_DEBUG3; - cx2 = strchr(cx + 1, ':'); +{ char *cx2 = strchr(cx + 1, ':'); xasprintf(&newctx, "%.*s%s%s", (int)(cx - oldctx + 1), oldctx, newname, cx2 == NULL ? "" : cx2); - +} debug3_f("setting context from '%s' to '%s'", oldctx, newctx); if (setcon(newctx) < 0) do_log2_f(log_level, "setcon %s from %s failed with %s", @@ -266,8 +265,8 @@ int i, value; FILE *fp; - debug3("%s", __func__); - for (i = 0; oom_adjust[i].path != NULL; i++) { + debug3_f("entering"); + for (i = 0; oom_adjust[i].path != NULL; i++) { oom_adj_path = oom_adjust[i].path; value = oom_adjust[i].value; if ((fp = fopen(oom_adj_path, "r+")) != NULL) { @@ -296,7 +295,7 @@ { FILE *fp; - debug3("%s", __func__); + debug3_f("entering"); if (oom_adj_save == INT_MIN || oom_adj_path == NULL || (fp = fopen(oom_adj_path, "w")) == NULL) return; diff -ruN openssh-9.4p1/openbsd-compat/port-net.c openssh-9.4p1+x509-14.2.1/openbsd-compat/port-net.c --- openssh-9.4p1/openbsd-compat/port-net.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/openbsd-compat/port-net.c 2023-08-20 10:07:01.000000000 +0300 @@ -26,11 +26,11 @@ #include #include #include -#include #include #include #include "openbsd-compat/sys-queue.h" +#include "xmalloc.h" #include "log.h" #include "misc.h" #include "sshbuf.h" @@ -54,8 +54,8 @@ socklen_t len = sizeof(dev) - 1; if (getsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, dev, &len) == -1) { - error("%s: cannot determine VRF for fd=%d : %s", - __func__, fd, strerror(errno)); + error_f("cannot determine VRF for fd=%d : %s", + fd, strerror(errno)); return NULL; } dev[len] = '\0'; @@ -67,8 +67,8 @@ { if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, name, strlen(name)) == -1) { - error("%s: setsockopt(%d, SO_BINDTODEVICE, %s): %s", - __func__, fd, name, strerror(errno)); + error_f("setsockopt(%d, SO_BINDTODEVICE, %s): %s", + fd, name, strerror(errno)); return -1; } return 0; @@ -117,7 +117,7 @@ void sys_set_process_rdomain(const char *name) { - fatal("%s: not supported", __func__); + fatal_f("not supported"); } #endif /* defined(SYS_RDOMAIN_XXX) */ @@ -128,6 +128,7 @@ * * SSH_TUN_LINUX Use the (newer) Linux tun/tap device * SSH_TUN_FREEBSD Use the FreeBSD tun/tap device + * SSH_TUN_DARWIN Use the Darwin utun device * SSH_TUN_COMPAT_AF Translate the OpenBSD address family * SSH_TUN_PREPEND_AF Prepend/remove the address family */ @@ -138,7 +139,11 @@ #if defined(SSH_TUN_LINUX) #include +#ifdef __ANDROID__ +#define TUN_CTRL_DEV "/dev/tun" +#else #define TUN_CTRL_DEV "/dev/net/tun" +#endif int sys_tun_open(int tun, int mode, char **ifname) @@ -150,12 +155,12 @@ if (ifname != NULL) *ifname = NULL; if ((fd = open(TUN_CTRL_DEV, O_RDWR)) == -1) { - debug("%s: failed to open tunnel control device \"%s\": %s", - __func__, TUN_CTRL_DEV, strerror(errno)); + debug_f("failed to open tunnel control device \"%s\": %s", + TUN_CTRL_DEV, strerror(errno)); return (-1); } - bzero(&ifr, sizeof(ifr)); + memset(&ifr, 0, sizeof(ifr)); if (mode == SSH_TUNMODE_ETHERNET) { ifr.ifr_flags = IFF_TAP; @@ -168,26 +173,26 @@ if (tun != SSH_TUNID_ANY) { if (tun > SSH_TUNID_MAX) { - debug("%s: invalid tunnel id %x: %s", __func__, - tun, strerror(errno)); + debug_f("invalid tunnel id %x: %s", tun, + strerror(errno)); goto failed; } snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), name, tun); } if (ioctl(fd, TUNSETIFF, &ifr) == -1) { - debug("%s: failed to configure tunnel (mode %d): %s", __func__, - mode, strerror(errno)); + debug_f("failed to configure tunnel (mode %d): %s", mode, + strerror(errno)); goto failed; } if (tun == SSH_TUNID_ANY) - debug("%s: tunnel mode %d fd %d", __func__, mode, fd); + debug_f("tunnel mode %d fd %d", mode, fd); else - debug("%s: %s mode %d fd %d", __func__, ifr.ifr_name, mode, fd); + debug_f("%s mode %d fd %d", ifr.ifr_name, mode, fd); - if (ifname != NULL && (*ifname = strdup(ifr.ifr_name)) == NULL) - goto failed; + if (ifname != NULL) + *ifname = xstrdup(ifr.ifr_name); return (fd); @@ -212,16 +217,13 @@ char name[100]; int fd = -1, sock; const char *tunbase = "tun"; -#if defined(TUNSIFHEAD) && !defined(SSH_TUN_PREPEND_AF) - int flag; -#endif if (ifname != NULL) *ifname = NULL; if (mode == SSH_TUNMODE_ETHERNET) { #ifdef SSH_TUN_NO_L2 - debug("%s: no layer 2 tunnelling support", __func__); + debug_f("no layer 2 tunnelling support"); return (-1); #else tunbase = "tap"; @@ -240,28 +242,27 @@ break; } } else { - debug("%s: invalid tunnel %u\n", __func__, tun); + debug_f("invalid tunnel %u", tun); return (-1); } - if (fd < 0) { - debug("%s: %s open failed: %s", __func__, name, - strerror(errno)); + if (fd == -1) { + debug_f("%s open failed: %s", name, strerror(errno)); return (-1); } /* Turn on tunnel headers */ #if defined(TUNSIFHEAD) && !defined(SSH_TUN_PREPEND_AF) - flag = 1; +{ int flag = 1; if (mode != SSH_TUNMODE_ETHERNET && ioctl(fd, TUNSIFHEAD, &flag) == -1) { - debug("%s: ioctl(%d, TUNSIFHEAD, 1): %s", __func__, fd, - strerror(errno)); + debug_f("ioctl(%d, TUNSIFHEAD, 1): %s", fd, strerror(errno)); close(fd); } +} #endif - debug("%s: %s mode %d fd %d", __func__, name, mode, fd); + debug_f("%s mode %d fd %d", name, mode, fd); /* Set the tunnel device operation mode */ snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s%d", tunbase, tun); @@ -276,8 +277,8 @@ goto failed; } - if (ifname != NULL && (*ifname = strdup(ifr.ifr_name)) == NULL) - goto failed; + if (ifname != NULL) + *ifname = xstrdup(ifr.ifr_name); close(sock); return (fd); @@ -287,12 +288,79 @@ close(fd); if (sock >= 0) close(sock); - debug("%s: failed to set %s mode %d: %s", __func__, name, - mode, strerror(errno)); + debug_f("failed to set %s mode %d: %s", name, mode, strerror(errno)); return (-1); } #endif /* SSH_TUN_FREEBSD */ +#ifdef SSH_TUN_DARWIN +#include +#include +#include + +int +sys_tun_open(int tun, int mode, char **ifname) +{ + struct ctl_info info; + struct sockaddr_ctl addr; + int fd; + + if (ifname != NULL) + *ifname = NULL; + + if (tun != SSH_TUNID_ANY && tun > SSH_TUNID_MAX) { + debug_f("invalid tunnel %u", tun); + return (-1); + } + + if (mode == SSH_TUNMODE_ETHERNET) { + debug_f("no layer 2 tunnelling support"); + return (-1); + } + + fd = socket(PF_SYSTEM, SOCK_DGRAM, SYSPROTO_CONTROL); + if (fd == -1) { + debug_f("failed to create control socket: %s", + strerror(errno)); + return (-1); + } + + memset(&info, 0, sizeof(info)); + strlcpy(info.ctl_name, UTUN_CONTROL_NAME, sizeof(info.ctl_name)); + if (ioctl(fd, CTLIOCGINFO, &info) == -1) { + debug_f("failed to lookup utun control id: %s", + strerror(errno)); + goto failed; + } + + memset(&addr, 0, sizeof(addr)); + addr.sc_id = info.ctl_id; + addr.sc_len = sizeof(addr); + addr.sc_family = AF_SYSTEM; + addr.ss_sysaddr = AF_SYS_CONTROL; + if (tun != SSH_TUNID_ANY) + addr.sc_unit = tun + 1; + + if (connect(fd, (struct sockaddr *)&addr, sizeof(addr)) == -1) { + debug_f("failed to connect to utun device: %s", + strerror(errno)); + goto failed; + } + + if (ifname != NULL) { + char buf[20]; + snprintf(buf, sizeof(buf), "tun%d", addr.sc_unit); + *ifname = xstrdup(buf); + } + + return (fd); + + failed: + close(fd); + return (-1); +} +#endif /* SSH_TUN_DARWIN */ + /* * System-specific channel filters */ @@ -305,6 +373,17 @@ #define OPENBSD_AF_INET 2 #define OPENBSD_AF_INET6 24 +#if defined(SSH_TUN_PREPEND_AF) +/* read buffer size */ +/* NOTE keep synchronised with channels.c */ +#if defined(HAVE_CYGWIN) && !defined(CHAN_RBUF) /* unused */ +# define CHAN_RBUF (64*1024) +#endif +# ifndef CHAN_RBUF +# define CHAN_RBUF (4*1024) +# endif +#endif + int sys_tun_infilter(struct ssh *ssh, struct Channel *c, char *buf, int _len) { @@ -319,6 +398,7 @@ u_int32_t af; #endif + UNUSED(ssh); /* XXX update channel input filter API to use unsigned length */ if (_len < 0) return -1; @@ -345,7 +425,7 @@ #endif if ((r = sshbuf_put_string(c->input, ptr, len)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "buffer error"); return (0); } @@ -357,9 +437,10 @@ u_int32_t af; int r; + UNUSED(ssh); /* XXX new API is incompatible with this signature. */ if ((r = sshbuf_get_string(c->output, data, dlen)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "buffer error"); if (*dlen < sizeof(af)) return (NULL); buf = *data; diff -ruN openssh-9.4p1/openbsd-compat/port-net.h openssh-9.4p1+x509-14.2.1/openbsd-compat/port-net.h --- openssh-9.4p1/openbsd-compat/port-net.h 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/openbsd-compat/port-net.h 2023-08-20 10:07:00.000000000 +0300 @@ -1,5 +1,6 @@ /* * Copyright (c) 2005 Reyk Floeter + * Copyright (c) 2020 Roumen Petrov. All rights reserved. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -20,7 +21,8 @@ struct Channel; struct ssh; -#if defined(SSH_TUN_LINUX) || defined(SSH_TUN_FREEBSD) +#if defined(SSH_TUN_LINUX) || defined(SSH_TUN_FREEBSD) || \ + defined(SSH_TUN_DARWIN) # define CUSTOM_SYS_TUN_OPEN int sys_tun_open(int, int, char **); #endif @@ -45,4 +47,14 @@ void sys_set_process_rdomain(const char *name); #endif +#ifndef HAVE_SYS_SET_PROCESS_RDOMAIN +# ifdef __OpenBSD__ +# define HAVE_SETRTABLE +# endif +#endif + +#if defined(HAVE_SYS_SET_PROCESS_RDOMAIN) || defined(HAVE_SETRTABLE) +# defined ENABLE_ROUTING_DOMAIN +#endif + #endif diff -ruN openssh-9.4p1/openbsd-compat/port-prngd.c openssh-9.4p1+x509-14.2.1/openbsd-compat/port-prngd.c --- openssh-9.4p1/openbsd-compat/port-prngd.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/openbsd-compat/port-prngd.c 2023-08-20 10:07:01.000000000 +0300 @@ -1,5 +1,6 @@ /* * Copyright (c) 2001 Damien Miller. All rights reserved. + * Copyright (c) 2021 Roumen Petrov. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -44,7 +45,9 @@ #include "misc.h" #include "log.h" -#if defined(PRNGD_PORT) || defined(PRNGD_SOCKET) +#ifndef OPENSSL_PRNG_ONLY +extern int seed_from_prngd(unsigned char *buf, size_t bytes); + /* * EGD/PRNGD interface. * @@ -145,7 +148,6 @@ close(fd); return rval; } -#endif /* PRNGD_PORT || PRNGD_SOCKET */ int seed_from_prngd(unsigned char *buf, size_t bytes) @@ -162,3 +164,8 @@ #endif return -1; } +#else /* OPENSSL_PRNG_ONLY */ + +typedef int port_prngd_empty_translation_unit; + +#endif /* OPENSSL_PRNG_ONLY */ diff -ruN openssh-9.4p1/openbsd-compat/port-solaris.c openssh-9.4p1+x509-14.2.1/openbsd-compat/port-solaris.c --- openssh-9.4p1/openbsd-compat/port-solaris.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/openbsd-compat/port-solaris.c 2023-08-20 10:07:01.000000000 +0300 @@ -14,10 +14,8 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include "config.h" #include "includes.h" -#include #include #include @@ -50,18 +48,18 @@ ct_stathdl_t stathdl; if ((stat_fd = open64(CT_LATEST, O_RDONLY)) == -1) { - error("%s: Error opening 'latest' process " - "contract: %s", __func__, strerror(errno)); + error_f("error opening 'latest' process contract: %s" + strerror(errno)); return -1; } if (ct_status_read(stat_fd, CTD_COMMON, &stathdl) != 0) { - error("%s: Error reading process contract " - "status: %s", __func__, strerror(errno)); + error_f("error reading process contract status: %s", + strerror(errno)); goto out; } if ((ctid = ct_status_get_id(stathdl)) < 0) { - error("%s: Error getting process contract id: %s", - __func__, strerror(errno)); + error_f("error getting process contract id: %s", + strerror(errno)); goto out; } @@ -75,40 +73,38 @@ solaris_contract_pre_fork(void) { if ((tmpl_fd = open64(CT_TEMPLATE, O_RDWR)) == -1) { - error("%s: open %s: %s", __func__, - CT_TEMPLATE, strerror(errno)); + error_f("open %s: %s", CT_TEMPLATE, strerror(errno)); return; } - debug2("%s: setting up process contract template on fd %d", - __func__, tmpl_fd); + debug3_f("setting up process contract template on fd %d", tmpl_fd); /* First we set the template parameters and event sets. */ if (ct_pr_tmpl_set_param(tmpl_fd, CT_PR_PGRPONLY) != 0) { - error("%s: Error setting process contract parameter set " - "(pgrponly): %s", __func__, strerror(errno)); + error_f("error setting process contract parameter set " + "(pgrponly): %s", strerror(errno)); goto fail; } if (ct_pr_tmpl_set_fatal(tmpl_fd, CT_PR_EV_HWERR) != 0) { - error("%s: Error setting process contract template " - "fatal events: %s", __func__, strerror(errno)); + error_f("error setting process contract template " + "fatal events: %s", strerror(errno)); goto fail; } if (ct_tmpl_set_critical(tmpl_fd, 0) != 0) { - error("%s: Error setting process contract template " - "critical events: %s", __func__, strerror(errno)); + error_f("error setting process contract template " + "critical events: %s", strerror(errno)); goto fail; } if (ct_tmpl_set_informative(tmpl_fd, CT_PR_EV_HWERR) != 0) { - error("%s: Error setting process contract template " - "informative events: %s", __func__, strerror(errno)); + error_f("error setting process contract template " + "informative events: %s", strerror(errno)); goto fail; } /* Now make this the active template for this process. */ if (ct_tmpl_activate(tmpl_fd) != 0) { - error("%s: Error activating process contract " - "template: %s", __func__, strerror(errno)); + error_f("error activating process contract template: %s", + strerror(errno)); goto fail; } return; @@ -123,13 +119,12 @@ void solaris_contract_post_fork_child() { - debug2("%s: clearing process contract template on fd %d", - __func__, tmpl_fd); + debug3_f("clearing process contract template on fd %d", tmpl_fd); /* Clear the active template. */ if (ct_tmpl_clear(tmpl_fd) != 0) - error("%s: Error clearing active process contract " - "template: %s", __func__, strerror(errno)); + error_f("error clearing active process contract template: %s", + strerror(errno)); close(tmpl_fd); tmpl_fd = -1; @@ -142,15 +137,15 @@ char ctl_path[256]; int r, ctl_fd = -1, stat_fd = -1; - debug2("%s: clearing template (fd %d)", __func__, tmpl_fd); + debug3_f("clearing template (fd %d)", tmpl_fd); if (tmpl_fd == -1) return; /* First clear the active template. */ if ((r = ct_tmpl_clear(tmpl_fd)) != 0) - error("%s: Error clearing active process contract " - "template: %s", __func__, strerror(errno)); + error_f("error clearing active process contract template: %s", + strerror(errno)); close(tmpl_fd); tmpl_fd = -1; @@ -166,18 +161,18 @@ /* Now lookup and abandon the contract we've created. */ ctid = get_active_process_contract_id(); - debug2("%s: abandoning contract id %ld", __func__, ctid); + debug3_f("abandoning contract id %ld", ctid); snprintf(ctl_path, sizeof(ctl_path), CTFS_ROOT "/process/%ld/ctl", ctid); if ((ctl_fd = open64(ctl_path, O_WRONLY)) < 0) { - error("%s: Error opening process contract " - "ctl file: %s", __func__, strerror(errno)); + error_f("error opening process contract ctl file: %s", + strerror(errno)); goto fail; } if (ct_ctl_abandon(ctl_fd) < 0) { - error("%s: Error abandoning process contract: %s", - __func__, strerror(errno)); + error_f("error abandoning process contract: %s", + strerror(errno)); goto fail; } close(ctl_fd); @@ -199,6 +194,8 @@ #include #include +#include "log.h" + /* * Get/set solaris default project. * If we fail, just run along gracefully. diff -ruN openssh-9.4p1/openbsd-compat/pwcache.c openssh-9.4p1+x509-14.2.1/openbsd-compat/pwcache.c --- openssh-9.4p1/openbsd-compat/pwcache.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/openbsd-compat/pwcache.c 2023-08-20 10:07:01.000000000 +0300 @@ -44,7 +44,7 @@ #define MASK (NCACHE - 1) /* bits to store with */ #ifndef HAVE_USER_FROM_UID -char * +const char * user_from_uid(uid_t uid, int nouser) { static struct ncache { @@ -79,7 +79,7 @@ #endif #ifndef HAVE_GROUP_FROM_GID -char * +const char * group_from_gid(gid_t gid, int nogroup) { static struct ncache { diff -ruN openssh-9.4p1/openbsd-compat/readpassphrase.c openssh-9.4p1+x509-14.2.1/openbsd-compat/readpassphrase.c --- openssh-9.4p1/openbsd-compat/readpassphrase.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/openbsd-compat/readpassphrase.c 2023-08-20 10:07:01.000000000 +0300 @@ -46,7 +46,7 @@ # define _POSIX_VDISABLE VDISABLE #endif -static volatile sig_atomic_t signo[_NSIG]; +static volatile sig_atomic_t signo[NSIG]; static void handler(int); @@ -67,7 +67,7 @@ } restart: - for (i = 0; i < _NSIG; i++) + for (i = 0; i < NSIG; i++) signo[i] = 0; nr = -1; save_errno = 0; @@ -91,7 +91,7 @@ * If we are using a tty but are not the foreground pgrp this will * generate SIGTTOU, so do it *before* installing the signal handlers. */ - if (input != STDIN_FILENO && tcgetattr(input, &oterm) == 0) { + if (input != STDIN_FILENO && tcgetattr(input, &oterm) != -1) { memcpy(&term, &oterm, sizeof(term)); if (!(flags & RPP_ECHO_ON)) term.c_lflag &= ~(ECHO | ECHONL); @@ -173,7 +173,7 @@ * If we were interrupted by a signal, resend it to ourselves * now that we have restored the signal handlers. */ - for (i = 0; i < _NSIG; i++) { + for (i = 0; i < NSIG; i++) { if (signo[i]) { kill(getpid(), i); switch (i) { diff -ruN openssh-9.4p1/openbsd-compat/reallocarray.c openssh-9.4p1+x509-14.2.1/openbsd-compat/reallocarray.c --- openssh-9.4p1/openbsd-compat/reallocarray.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/openbsd-compat/reallocarray.c 2023-08-20 10:07:01.000000000 +0300 @@ -23,7 +23,7 @@ #include #include #ifdef HAVE_STDINT_H -#include +# include #endif #include diff -ruN openssh-9.4p1/openbsd-compat/recallocarray.c openssh-9.4p1+x509-14.2.1/openbsd-compat/recallocarray.c --- openssh-9.4p1/openbsd-compat/recallocarray.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/openbsd-compat/recallocarray.c 2023-08-20 10:07:01.000000000 +0300 @@ -23,7 +23,7 @@ #include #include #ifdef HAVE_STDINT_H -#include +# include #endif #include #include @@ -80,8 +80,7 @@ } else memcpy(newptr, ptr, newsize); - explicit_bzero(ptr, oldsize); - free(ptr); + freezero(ptr, oldsize); return newptr; } diff -ruN openssh-9.4p1/openbsd-compat/regress/closefromtest.c openssh-9.4p1+x509-14.2.1/openbsd-compat/regress/closefromtest.c --- openssh-9.4p1/openbsd-compat/regress/closefromtest.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/openbsd-compat/regress/closefromtest.c 2023-08-20 10:07:01.000000000 +0300 @@ -26,7 +26,7 @@ #define NUM_OPENS 10 -void +static void fail(char *msg) { fprintf(stderr, "closefrom: %s\n", msg); diff -ruN openssh-9.4p1/openbsd-compat/regress/Makefile.in openssh-9.4p1+x509-14.2.1/openbsd-compat/regress/Makefile.in --- openssh-9.4p1/openbsd-compat/regress/Makefile.in 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/openbsd-compat/regress/Makefile.in 2023-08-20 10:07:01.000000000 +0300 @@ -7,11 +7,10 @@ CC=@CC@ LD=@LD@ CFLAGS=@CFLAGS@ -CPPFLAGS=-I. -I.. -I../.. -I$(srcdir) -I$(srcdir)/.. -I$(srcdir)/../.. @CPPFLAGS@ @DEFS@ +CPPFLAGS=-I../.. -I$(srcdir)/../.. @CPPFLAGS@ @DEFS@ EXEEXT=@EXEEXT@ LIBCOMPAT=../libopenbsd-compat.a -LIBSSH=../../libssh.a -LIBS=@LIBS@ @CHANNELLIBS@ +LIBS=@LIBS@ LDFLAGS=@LDFLAGS@ $(LIBCOMPAT) TESTPROGS=closefromtest$(EXEEXT) snprintftest$(EXEEXT) strduptest$(EXEEXT) \ @@ -19,8 +18,8 @@ all: t-exec ${OTHERTESTS} -.c: $(LIBCOMPAT) $(LIBSSH) - $(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) -o $@ $< $(LIBCOMPAT) $(LIBSSH) $(LIBS) +%$(EXEEXT): %.c $(LIBCOMPAT) + $(CC) -o $@ $(CFLAGS) $(CPPFLAGS) $< $(LDFLAGS) $(LIBS) t-exec: $(TESTPROGS) @echo running compat regress tests diff -ruN openssh-9.4p1/openbsd-compat/regress/opensslvertest.c openssh-9.4p1+x509-14.2.1/openbsd-compat/regress/opensslvertest.c --- openssh-9.4p1/openbsd-compat/regress/opensslvertest.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/openbsd-compat/regress/opensslvertest.c 2023-08-20 10:07:01.000000000 +0300 @@ -1,5 +1,6 @@ /* * Copyright (c) 2014 Darren Tucker + * Copyright (c) 2018-2023 Roumen Petrov * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -18,6 +19,27 @@ #include #include +#include +#include "log.h" + +/* ssh_FIPS_mode() dependency */ +void +sshlog_cryptoerr_all(const char *file, const char *func, int line, + LogLevel level +) { + UNUSED(file); UNUSED(func); UNUSED(line); + UNUSED(level); +} + +void +sshfatal(const char *file, const char *func, int line, + const char *fmt, ... +) { + UNUSED(file); UNUSED(func); UNUSED(line); + UNUSED(fmt); + _exit(255); +} + int ssh_compatible_openssl(long, long); @@ -26,6 +48,15 @@ long libver; int result; } version_tests[] = { + /* built with 0.9.8b release headers */ + { 0x0090802fL, 0x0090802fL, 1}, /* exact match */ + { 0x0090802fL, 0x0090804fL, 1}, /* newer library fix version: ok */ + { 0x0090802fL, 0x0090801fL, 1}, /* older library fix version: ok */ + { 0x0090802fL, 0x0090702fL, 0}, /* older library minor version: NO */ + { 0x0090802fL, 0x0090902fL, 0}, /* newer library minor version: NO */ + { 0x0090802fL, 0x0080802fL, 0}, /* older library major version: NO */ + { 0x0090802fL, 0x1000100fL, 0}, /* newer library major version: NO */ + /* built with 1.0.1b release headers */ { 0x1000101fL, 0x1000101fL, 1},/* exact match */ { 0x1000101fL, 0x1000102fL, 1}, /* newer library patch version: ok */ @@ -57,7 +88,7 @@ { 0x3010101fL, 0x4010101fL, 0}, /* newer library major version: NO */ }; -void +static void fail(long hver, long lver, int result) { fprintf(stderr, "opensslver: header %lx library %lx != %d \n", hver, lver, result); diff -ruN openssh-9.4p1/openbsd-compat/regress/snprintftest.c openssh-9.4p1+x509-14.2.1/openbsd-compat/regress/snprintftest.c --- openssh-9.4p1/openbsd-compat/regress/snprintftest.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/openbsd-compat/regress/snprintftest.c 2023-08-20 10:07:01.000000000 +0300 @@ -34,7 +34,8 @@ failed = 1; } -int x_snprintf(char *str, size_t count, const char *fmt, ...) +static int +x_snprintf(char *str, size_t count, const char *fmt, ...) { size_t ret; va_list ap; diff -ruN openssh-9.4p1/openbsd-compat/regress/strduptest.c openssh-9.4p1+x509-14.2.1/openbsd-compat/regress/strduptest.c --- openssh-9.4p1/openbsd-compat/regress/strduptest.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/openbsd-compat/regress/strduptest.c 2023-08-20 10:07:01.000000000 +0300 @@ -21,7 +21,7 @@ static int fail = 0; -void +static void test(const char *a) { char *b; diff -ruN openssh-9.4p1/openbsd-compat/regress/strtonumtest.c openssh-9.4p1+x509-14.2.1/openbsd-compat/regress/strtonumtest.c --- openssh-9.4p1/openbsd-compat/regress/strtonumtest.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/openbsd-compat/regress/strtonumtest.c 2023-08-20 10:07:01.000000000 +0300 @@ -1,6 +1,7 @@ /* $OpenBSD: strtonumtest.c,v 1.1 2004/08/03 20:38:36 otto Exp $ */ /* * Copyright (c) 2004 Otto Moerbeek + * Copyright (c) 2020 Roumen Petrov * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -23,23 +24,11 @@ #include #include -/* LLONG_MAX is known as LONGLONG_MAX on AIX */ -#if defined(LONGLONG_MAX) && !defined(LLONG_MAX) -# define LLONG_MAX LONGLONG_MAX -# define LLONG_MIN LONGLONG_MIN -#endif - -/* LLONG_MAX is known as LONG_LONG_MAX on HP-UX */ -#if defined(LONG_LONG_MAX) && !defined(LLONG_MAX) -# define LLONG_MAX LONG_LONG_MAX -# define LLONG_MIN LONG_LONG_MIN -#endif - long long strtonum(const char *, long long, long long, const char **); int fail; -void +static void test(const char *p, long long lb, long long ub, int ok) { long long val; @@ -57,8 +46,11 @@ } } -int main(void) +int main(int argc, char *argv[]) { + UNUSED(argc); + UNUSED(argv); + test("1", 0, 10, 1); test("0", -2, 5, 1); test("0", 2, 5, 0); diff -ruN openssh-9.4p1/openbsd-compat/rresvport.c openssh-9.4p1+x509-14.2.1/openbsd-compat/rresvport.c --- openssh-9.4p1/openbsd-compat/rresvport.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/openbsd-compat/rresvport.c 2023-08-20 10:07:01.000000000 +0300 @@ -82,12 +82,12 @@ sa->sa_family = af; s = socket(af, SOCK_STREAM, 0); - if (s < 0) + if (s == -1) return (-1); *portp = htons(*alport); if (*alport < IPPORT_RESERVED - 1) { - if (bind(s, sa, salen) >= 0) + if (bind(s, sa, salen) != -1) return (s); if (errno != EADDRINUSE) { (void)close(s); diff -ruN openssh-9.4p1/openbsd-compat/setproctitle.c openssh-9.4p1+x509-14.2.1/openbsd-compat/setproctitle.c --- openssh-9.4p1/openbsd-compat/setproctitle.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/openbsd-compat/setproctitle.c 2023-08-20 10:07:01.000000000 +0300 @@ -116,6 +116,8 @@ for (i = 0; envp[i] != NULL; i++) environ[i] = strdup(envp[i]); environ[i] = NULL; +#else + UNUSED(argc); UNUSED(argv); #endif /* SPT_REUSEARGV */ } @@ -148,7 +150,7 @@ r = vsnprintf(buf + len, sizeof(buf) - len , fmt, ap); } va_end(ap); - if (r == -1 || (size_t)r >= sizeof(buf) - len) + if (r < 0 || (size_t)r >= sizeof(buf) - len) return; strnvis(ptitle, buf, sizeof(ptitle), VIS_CSTYLE|VIS_NL|VIS_TAB|VIS_OCTAL); @@ -164,6 +166,8 @@ argv_start[len] = SPT_PADCHAR; #endif +#else + UNUSED(fmt); #endif /* SPT_NONE */ } diff -ruN openssh-9.4p1/openbsd-compat/sha2.c openssh-9.4p1+x509-14.2.1/openbsd-compat/sha2.c --- openssh-9.4p1/openbsd-compat/sha2.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/openbsd-compat/sha2.c 2023-08-20 10:07:01.000000000 +0300 @@ -38,6 +38,8 @@ #include "includes.h" +#ifndef WITH_OPENSSL + #if !defined(HAVE_SHA256UPDATE) || !defined(HAVE_SHA384UPDATE) || \ !defined(HAVE_SHA512UPDATE) @@ -1008,3 +1010,5 @@ #endif /* 0 */ #endif /* HAVE_SHA{256,384,512}UPDATE */ + +#endif /*ndef WITH_OPENSSL*/ diff -ruN openssh-9.4p1/openbsd-compat/sha2.h openssh-9.4p1+x509-14.2.1/openbsd-compat/sha2.h --- openssh-9.4p1/openbsd-compat/sha2.h 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/openbsd-compat/sha2.h 2023-08-20 10:07:00.000000000 +0300 @@ -41,6 +41,8 @@ #include "includes.h" +#ifndef WITH_OPENSSL + #if !defined(HAVE_SHA256UPDATE) || !defined(HAVE_SHA384UPDATE) || \ !defined(HAVE_SHA512UPDATE) @@ -171,4 +173,6 @@ #endif /* HAVE_SHA{256,384,512}UPDATE */ +#endif /*ndef WITH_OPENSSL*/ + #endif /* _SSHSHA2_H */ diff -ruN openssh-9.4p1/openbsd-compat/sys-queue.h openssh-9.4p1+x509-14.2.1/openbsd-compat/sys-queue.h --- openssh-9.4p1/openbsd-compat/sys-queue.h 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/openbsd-compat/sys-queue.h 2023-08-20 10:07:00.000000000 +0300 @@ -491,7 +491,7 @@ if (((elm)->field.sqx_next = XSIMPLEQ_XOR(head, \ (elm)->field.sqx_next)->field.sqx_next) \ == XSIMPLEQ_XOR(head, NULL)) \ - (head)->sqx_last = \ + (head)->sqx_last = \ XSIMPLEQ_XOR(head, &(elm)->field.sqx_next); \ } while (0) diff -ruN openssh-9.4p1/openbsd-compat/xcrypt.c openssh-9.4p1+x509-14.2.1/openbsd-compat/xcrypt.c --- openssh-9.4p1/openbsd-compat/xcrypt.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/openbsd-compat/xcrypt.c 2023-08-20 10:07:01.000000000 +0300 @@ -54,13 +54,22 @@ # include # endif +# if defined(HAVE_MD5_PASSWORDS) && !defined(HAVE_MD5_CRYPT) +# include "md5crypt.h" +# endif + # if defined(WITH_OPENSSL) && !defined(HAVE_CRYPT) && defined(HAVE_DES_CRYPT) # include # define crypt DES_crypt # endif -#define MINIMUM(a, b) (((a) < (b)) ? (a) : (b)) - +#ifndef HAVE_SETPWENT +/*FIXME: detect by configure */ +# define HAVE_SETPWENT 1 +#endif +#ifdef __ANDROID__ +# undef HAVE_SETPWENT +#endif /* * Pick an appropriate password encryption type and salt for the running * system by searching through accounts until we find one that has a valid @@ -70,14 +79,17 @@ static const char * pick_salt(void) { +#ifdef HAVE_SETPWENT struct passwd *pw; char *passwd, *p; size_t typelen; - static char salt[32]; +#endif /*def HAVE_SETPWENT*/ + static char salt[32] = {'\0'}; if (salt[0] != '\0') return salt; strlcpy(salt, "xx", sizeof(salt)); +#ifdef HAVE_SETPWENT setpwent(); while ((pw = getpwent()) != NULL) { if ((passwd = shadow_pw(pw)) == NULL) @@ -91,6 +103,7 @@ } out: endpwent(); +#endif /*def HAVE_SETPWENT*/ return salt; } @@ -106,7 +119,12 @@ if (salt == NULL) salt = pick_salt(); -#if defined(__hpux) && !defined(HAVE_SECUREWARE) +# ifdef HAVE_MD5_PASSWORDS + if (is_md5_salt(salt)) + crypted = md5_crypt(password, salt); + else + crypted = crypt(password, salt); +# elif defined(__hpux) && !defined(HAVE_SECUREWARE) if (iscomsec()) crypted = bigcrypt(password, salt); else @@ -114,8 +132,10 @@ # elif defined(HAVE_SECUREWARE) crypted = bigcrypt(password, salt); # else + /* if password is NULL (on Android ...) */ + if (password == NULL) return NULL; crypted = crypt(password, salt); -#endif +# endif return crypted; } diff -ruN openssh-9.4p1/openbsd-compat/xmd5crypt.c openssh-9.4p1+x509-14.2.1/openbsd-compat/xmd5crypt.c --- openssh-9.4p1/openbsd-compat/xmd5crypt.c 1970-01-01 02:00:00.000000000 +0200 +++ openssh-9.4p1+x509-14.2.1/openbsd-compat/xmd5crypt.c 2023-08-20 10:07:01.000000000 +0300 @@ -0,0 +1,206 @@ +/* + * ---------------------------------------------------------------------------- + * "THE BEER-WARE LICENSE" (Revision 42): + * wrote this file. As long as you retain this + * notice you can do whatever you want with this stuff. If we meet some + * day, and you think this stuff is worth it, you can buy me a beer in + * return. Poul-Henning Kamp + * ---------------------------------------------------------------------------- + * + * Copyright (c) 2020 Roumen Petrov. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "includes.h" + +#if defined(HAVE_MD5_PASSWORDS) && !defined(HAVE_MD5_CRYPT) +#include + +#include + +#include +#include "evp-compat.h" + +#include "md5crypt.h" +#include "log.h" + +/* 0 ... 63 => ascii - 64 */ +static unsigned char itoa64[] = + "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; + +static char *magic = "$1$"; + +static char * +to64(unsigned long v, int n) +{ + static char buf[5]; + char *s = buf; + + if (n > 4) + return (NULL); + + memset(buf, '\0', sizeof(buf)); + while (--n >= 0) { + *s++ = itoa64[v&0x3f]; + v >>= 6; + } + + return (buf); +} + +int +is_md5_salt(const char *salt) +{ + return (strncmp(salt, magic, strlen(magic)) == 0); +} + +char * +md5_crypt(const char *pw, const char *salt) +{ + static char passwd[120], salt_copy[9]; + static const char *sp, *ep; + unsigned char final[16]; + unsigned int final_len; + int sl, pl, i, j; + EVP_MD_CTX *ctx, *ctx1; + unsigned long l; + + /* Refine the Salt first */ + sp = salt; + + /* If it starts with the magic string, then skip that */ + if(strncmp(sp, magic, strlen(magic)) == 0) + sp += strlen(magic); + + /* It stops at the first '$', max 8 chars */ + for (ep = sp; *ep != '$'; ep++) { + if (*ep == '\0' || ep >= (sp + 8)) + break; + } + + /* get the length of the true salt */ + sl = ep - sp; + + /* Stash the salt */ + memcpy(salt_copy, sp, sl); + salt_copy[sl] = '\0'; + + ctx = EVP_MD_CTX_new(); + if (ctx == NULL) { + fatal("md5_crypt: out of memory - ctx"); + return NULL; /*unreachable code*/ + } + ctx1 = EVP_MD_CTX_new(); + if (ctx1 == NULL) { + fatal("md5_crypt: out of memory - ctx1"); + return NULL; /*unreachable code*/ + } + + EVP_DigestInit_ex(ctx, EVP_md5(), NULL); + + /* The password first, since that is what is most unknown */ + EVP_DigestUpdate(ctx, pw, strlen(pw)); + + /* Then our magic string */ + EVP_DigestUpdate(ctx, magic, strlen(magic)); + + /* Then the raw salt */ + EVP_DigestUpdate(ctx, sp, sl); + + /* Then just as many characters of the MD5(pw, salt, pw) */ + EVP_DigestInit_ex(ctx1, EVP_md5(), NULL); + EVP_DigestUpdate(ctx1, pw, strlen(pw)); + EVP_DigestUpdate(ctx1, sp, sl); + EVP_DigestUpdate(ctx1, pw, strlen(pw)); + final_len = sizeof(final); + EVP_DigestFinal(ctx1, final, &final_len); + + for(pl = strlen(pw); pl > 0; pl -= 16) + EVP_DigestUpdate(ctx, final, pl > 16 ? 16 : pl); + + /* Don't leave anything around in vm they could use. */ + memset(final, '\0', sizeof final); + + /* Then something really weird... */ + for (j = 0, i = strlen(pw); i != 0; i >>= 1) + if (i & 1) + EVP_DigestUpdate(ctx, final + j, 1); + else + EVP_DigestUpdate(ctx, pw + j, 1); + + /* Now make the output string */ + snprintf(passwd, sizeof(passwd), "%s%s$", magic, salt_copy); + + final_len = sizeof(final); + EVP_DigestFinal(ctx, final, &final_len); + + /* + * and now, just to make sure things don't run too fast + * On a 60 Mhz Pentium this takes 34 msec, so you would + * need 30 seconds to build a 1000 entry dictionary... + */ + for(i = 0; i < 1000; i++) { + EVP_DigestInit_ex(ctx1, EVP_md5(), NULL); + if (i & 1) + EVP_DigestUpdate(ctx1, pw, strlen(pw)); + else + EVP_DigestUpdate(ctx1, final, 16); + + if (i % 3) + EVP_DigestUpdate(ctx1, sp, sl); + + if (i % 7) + EVP_DigestUpdate(ctx1, pw, strlen(pw)); + + if (i & 1) + EVP_DigestUpdate(ctx1, final, 16); + else + EVP_DigestUpdate(ctx1, pw, strlen(pw)); + + final_len = sizeof(final); + EVP_DigestFinal(ctx1, final, &final_len); + } + + l = (final[ 0]<<16) | (final[ 6]<<8) | final[12]; + strlcat(passwd, to64(l, 4), sizeof(passwd)); + l = (final[ 1]<<16) | (final[ 7]<<8) | final[13]; + strlcat(passwd, to64(l, 4), sizeof(passwd)); + l = (final[ 2]<<16) | (final[ 8]<<8) | final[14]; + strlcat(passwd, to64(l, 4), sizeof(passwd)); + l = (final[ 3]<<16) | (final[ 9]<<8) | final[15]; + strlcat(passwd, to64(l, 4), sizeof(passwd)); + l = (final[ 4]<<16) | (final[10]<<8) | final[ 5]; + strlcat(passwd, to64(l, 4), sizeof(passwd)); + l = final[11] ; + strlcat(passwd, to64(l, 2), sizeof(passwd)); + + /* Don't leave anything around in vm they could use. */ + memset(final, 0, sizeof(final)); + memset(salt_copy, 0, sizeof(salt_copy)); + EVP_MD_CTX_free(ctx); + EVP_MD_CTX_free(ctx1); + (void)to64(0, 4); + + return (passwd); +} + +#endif /* defined(HAVE_MD5_PASSWORDS) && !defined(HAVE_MD5_CRYPT) */ diff -ruN openssh-9.4p1/opensshd.init.in openssh-9.4p1+x509-14.2.1/opensshd.init.in --- openssh-9.4p1/opensshd.init.in 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/opensshd.init.in 2023-08-20 10:07:00.000000000 +0300 @@ -18,6 +18,7 @@ [ X$PidFile = X ] || PIDFILE=$PidFile SSH_KEYGEN=$prefix/bin/ssh-keygen + stop_service() { if [ -r $PIDFILE -a ! -z ${PIDFILE} ]; then PID=`${CAT} ${PIDFILE}` @@ -33,8 +34,8 @@ # XXX We really should check if the service is already going, but # XXX we will opt out at this time. - Bal - # Check to see if we have keys that need to be made - ${SSH_KEYGEN} -A + # Create keys if necessary + $SSH_KEYGEN -A # Start SSHD echo "starting $SSHD... \c" ; $SSHD diff -ruN openssh-9.4p1/OVERVIEW openssh-9.4p1+x509-14.2.1/OVERVIEW --- openssh-9.4p1/OVERVIEW 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/OVERVIEW 2023-08-20 10:07:00.000000000 +0300 @@ -35,11 +35,11 @@ - Ssh contains several encryption algorithms. These are all accessed through the cipher.h interface. The interface code is in cipher.c, and the implementations are either in libc or - LibreSSL. + OpenSSL. Multiple Precision Integer Library - - Uses the LibreSSL BIGNUM sublibrary. + - Uses the OpenSSL BIGNUM sublibrary. Random Numbers diff -ruN openssh-9.4p1/packet.c openssh-9.4p1+x509-14.2.1/packet.c --- openssh-9.4p1/packet.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/packet.c 2023-08-20 10:07:01.000000000 +0300 @@ -15,6 +15,7 @@ * * SSH2 packet format added by Markus Friedl. * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. + * Copyright (c) 2018-2023 Roumen Petrov. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -59,32 +60,19 @@ #include #include #ifdef HAVE_POLL_H -#include +# include +#else +# ifdef HAVE_SYS_POLL_H +# include +# endif #endif #include #include -/* - * Explicitly include OpenSSL before zlib as some versions of OpenSSL have - * "free_func" in their headers, which zlib typedefs. - */ -#ifdef WITH_OPENSSL -# include -# include -# ifdef OPENSSL_HAS_ECC -# include -# endif -#endif - -#ifdef WITH_ZLIB -#include -#endif - #include "xmalloc.h" #include "compat.h" #include "ssh2.h" #include "cipher.h" -#include "sshkey.h" #include "kex.h" #include "digest.h" #include "mac.h" @@ -97,6 +85,14 @@ #include "ssherr.h" #include "sshbuf.h" +/* Include zlib last to avoid clash between OpenSSL function argument + * free_func and zlib typedef with same name. + * Should avoid "syntax error before 'free_func'". + */ +#ifdef WITH_ZLIB +#include +#endif + #ifdef PACKET_DEBUG #define DBG(x) x #else @@ -105,6 +101,15 @@ #define PACKET_MAX_SIZE (256 * 1024) +static inline void +ms_to_timespec(struct timespec *ts, int ms) +{ + if (ms < 0) ms = 0; + ts->tv_sec = ms / 1000; + ts->tv_nsec = (ms % 1000) * 1000000; +} + + struct packet_state { u_int32_t seqnr; u_int32_t packets; @@ -233,8 +238,8 @@ struct session_state *state = NULL; if ((ssh = calloc(1, sizeof(*ssh))) == NULL || - (state = calloc(1, sizeof(*state))) == NULL || (ssh->kex = kex_new()) == NULL || + (state = calloc(1, sizeof(*state))) == NULL || (state->input = sshbuf_new()) == NULL || (state->output = sshbuf_new()) == NULL || (state->outgoing_packet = sshbuf_new()) == NULL || @@ -257,17 +262,17 @@ ssh->state = state; return ssh; fail: - if (ssh) { - kex_free(ssh->kex); - free(ssh); - } - if (state) { + if (state != NULL) { sshbuf_free(state->input); sshbuf_free(state->output); sshbuf_free(state->incoming_packet); sshbuf_free(state->outgoing_packet); free(state); } + if (ssh != NULL) { + kex_free(ssh->kex); + free(ssh); + } return NULL; } @@ -286,6 +291,8 @@ (ssh->kex != NULL && ssh->kex->done == 0); } +/* NOTE: "none" is not allowed in FIPS mode */ +const struct sshcipher * cipher_none(void); /* * Sets the descriptors used for communication. */ @@ -293,7 +300,7 @@ ssh_packet_set_connection(struct ssh *ssh, int fd_in, int fd_out) { struct session_state *state; - const struct sshcipher *none = cipher_by_name("none"); + const struct sshcipher *none = cipher_none(); int r; if (none == NULL) { @@ -363,9 +370,8 @@ int r; free(ssh->log_preamble); - if (fmt == NULL) - ssh->log_preamble = NULL; - else { + ssh->log_preamble = NULL; + if (fmt != NULL) { va_start(args, fmt); r = vasprintf(&ssh->log_preamble, fmt, args); va_end(args); @@ -826,24 +832,33 @@ static int start_compression_out(struct ssh *ssh, int level) { + UNUSED(ssh); + UNUSED(level); return SSH_ERR_INTERNAL_ERROR; } static int start_compression_in(struct ssh *ssh) { + UNUSED(ssh); return SSH_ERR_INTERNAL_ERROR; } static int compress_buffer(struct ssh *ssh, struct sshbuf *in, struct sshbuf *out) { + UNUSED(ssh); + UNUSED(in); + UNUSED(out); return SSH_ERR_INTERNAL_ERROR; } static int uncompress_buffer(struct ssh *ssh, struct sshbuf *in, struct sshbuf *out) { + UNUSED(ssh); + UNUSED(in); + UNUSED(out); return SSH_ERR_INTERNAL_ERROR; } #endif /* WITH_ZLIB */ @@ -851,7 +866,8 @@ void ssh_clear_newkeys(struct ssh *ssh, int mode) { - if (ssh->kex && ssh->kex->newkeys[mode]) { + if (ssh->kex == NULL) return; + if (ssh->kex->newkeys[mode]) { kex_free_newkeys(ssh->kex->newkeys[mode]); ssh->kex->newkeys[mode] = NULL; } @@ -869,9 +885,9 @@ u_int64_t *max_blocks; const char *wmsg; int r, crypt_type; - const char *dir = mode == MODE_OUT ? "out" : "in"; + const char *dir = (mode == MODE_OUT) ? "out" : "in"; - debug2_f("mode %d", mode); + debug2_f("mode %d/%s", mode, dir); if (mode == MODE_OUT) { ccp = &state->send_context; @@ -970,7 +986,7 @@ return 0; /* Peer can't rekey */ - if (ssh->compat & SSH_BUG_NOREKEY) + if (ssh_compat_fellows(ssh, SSH_BUG_NOREKEY)) return 0; /* @@ -1113,7 +1129,7 @@ (r = sshbuf_putb(state->outgoing_packet, state->compression_buffer)) != 0) goto out; - DBG(debug("compression: raw %d compressed %zd", len, + DBG(debug("compression: raw %d compressed %zu", len, sshbuf_len(state->outgoing_packet))); } @@ -1208,7 +1224,7 @@ if (++state->p_send.seqnr == 0) logit("outgoing seqnr wraps around"); if (++state->p_send.packets == 0) - if (!(ssh->compat & SSH_BUG_NOREKEY)) + if (!ssh_compat_fellows(ssh, SSH_BUG_NOREKEY)) return SSH_ERR_NEED_REKEY; state->p_send.blocks += len / block_size; state->p_send.bytes += len; @@ -1324,11 +1340,10 @@ ssh_packet_read_seqnr(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p) { struct session_state *state = ssh->state; - int len, r, ms_remain = 0; - struct pollfd pfd; + int r, ms_remain; char buf[8192]; struct timeval start; - struct timespec timespec, *timespecp = NULL; + struct timespec timeout, *timeoutp; DBG(debug("packet_read()")); @@ -1339,8 +1354,19 @@ if ((r = ssh_packet_write_wait(ssh)) != 0) goto out; + if (state->packet_timeout_ms > 0) { + ms_remain = state->packet_timeout_ms; + timeoutp = &timeout; + } else { + ms_remain = 0; /* set to avoid uninitialised warning */ + timeoutp = NULL; + } + /* Stay in the loop until we have received a complete packet. */ for (;;) { + int ret; + struct pollfd pfd; + /* Try to read a packet from the buffer. */ r = ssh_packet_read_poll_seqnr(ssh, typep, seqnr_p); if (r != 0) @@ -1355,17 +1381,13 @@ pfd.fd = state->connection_in; pfd.events = POLLIN; - if (state->packet_timeout_ms > 0) { - ms_remain = state->packet_timeout_ms; - timespecp = ×pec; - } /* Wait for some data to arrive. */ for (;;) { if (state->packet_timeout_ms > 0) { - ms_to_timespec(×pec, ms_remain); + ms_to_timespec(&timeout, ms_remain); monotime_tv(&start); } - if ((r = ppoll(&pfd, 1, timespecp, NULL)) >= 0) + if ((ret = ppoll(&pfd, 1, timeoutp, NULL)) != -1) break; if (errno != EAGAIN && errno != EINTR && errno != EWOULDBLOCK) { @@ -1376,14 +1398,15 @@ continue; ms_subtract_diff(&start, &ms_remain); if (ms_remain <= 0) { - r = 0; + ret = 0; break; } } - if (r == 0) { + if (ret == 0) { r = SSH_ERR_CONN_TIMEOUT; goto out; } + { ssize_t len; /* Read data from the socket. */ len = read(state->connection_in, buf, sizeof(buf)); if (len == 0) { @@ -1399,6 +1422,7 @@ if ((r = ssh_packet_process_incoming(ssh, buf, len)) != 0) goto out; } + } out: return r; } @@ -1445,8 +1469,7 @@ size_t need; int r; - if (ssh->kex) - return SSH_ERR_INTERNAL_ERROR; + UNUSED(seqnr_p); *typep = SSH_MSG_NONE; cp = sshbuf_ptr(state->input); if (state->packlen == 0) { @@ -1632,7 +1655,7 @@ if (++state->p_read.seqnr == 0) logit("incoming seqnr wraps around"); if (++state->p_read.packets == 0) - if (!(ssh->compat & SSH_BUG_NOREKEY)) + if (!ssh_compat_fellows(ssh, SSH_BUG_NOREKEY)) return SSH_ERR_NEED_REKEY; state->p_read.blocks += (state->packlen + 4) / block_size; state->p_read.bytes += state->packlen + 4; @@ -1653,7 +1676,7 @@ ((r = sshbuf_consume_end(state->incoming_packet, padlen)) != 0)) goto out; - DBG(debug("input: len before de-compress %zd", + DBG(debug("input: len before de-compress %zu", sshbuf_len(state->incoming_packet))); if (comp && comp->enabled) { sshbuf_reset(state->compression_buffer); @@ -1664,7 +1687,7 @@ if ((r = sshbuf_putb(state->incoming_packet, state->compression_buffer)) != 0) goto out; - DBG(debug("input: len after de-compress %zd", + DBG(debug("input: len after de-compress %zu", sshbuf_len(state->incoming_packet))); } /* @@ -1697,8 +1720,8 @@ /* reset for next packet */ state->packlen = 0; - if ((r = ssh_packet_check_rekey(ssh)) != 0) - return r; + if (r == 0) + r = ssh_packet_check_rekey(ssh); out: return r; } @@ -1743,7 +1766,7 @@ reason == SSH2_DISCONNECT_BY_APPLICATION ? SYSLOG_LEVEL_INFO : SYSLOG_LEVEL_ERROR, "Received disconnect from %s port %d:" - "%u: %.400s", ssh_remote_ipaddr(ssh), + " reason %u - %.400s", ssh_remote_ipaddr(ssh), ssh_remote_port(ssh), reason, msg); free(msg); return SSH_ERR_DISCONNECTED; @@ -1786,25 +1809,26 @@ /* Reads and buffers data from the specified fd */ int -ssh_packet_process_read(struct ssh *ssh, int fd) +ssh_packet_process_read(struct ssh *ssh, int fd, size_t maxlen) { struct session_state *state = ssh->state; int r; size_t rlen; - if ((r = sshbuf_read(fd, state->input, PACKET_MAX_SIZE, &rlen)) != 0) - return r; + r = sshbuf_read(fd, state->input, maxlen, &rlen); + if (r != 0) return r; if (state->packet_discard) { - if ((r = sshbuf_consume_end(state->input, rlen)) != 0) - return r; + r = sshbuf_consume_end(state->input, rlen); + if (r != 0) return r; + state->keep_alive_timeouts = 0; /* ?? */ + if (rlen >= state->packet_discard) { - if ((r = ssh_packet_stop_discard(ssh)) != 0) - return r; + r = ssh_packet_stop_discard(ssh); + if (r != 0) return r; } state->packet_discard -= rlen; - return 0; } return 0; } @@ -1830,7 +1854,7 @@ va_list args; int r; - if ((ssh->compat & SSH_BUG_DEBUG)) + if (ssh_compat_fellows(ssh, SSH_BUG_DEBUG)) return; va_start(args, fmt); @@ -1868,22 +1892,19 @@ sshpkt_fmt_connection_id(ssh, remote_id, sizeof(remote_id)); + ssh_packet_clear_keys(ssh); + switch (r) { case SSH_ERR_CONN_CLOSED: - ssh_packet_clear_keys(ssh); logdie("Connection closed by %s", remote_id); case SSH_ERR_CONN_TIMEOUT: - ssh_packet_clear_keys(ssh); logdie("Connection %s %s timed out", ssh->state->server_side ? "from" : "to", remote_id); case SSH_ERR_DISCONNECTED: - ssh_packet_clear_keys(ssh); logdie("Disconnected from %s", remote_id); case SSH_ERR_SYSTEM_ERROR: - if (errno == ECONNRESET) { - ssh_packet_clear_keys(ssh); + if (errno == ECONNRESET) logdie("Connection reset by %s", remote_id); - } /* FALLTHROUGH */ case SSH_ERR_NO_CIPHER_ALG_MATCH: case SSH_ERR_NO_MAC_ALG_MATCH: @@ -1891,7 +1912,6 @@ case SSH_ERR_NO_KEX_ALG_MATCH: case SSH_ERR_NO_HOSTKEY_ALG_MATCH: if (ssh->kex && ssh->kex->failed_choice) { - ssh_packet_clear_keys(ssh); errno = oerrno; logdie("Unable to negotiate with %s: %s. " "Their offer: %s", remote_id, ssh_err(r), @@ -1899,15 +1919,13 @@ } /* FALLTHROUGH */ default: - if (vasprintf(&tag, fmt, ap) == -1) { - ssh_packet_clear_keys(ssh); - logdie_f("could not allocate failure message"); - } - ssh_packet_clear_keys(ssh); + if (vasprintf(&tag, fmt, ap) < 0) + logdie("Could not allocate packet failure message"); errno = oerrno; - logdie_r(r, "%s%sConnection %s %s", + logdie("%s%sConnection %s %s: %s", tag != NULL ? tag : "", tag != NULL ? ": " : "", - ssh->state->server_side ? "from" : "to", remote_id); + ssh->state->server_side ? "from" : "to", + remote_id, ssh_err(r)); } } @@ -1920,7 +1938,7 @@ sshpkt_vfatal(ssh, r, fmt, ap); /* NOTREACHED */ va_end(ap); - logdie_f("should have exited"); + logdie("Packet should have exited"); } /* @@ -2003,28 +2021,35 @@ int ssh_packet_write_wait(struct ssh *ssh) { - int ret, r, ms_remain = 0; + int r, ms_remain; struct timeval start; - struct timespec timespec, *timespecp = NULL; + struct timespec timeout, *timeoutp; struct session_state *state = ssh->state; - struct pollfd pfd; if ((r = ssh_packet_write_poll(ssh)) != 0) return r; + + if (state->packet_timeout_ms > 0) { + ms_remain = state->packet_timeout_ms; + timeoutp = &timeout; + } else { + ms_remain = 0; /* set to avoid uninitialised warning */ + timeoutp = NULL; + } + while (ssh_packet_have_data_to_write(ssh)) { + int ret; + struct pollfd pfd; + pfd.fd = state->connection_out; pfd.events = POLLOUT; - if (state->packet_timeout_ms > 0) { - ms_remain = state->packet_timeout_ms; - timespecp = ×pec; - } for (;;) { if (state->packet_timeout_ms > 0) { - ms_to_timespec(×pec, ms_remain); + ms_to_timespec(&timeout, ms_remain); monotime_tv(&start); } - if ((ret = ppoll(&pfd, 1, timespecp, NULL)) >= 0) + if ((ret = ppoll(&pfd, 1, timeoutp, NULL)) != -1) break; if (errno != EAGAIN && errno != EINTR && errno != EWOULDBLOCK) @@ -2107,12 +2132,12 @@ struct session_state *state = ssh->state; if (state->set_maxsize_called) { - logit_f("called twice: old %d new %d", + debug_f("called twice: old %d new %d", state->max_packet_size, s); return -1; } if (s < 4 * 1024 || s > 1024 * 1024) { - logit_f("bad size %d", s); + debug_f("bad size %d", s); return -1; } state->set_maxsize_called = 1; @@ -2207,9 +2232,8 @@ int r; if ((r = sshbuf_put_u32(m, kex->we_need)) != 0 || + /* TODO why to send hostkey_foo as is not set? */ (r = sshbuf_put_cstring(m, kex->hostkey_alg)) != 0 || - (r = sshbuf_put_u32(m, kex->hostkey_type)) != 0 || - (r = sshbuf_put_u32(m, kex->hostkey_nid)) != 0 || (r = sshbuf_put_u32(m, kex->kex_type)) != 0 || (r = sshbuf_put_stringb(m, kex->my)) != 0 || (r = sshbuf_put_stringb(m, kex->peer)) != 0 || @@ -2366,12 +2390,12 @@ struct kex *kex; int r; - if ((kex = kex_new()) == NULL) - return SSH_ERR_ALLOC_FAIL; + if ((kex = kex_new()) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } if ((r = sshbuf_get_u32(m, &kex->we_need)) != 0 || (r = sshbuf_get_cstring(m, &kex->hostkey_alg, NULL)) != 0 || - (r = sshbuf_get_u32(m, (u_int *)&kex->hostkey_type)) != 0 || - (r = sshbuf_get_u32(m, (u_int *)&kex->hostkey_nid)) != 0 || (r = sshbuf_get_u32(m, &kex->kex_type)) != 0 || (r = sshbuf_get_stringb(m, kex->my)) != 0 || (r = sshbuf_get_stringb(m, kex->peer)) != 0 || @@ -2380,6 +2404,11 @@ (r = sshbuf_get_stringb(m, kex->session_id)) != 0 || (r = sshbuf_get_u32(m, &kex->flags)) != 0) goto out; + /* as hostkey_alg is not set we receive empty string - so free it */ + if (kex->hostkey_alg[0] == '\0') { + free(kex->hostkey_alg); + kex->hostkey_alg = NULL; + } kex->server = 1; kex->done = 1; r = 0; @@ -2389,7 +2418,6 @@ if (kexp != NULL) *kexp = NULL; } else { - kex_free(*kexp); *kexp = kex; } return r; @@ -2407,6 +2435,8 @@ size_t ilen, olen; int r; + kex_free(ssh->kex); + ssh->kex = NULL; if ((r = kex_from_blob(m, &ssh->kex)) != 0 || (r = newkeys_from_blob(m, ssh, MODE_OUT)) != 0 || (r = newkeys_from_blob(m, ssh, MODE_IN)) != 0 || @@ -2521,6 +2551,16 @@ { return sshbuf_put_bignum2(ssh->state->outgoing_packet, v); } + +int +sshpkt_write_dh_group(struct ssh *ssh, EVP_PKEY *pk) { + return sshbuf_kex_write_dh_group(ssh->state->outgoing_packet, pk); +} + +int +sshpkt_write_dh_pub(struct ssh *ssh, EVP_PKEY *pk) { + return sshbuf_kex_write_dh_pub(ssh->state->outgoing_packet, pk); +} #endif /* WITH_OPENSSL */ /* fetch data from the incoming packet */ @@ -2627,8 +2667,6 @@ size_t len; int r; - if (ssh->kex) - return SSH_ERR_INTERNAL_ERROR; len = sshbuf_len(state->outgoing_packet); if (len < 6) return SSH_ERR_INTERNAL_ERROR; diff -ruN openssh-9.4p1/packet.h openssh-9.4p1+x509-14.2.1/packet.h --- openssh-9.4p1/packet.h 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/packet.h 2023-08-20 10:07:00.000000000 +0300 @@ -1,9 +1,9 @@ /* $OpenBSD: packet.h,v 1.94 2022/01/22 00:49:34 djm Exp $ */ - /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland * All rights reserved + * Copyright (c) 2019-2023 Roumen Petrov. All rights reserved. * Interface for the packet protocol functions. * * As far as I am concerned, the code I have written for this software @@ -17,24 +17,9 @@ #define PACKET_H #include - -#ifdef WITH_OPENSSL -# include -# ifdef OPENSSL_HAS_ECC -# include -# else /* OPENSSL_HAS_ECC */ -# define EC_KEY void -# define EC_GROUP void -# define EC_POINT void -# endif /* OPENSSL_HAS_ECC */ -#else /* WITH_OPENSSL */ -# define BIGNUM void -# define EC_KEY void -# define EC_GROUP void -# define EC_POINT void -#endif /* WITH_OPENSSL */ - #include + +#include "evp-compat.h" #include "openbsd-compat/sys-queue.h" struct kex; @@ -43,6 +28,7 @@ struct session_state; /* private session data */ #include "dispatch.h" /* typedef, DISPATCH_MAX */ +#include "compat.h" struct key_entry { TAILQ_ENTRY(key_entry) next; @@ -71,8 +57,8 @@ /* number of packets to ignore in the dispatcher */ int dispatch_skip_packets; - /* datafellows */ - int compat; + /* secure shell compatibility flags */ + ssh_compat compat; /* Lists for private and public keys */ TAILQ_HEAD(, key_entry) private_keys; @@ -88,6 +74,20 @@ void *app_data; }; + +void ssh_set_compatibility(struct ssh *ssh, const char *remote_version); + +static inline int/*bool*/ +ssh_compat_fellows(struct ssh *ssh, u_int flag) { + return check_compat_fellows(&ssh->compat, flag); +} + +static inline int/*bool*/ +ssh_compat_extra(struct ssh *ssh, u_int flag) { + return check_compat_extra(&ssh->compat, flag); +} + + typedef int (ssh_packet_hook_fn)(struct ssh *, struct sshbuf *, u_char *, void *); @@ -128,7 +128,7 @@ int ssh_packet_read_poll(struct ssh *); int ssh_packet_read_poll2(struct ssh *, u_char *, u_int32_t *seqnr_p); int ssh_packet_process_incoming(struct ssh *, const char *buf, u_int len); -int ssh_packet_process_read(struct ssh *, int); +int ssh_packet_process_read(struct ssh *, int, size_t); int ssh_packet_read_seqnr(struct ssh *, u_char *, u_int32_t *seqnr_p); int ssh_packet_read_poll_seqnr(struct ssh *, u_char *, u_int32_t *seqnr_p); @@ -193,6 +193,8 @@ int sshpkt_put_stringb(struct ssh *ssh, const struct sshbuf *v); int sshpkt_put_ec(struct ssh *ssh, const EC_POINT *v, const EC_GROUP *g); int sshpkt_put_bignum2(struct ssh *ssh, const BIGNUM *v); +int sshpkt_write_dh_group(struct ssh *ssh, EVP_PKEY *pk); +int sshpkt_write_dh_pub(struct ssh *ssh, EVP_PKEY *pk); int sshpkt_get(struct ssh *ssh, void *valp, size_t len); int sshpkt_get_u8(struct ssh *ssh, u_char *valp); @@ -209,15 +211,4 @@ void sshpkt_fmt_connection_id(struct ssh *ssh, char *s, size_t l); const u_char *sshpkt_ptr(struct ssh *, size_t *lenp); -#if !defined(WITH_OPENSSL) -# undef BIGNUM -# undef EC_KEY -# undef EC_GROUP -# undef EC_POINT -#elif !defined(OPENSSL_HAS_ECC) -# undef EC_KEY -# undef EC_GROUP -# undef EC_POINT -#endif - #endif /* PACKET_H */ diff -ruN openssh-9.4p1/pathnames.h openssh-9.4p1+x509-14.2.1/pathnames.h --- openssh-9.4p1/pathnames.h 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/pathnames.h 2023-08-20 10:07:00.000000000 +0300 @@ -10,6 +10,28 @@ * software must be clearly marked as such, and if the derived work is * incompatible with the protocol description in the RFC file, it must be * called by a name other than "ssh" or "Secure Shell". + * + * Copyright (c) 2002-2020 Roumen Petrov. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #define ETCDIR "/etc" @@ -18,6 +40,14 @@ #define SSHDIR ETCDIR "/ssh" #endif +#ifndef SSHBINDIR +#define SSHBINDIR "/usr/bin" +#endif + +#ifndef SSHLIBEXECDIR +#define SSHLIBEXECDIR "/usr/libexec" +#endif + #ifndef _PATH_SSH_PIDDIR #define _PATH_SSH_PIDDIR "/var/run" #endif @@ -43,9 +73,7 @@ #define _PATH_HOST_RSA_KEY_FILE SSHDIR "/ssh_host_rsa_key" #define _PATH_DH_MODULI SSHDIR "/moduli" -#ifndef _PATH_SSH_PROGRAM -#define _PATH_SSH_PROGRAM "/usr/bin/ssh" -#endif +#define _PATH_SSH_PROGRAM SSHBINDIR "/ssh" /* * The process id of the daemon listening for connections is saved here to @@ -77,8 +105,6 @@ #define _PATH_SSH_CLIENT_ID_RSA _PATH_SSH_USER_DIR "/id_rsa" #define _PATH_SSH_CLIENT_ID_ED25519 _PATH_SSH_USER_DIR "/id_ed25519" #define _PATH_SSH_CLIENT_ID_XMSS _PATH_SSH_USER_DIR "/id_xmss" -#define _PATH_SSH_CLIENT_ID_ECDSA_SK _PATH_SSH_USER_DIR "/id_ecdsa_sk" -#define _PATH_SSH_CLIENT_ID_ED25519_SK _PATH_SSH_USER_DIR "/id_ed25519_sk" /* * Configuration file in user's home directory. This file need not be @@ -88,6 +114,14 @@ */ #define _PATH_SSH_USER_CONFFILE _PATH_SSH_USER_DIR "/config" +#ifdef USE_OPENSSL_ENGINE +/* + * Engine configuration file in user's home directory. Same rules as + * for user config file. + */ +#define _PATH_SSH_ENGINE_CONFFILE _PATH_SSH_USER_DIR "/engine" +#endif + /* * File containing a list of those rsa keys that permit logging in as this * user. This file need not be readable by anyone but the user him/herself, @@ -117,27 +151,14 @@ #define _PATH_SSH_HOSTS_EQUIV SSHDIR "/shosts.equiv" #define _PATH_RHOSTS_EQUIV "/etc/hosts.equiv" -/* - * Default location of askpass - */ -#ifndef _PATH_SSH_ASKPASS_DEFAULT -#define _PATH_SSH_ASKPASS_DEFAULT "/usr/X11R6/bin/ssh-askpass" -#endif +/* Location of askpass */ +#define _PATH_SSH_ASKPASS SSHLIBEXECDIR "/ssh-askpass" /* Location of ssh-keysign for hostbased authentication */ -#ifndef _PATH_SSH_KEY_SIGN -#define _PATH_SSH_KEY_SIGN "/usr/libexec/ssh-keysign" -#endif +#define _PATH_SSH_KEY_SIGN SSHLIBEXECDIR "/ssh-keysign" /* Location of ssh-pkcs11-helper to support keys in tokens */ -#ifndef _PATH_SSH_PKCS11_HELPER -#define _PATH_SSH_PKCS11_HELPER "/usr/libexec/ssh-pkcs11-helper" -#endif - -/* Location of ssh-sk-helper to support keys in security keys */ -#ifndef _PATH_SSH_SK_HELPER -#define _PATH_SSH_SK_HELPER "/usr/libexec/ssh-sk-helper" -#endif +#define _PATH_SSH_PKCS11_HELPER SSHLIBEXECDIR "/ssh-pkcs11-helper" /* xauth for X11 forwarding */ #ifndef _PATH_XAUTH @@ -154,10 +175,8 @@ #define _PATH_CP "cp" #endif -/* for sftp */ -#ifndef _PATH_SFTP_SERVER -#define _PATH_SFTP_SERVER "/usr/libexec/sftp-server" -#endif +/* for external sftp sever */ +#define _PATH_SFTP_SERVER SSHLIBEXECDIR "/sftp-server" /* chroot directory for unprivileged user when UsePrivilegeSeparation=yes */ #ifndef _PATH_PRIVSEP_CHROOT_DIR @@ -173,7 +192,19 @@ #define _PATH_LS "ls" #endif -/* Askpass program define */ -#ifndef ASKPASS_PROGRAM -#define ASKPASS_PROGRAM "/usr/lib/ssh/ssh-askpass" -#endif /* ASKPASS_PROGRAM */ + +#ifndef SSHCADIR +#define SSHCADIR SSHDIR "/ca" +#endif + +/* x509 user store */ +#define _PATH_USERCA_CERTIFICATE_FILE "~/" _PATH_SSH_USER_DIR "/ca-bundle.crt" +#define _PATH_USERCA_CERTIFICATE_PATH "~/" _PATH_SSH_USER_DIR "/crt" +#define _PATH_USERCA_REVOCATION_FILE "~/" _PATH_SSH_USER_DIR "/ca-bundle.crl" +#define _PATH_USERCA_REVOCATION_PATH "~/" _PATH_SSH_USER_DIR "/crl" + +/* x509 system store */ +#define _PATH_CA_CERTIFICATE_FILE SSHCADIR "/ca-bundle.crt" +#define _PATH_CA_CERTIFICATE_PATH SSHCADIR "/crt" +#define _PATH_CA_REVOCATION_FILE SSHCADIR "/ca-bundle.crl" +#define _PATH_CA_REVOCATION_PATH SSHCADIR "/crl" diff -ruN openssh-9.4p1/platform.c openssh-9.4p1+x509-14.2.1/platform.c --- openssh-9.4p1/platform.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/platform.c 2023-08-20 10:07:01.000000000 +0300 @@ -24,7 +24,6 @@ #include "log.h" #include "misc.h" #include "servconf.h" -#include "sshkey.h" #include "hostfile.h" #include "auth.h" #include "auth-pam.h" @@ -65,6 +64,8 @@ { #ifdef USE_SOLARIS_PROCESS_CONTRACTS solaris_contract_post_fork_parent(child_pid); +#else + UNUSED(child_pid); #endif } @@ -103,6 +104,7 @@ (void)ssh_selinux_enabled(); #endif + UNUSED(pw); #ifdef USE_SOLARIS_PROJECTS /* * If solaris projects were detected, set the default now, unless @@ -146,6 +148,7 @@ void platform_setusercontext_post_groups(struct passwd *pw) { + UNUSED(pw); #if !defined(HAVE_LOGIN_CAP) && defined(USE_PAM) /* * PAM credentials may take the form of supplementary groups. @@ -195,6 +198,7 @@ #ifdef USE_AIX_KRB_NAME return aix_krb5_get_principal_name(pw_name); #else + UNUSED(pw_name); return NULL; #endif } @@ -204,12 +208,13 @@ platform_locked_account(struct passwd *pw) { int locked = 0; - char *passwd = pw->pw_passwd; -#ifdef USE_SHADOW - struct spwd *spw = NULL; + const char *passwd = pw->pw_passwd; #ifdef USE_LIBIAF char *iaf_passwd = NULL; #endif +#ifdef USE_SHADOW +{ + struct spwd *spw = NULL; spw = getspnam(pw->pw_name); #ifdef HAS_SHADOW_EXPIRE @@ -219,14 +224,15 @@ if (spw != NULL) #ifdef USE_LIBIAF - iaf_passwd = passwd = get_iaf_password(pw); + passwd = iaf_passwd = get_iaf_password(pw); #else passwd = spw->sp_pwdp; -#endif /* USE_LIBIAF */ +#endif +} #endif /* check for locked account */ - if (passwd && *passwd) { + if (passwd != NULL && *passwd != '\0') { #ifdef LOCKED_PASSWD_STRING if (strcmp(passwd, LOCKED_PASSWD_STRING) == 0) locked = 1; @@ -241,6 +247,7 @@ locked = 1; #endif } + #ifdef USE_LIBIAF if (iaf_passwd != NULL) freezero(iaf_passwd, strlen(iaf_passwd)); diff -ruN openssh-9.4p1/platform-tracing.c openssh-9.4p1+x509-14.2.1/platform-tracing.c --- openssh-9.4p1/platform-tracing.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/platform-tracing.c 2023-08-20 10:07:01.000000000 +0300 @@ -32,7 +32,7 @@ #include #include #include -#include +#include /* for getpid */ #include "log.h" @@ -40,11 +40,11 @@ platform_disable_tracing(int strict) { #if defined(HAVE_PROCCTL) && defined(PROC_TRACE_CTL) - /* On FreeBSD, we should make this process untraceable */ +{ /* On FreeBSD, we should make this process untraceable */ int disable_trace = PROC_TRACE_CTL_DISABLE; /* - * On FreeBSD, we should make this process untraceable. + * FreeBSD reference #259174 . * pid=0 means "this process" but some older kernels do not * understand that so retry with our own pid before failing. */ @@ -55,6 +55,7 @@ if (strict) fatal("unable to make the process untraceable: %s", strerror(errno)); +} #endif #if defined(HAVE_PRCTL) && defined(PR_SET_DUMPABLE) /* Disable ptrace on Linux without sgid bit */ diff -ruN openssh-9.4p1/poly1305.c openssh-9.4p1+x509-14.2.1/poly1305.c --- openssh-9.4p1/poly1305.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/poly1305.c 2023-08-20 10:07:01.000000000 +0300 @@ -1,9 +1,10 @@ -/* $OpenBSD: poly1305.c,v 1.4 2023/07/17 05:26:38 djm Exp $ */ /* * Public Domain poly1305 from Andrew Moon * poly1305-donna-unrolled.c from https://github.com/floodyberry/poly1305-donna */ +/* $OpenBSD: poly1305.c,v 1.3 2013/12/19 22:57:13 djm Exp $ */ + #include "includes.h" #include diff -ruN openssh-9.4p1/progressmeter.c openssh-9.4p1+x509-14.2.1/progressmeter.c --- openssh-9.4p1/progressmeter.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/progressmeter.c 2023-08-20 10:07:01.000000000 +0300 @@ -1,6 +1,7 @@ -/* $OpenBSD: progressmeter.c,v 1.53 2023/04/12 14:22:04 jsg Exp $ */ +/* $OpenBSD: progressmeter.c,v 1.51 2023/02/22 03:56:43 djm Exp $ */ /* * Copyright (c) 2003 Nils Nordman. All rights reserved. + * Copyright (c) 2019-2023 Roumen Petrov. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -30,10 +31,8 @@ #include #include -#include #include #include -#include #include #include #include @@ -46,10 +45,23 @@ #define DEFAULT_WINSIZE 80 #define MAX_WINSIZE 512 -#define PADDING 1 /* padding between the progress indicators */ #define UPDATE_INTERVAL 1 /* update the progress meter every second */ #define STALL_TIME 5 /* we're stalled after this many seconds */ +/* Progress format: {name+space(1)}[info(34)]. + * Do not write to last column! + * + * Progress information part, items separated by space: + * percent : format "nnn% ", i.e. 4+1 characters + * amount : format "nnnnuu ", i.e. 6+1 characters + * bandwidth: format "nnn.nuu/s ", i.e. 9+1 characters + * ETA : various formats, 12 characters + * , i.e. 34 ascii characters. + * + * NOTE: length counts trailing '\0'. + */ +#define PROGRESS_INFO_LEN (34+1) + /* determines whether we can output to the terminal */ static int can_output(void); @@ -82,14 +94,10 @@ return (getpgrp() == tcgetpgrp(STDOUT_FILENO)); } -/* size needed to format integer type v, using (nbits(v) * log2(10) / 10) */ -#define STRING_SIZE(v) (((sizeof(v) * 8 * 4) / 10) + 1) - -static const char * -format_rate(off_t bytes) +static int +format_rate(char *buf, int size, off_t bytes) { int i; - static char buf[STRING_SIZE(bytes) * 2 + 16]; bytes *= 100; for (i = 0; bytes >= 100*1000 && unit[i] != 'T'; i++) @@ -98,40 +106,33 @@ i++; bytes = (bytes + 512) / 1024; } - snprintf(buf, sizeof(buf), "%3lld.%1lld%c%s", + return snprintf(buf, size, "%3lld.%1lld%c%c/s ", (long long) (bytes + 5) / 100, (long long) (bytes + 5) / 10 % 10, - unit[i], - i ? "B" : " "); - return buf; + unit[i], i > 0 ? 'B' : ' '); } -static const char * -format_size(off_t bytes) +static int +format_size(char *buf, int size, off_t bytes) { int i; - static char buf[STRING_SIZE(bytes) + 16]; for (i = 0; bytes >= 10000 && unit[i] != 'T'; i++) bytes = (bytes + 512) / 1024; - snprintf(buf, sizeof(buf), "%4lld%c%s", + return snprintf(buf, size, "%4lld%c%c ", (long long) bytes, - unit[i], - i ? "B" : " "); - return buf; + unit[i], i > 0 ? 'B' : ' '); } void refresh_progress_meter(int force_update) { - char *buf = NULL, *obuf = NULL; + char buf[4 * MAX_WINSIZE + 1]; off_t transferred; double elapsed, now; - int percent; off_t bytes_left; int cur_speed; - int hours, minutes, seconds; - int file_len, cols; + int len; if ((!force_update && !alarm_fired && !win_resized) || !can_output()) return; @@ -171,27 +172,59 @@ last_update = now; - /* Don't bother if we can't even display the completion percentage */ - if (win_size < 4) - return; + /* Skip output if cannot display the completion percentage at least. + * NOTE: win_size counts trailing '\0'! + */ + if (win_size < 6) return; + + buf[0] = '\r'; + buf[1] = '\0'; /* filename */ - file_len = cols = win_size - 36; - if (file_len > 0) { - asmprintf(&buf, INT_MAX, &cols, "%-*s", file_len, file); - /* If we used fewer columns than expected then pad */ - if (cols < file_len) - xextendf(&buf, NULL, "%*s", file_len - cols, ""); + if (win_size > (PROGRESS_INFO_LEN + 2)) { + int file_len = win_size - (PROGRESS_INFO_LEN + 2); + #if 0 + /* TODO: lost space character from format! */ + snmprintf(buf+1, sizeof(buf)-1, &file_len, "%-*s ", + file_len, file); + #else + snmprintf(buf+1, sizeof(buf)-1, &file_len, "%-*s", + file_len, file); + /* work-around */ + strlcat(buf+1, " ", sizeof(buf)-1); + #endif } + +{ int ilen; + char *ibuf; + + len = strlen(buf); + ilen = len > 1 ? PROGRESS_INFO_LEN : (win_size - 1); + ibuf = buf + len; + /* percent of transfer done */ +{ int percent; if (end_pos == 0 || cur_pos == end_pos) percent = 100; else percent = ((float)cur_pos / end_pos) * 100; + len = snprintf(ibuf, ilen, "%3d%% ", percent); + ilen -= len; + if (ilen < 1) goto done; + ibuf += len; +} - /* percent / amount transferred / bandwidth usage */ - xextendf(&buf, NULL, " %3d%% %s %s/s ", percent, format_size(cur_pos), - format_rate((off_t)bytes_per_second)); + /* amount transferred */ + len = format_size(ibuf, ilen, cur_pos); + ilen -= len; + if (ilen < 1) goto done; + ibuf += len; + + /* bandwidth usage */ + len = format_rate(ibuf, ilen, (off_t)bytes_per_second); + ilen -= len; + if (ilen < 1) goto done; + ibuf += len; /* ETA */ if (!transferred) @@ -200,10 +233,12 @@ stalled = 0; if (stalled >= STALL_TIME) - xextendf(&buf, NULL, "- stalled -"); + strlcat(ibuf, "- stalled - ", ilen); else if (bytes_per_second == 0 && bytes_left) - xextendf(&buf, NULL, " --:-- ETA"); + strlcat(ibuf, " --:-- ETA ", ilen); else { + int hours, minutes, seconds; + if (bytes_left > 0) seconds = bytes_left / bytes_per_second; else @@ -214,32 +249,39 @@ minutes = seconds / 60; seconds -= minutes * 60; - if (hours != 0) { - xextendf(&buf, NULL, "%d:%02d:%02d", - hours, minutes, seconds); - } else - xextendf(&buf, NULL, " %02d:%02d", minutes, seconds); + /* formats: + * "nn:nn:nn", i.e. 8 charactes + * "n:nn:nn", i.e. 7 charactes + * " nn:nn", i.e. 7 charactes + */ + if (hours != 0) + len = snprintf(ibuf, ilen, + "%d:%02d:%02d", hours, minutes, seconds); + else + len = snprintf(ibuf, ilen, + " %02d:%02d", minutes, seconds); + if (len >= ilen) goto done; + /* format 4 charactes */ if (bytes_left > 0) - xextendf(&buf, NULL, " ETA"); + strlcat(ibuf, " ETA", ilen); else - xextendf(&buf, NULL, " "); - } + strlcat(ibuf, " ", ilen); - /* Finally, truncate string at window width */ - cols = win_size - 1; - asmprintf(&obuf, INT_MAX, &cols, " %s", buf); - if (obuf != NULL) { - *obuf = '\r'; /* must insert as asmprintf() would escape it */ - atomicio(vwrite, STDOUT_FILENO, obuf, strlen(obuf)); + /* cleanup last column */ + if (len < 8) + strlcat(ibuf, " ", ilen); } - free(buf); - free(obuf); +} +done: + len = strlen(buf); + atomicio(vwrite, STDOUT_FILENO, buf, len); } static void sig_alarm(int ignore) { + UNUSED(ignore); alarm_fired = 1; alarm(UPDATE_INTERVAL); } @@ -267,6 +309,8 @@ void stop_progress_meter(void) { + /* stop watching for window change */ + ssh_signal(SIGWINCH, SIG_DFL); alarm(0); if (!can_output()) @@ -282,6 +326,7 @@ static void sig_winch(int sig) { + UNUSED(sig); win_resized = 1; } diff -ruN openssh-9.4p1/PROTOCOL openssh-9.4p1+x509-14.2.1/PROTOCOL --- openssh-9.4p1/PROTOCOL 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/PROTOCOL 2023-08-20 10:07:00.000000000 +0300 @@ -344,41 +344,9 @@ extension signal "INFO@openssh.com" that allows sending SIGINFO on BSD-derived systems. -3. Authentication protocol changes +3. SFTP protocol changes -3.1. Host-bound public key authentication - -This is trivial change to the traditional "publickey" authentication -method. The authentication request is identical to the original method -but for the name and one additional field: - - byte SSH2_MSG_USERAUTH_REQUEST - string username - string "ssh-connection" - string "publickey-hostbound-v00@openssh.com" - bool has_signature - string pkalg - string public key - string server host key - -Because the entire SSH2_MSG_USERAUTH_REQUEST message is included in -the signed data, this ensures that a binding between the destination -user, the server identity and the session identifier is visible to the -signer. OpenSSH uses this binding via signed data to implement per-key -restrictions in ssh-agent. - -A server may advertise this method using the SSH2_MSG_EXT_INFO -mechanism (RFC8308), with the following message: - - string "publickey-hostbound@openssh.com" - string "0" (version) - -Clients should prefer host-bound authentication when advertised by -server. - -4. SFTP protocol changes - -4.1. sftp: Reversal of arguments to SSH_FXP_SYMLINK +3.1. sftp: Reversal of arguments to SSH_FXP_SYMLINK When OpenSSH's sftp-server was implemented, the order of the arguments to the SSH_FXP_SYMLINK method was inadvertently reversed. Unfortunately, @@ -391,7 +359,7 @@ string targetpath string linkpath -4.2. sftp: Server extension announcement in SSH_FXP_VERSION +3.2. sftp: Server extension announcement in SSH_FXP_VERSION OpenSSH's sftp-server lists the extensions it supports using the standard extension announcement mechanism in the SSH_FXP_VERSION server @@ -412,7 +380,7 @@ extension with multiple versions (though this is unlikely). Clients MUST check the version number before attempting to use the extension. -4.3. sftp: Extension request "posix-rename@openssh.com" +3.3. sftp: Extension request "posix-rename@openssh.com" This operation provides a rename operation with POSIX semantics, which are different to those provided by the standard SSH_FXP_RENAME in @@ -429,7 +397,7 @@ This extension is advertised in the SSH_FXP_VERSION hello with version "1". -4.4. sftp: Extension requests "statvfs@openssh.com" and +3.4. sftp: Extension requests "statvfs@openssh.com" and "fstatvfs@openssh.com" These requests correspond to the statvfs and fstatvfs POSIX system @@ -470,7 +438,7 @@ Both the "statvfs@openssh.com" and "fstatvfs@openssh.com" extensions are advertised in the SSH_FXP_VERSION hello with version "2". -4.5. sftp: Extension request "hardlink@openssh.com" +3.5. sftp: Extension request "hardlink@openssh.com" This request is for creating a hard link to a regular file. This request is implemented as a SSH_FXP_EXTENDED request with the @@ -486,7 +454,7 @@ This extension is advertised in the SSH_FXP_VERSION hello with version "1". -4.6. sftp: Extension request "fsync@openssh.com" +3.6. sftp: Extension request "fsync@openssh.com" This request asks the server to call fsync(2) on an open file handle. @@ -500,7 +468,7 @@ This extension is advertised in the SSH_FXP_VERSION hello with version "1". -4.7. sftp: Extension request "lsetstat@openssh.com" +3.7. sftp: Extension request "lsetstat@openssh.com" This request is like the "setstat" command, but sets file attributes on symlinks. It is implemented as a SSH_FXP_EXTENDED request with the @@ -516,7 +484,7 @@ This extension is advertised in the SSH_FXP_VERSION hello with version "1". -4.8. sftp: Extension request "limits@openssh.com" +3.8. sftp: Extension request "limits@openssh.com" This request is used to determine various limits the server might impose. Clients should not attempt to exceed these limits as the server might sever @@ -559,7 +527,7 @@ This extension is advertised in the SSH_FXP_VERSION hello with version "1". -4.9. sftp: Extension request "expand-path@openssh.com" +3.9. sftp: Extension request "expand-path@openssh.com" This request supports canonicalisation of relative paths and those that need tilde-expansion, i.e. "~", "~/..." and "~user/..." @@ -578,50 +546,15 @@ This extension is advertised in the SSH_FXP_VERSION hello with version "1". -4.10. sftp: Extension request "copy-data" - -This request asks the server to copy data from one open file handle and -write it to a different open file handle. This avoids needing to transfer -the data across the network twice (a download followed by an upload). - - byte SSH_FXP_EXTENDED - uint32 id - string "copy-data" - string read-from-handle - uint64 read-from-offset - uint64 read-data-length - string write-to-handle - uint64 write-to-offset - -The server will copy read-data-length bytes starting from -read-from-offset from the read-from-handle and write them to -write-to-handle starting from write-to-offset, and then respond with a -SSH_FXP_STATUS message. - -It's equivalent to issuing a series of SSH_FXP_READ requests on -read-from-handle and a series of requests of SSH_FXP_WRITE on -write-to-handle. - -If read-from-handle and write-to-handle are the same, the server will -fail the request and respond with a SSH_FX_INVALID_PARAMETER message. - -If read-data-length is 0, then the server will read data from the -read-from-handle until EOF is reached. - -This extension is advertised in the SSH_FXP_VERSION hello with version -"1". - -This request is identical to the "copy-data" request documented in: - -https://tools.ietf.org/html/draft-ietf-secsh-filexfer-extensions-00#section-7 - -4.11. sftp: Extension request "home-directory" +3.10. sftp: Extension request "home-directory" This request asks the server to expand the specified user's home directory. An empty username implies the current user. This can be used by the client to expand ~/ type paths locally. - byte SSH_FXP_EXTENDED +It is implemented as a SSH_FXP_EXTENDED request with the following +format: + uint32 id string "home-directory" string username @@ -635,7 +568,7 @@ https://datatracker.ietf.org/doc/html/draft-ietf-secsh-filexfer-extensions-00#section-5 -4.12. sftp: Extension request "users-groups-by-id@openssh.com" +3.11. sftp: Extension request "users-groups-by-id@openssh.com" This request asks the server to return user and/or group names that correspond to one or more IDs (e.g. as returned from a SSH_FXP_STAT @@ -676,9 +609,9 @@ This extension is advertised in the SSH_FXP_VERSION hello with version "1". -5. Miscellaneous changes +4. Miscellaneous changes -5.1 Public key format +4.1 Public key format OpenSSH public keys, as generated by ssh-keygen(1) and appearing in authorized_keys files, are formatted as a single line of text consisting @@ -689,27 +622,24 @@ and the "New public key formats" section of PROTOCOL.certkeys for the OpenSSH certificate formats. -5.2 Private key format +4.2 Private key format OpenSSH private keys, as generated by ssh-keygen(1) use the format -described in PROTOCOL.key by default. As a legacy option, PEM format -(RFC7468) private keys are also supported for RSA, DSA and ECDSA keys +described in PROTOCOL.key by default. Private keys in portable PEM +format (RFC7468) are also supported for RSA, DSA and ECDSA keys and were the default format before OpenSSH 7.8. +Note that X.509 keys require standardized PEM format. +Also in FIPS mode proprietary format is not supported. -5.3 KRL format +4.3 KRL format OpenSSH supports a compact format for Key Revocation Lists (KRLs). This format is described in the PROTOCOL.krl file. -5.4 Connection multiplexing +4.4 Connection multiplexing OpenSSH's connection multiplexing uses messages as described in PROTOCOL.mux over a Unix domain socket for communications between a master instance and later clients. -5.5. Agent protocol extensions - -OpenSSH extends the usual agent protocol. These changes are documented -in the PROTOCOL.agent file. - $OpenBSD: PROTOCOL,v 1.48 2022/11/07 01:53:01 dtucker Exp $ diff -ruN openssh-9.4p1/PROTOCOL.agent openssh-9.4p1+x509-14.2.1/PROTOCOL.agent --- openssh-9.4p1/PROTOCOL.agent 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/PROTOCOL.agent 2023-08-20 10:07:00.000000000 +0300 @@ -1,84 +1,5 @@ -The SSH agent protocol is described in +This file used to contain a description of the SSH agent protocol +implemented by OpenSSH. It has since been superseded by https://tools.ietf.org/html/draft-miller-ssh-agent-04 -This file documents OpenSSH's extensions to the agent protocol. - -1. session-bind@openssh.com extension - -This extension allows a ssh client to bind an agent connection to a -particular SSH session identifier as derived from the initial key -exchange (as per RFC4253 section 7.2) and the host key used for that -exchange. This binding is verifiable at the agent by including the -initial KEX signature made by the host key. - -The message format is: - - byte SSH_AGENTC_EXTENSION (0x1b) - string session-bind@openssh.com - string hostkey - string session identifier - string signature - bool is_forwarding - -Where 'hostkey' is the encoded server host public key, 'session -identifier' is the exchange hash derived from the initial key -exchange, 'signature' is the server's signature of the session -identifier using the private hostkey, as sent in the final -SSH2_MSG_KEXDH_REPLY/SSH2_MSG_KEXECDH_REPLY message of the initial key -exchange. 'is_forwarding' is a flag indicating whether this connection -should be bound for user authentication or forwarding. - -When an agent received this message, it will verify the signature and -check the consistency of its contents, including refusing to accept -a duplicate session identifier, or any attempt to bind a connection -previously bound for authentication. It will then record the -binding for the life of the connection for use later in testing per-key -destination constraints. - -2. restrict-destination-v00@openssh.com key constraint extension - -The key constraint extension supports destination- and forwarding path- -restricted keys. It may be attached as a constraint when keys or -smartcard keys are added to an agent. - - byte SSH_AGENT_CONSTRAIN_EXTENSION (0xff) - string restrict-destination-v00@openssh.com - constraint[] constraints - -Where a constraint consists of: - - string from_username (must be empty) - string from_hostname - keyspec[] from_hostkeys - string to_username - string to_hostname - keyspec[] to_hostkeys - -And a keyspec consists of: - - string keyblob - bool is_ca - -When receiving this message, the agent will ensure that the -'from_username' field is empty, and that 'to_hostname' and 'to_hostkeys' -have been supplied (empty 'from_hostname' and 'from_hostkeys' are valid -and signify the initial hop from the host running ssh-agent). The agent -will then record the constraint against the key. - -Subsequent operations on this key including add/remove/request -identities and, in particular, signature requests will check the key -constraints against the session-bind@openssh.com bindings recorded for -the agent connection over which they were received. - -3. SSH_AGENT_CONSTRAIN_MAXSIGN key constraint - -This key constraint allows communication to an agent of the maximum -number of signatures that may be made with an XMSS key. The format of -the constraint is: - - byte SSH_AGENT_CONSTRAIN_MAXSIGN (0x03) - uint32 max_signatures - -This option is only valid for XMSS keys. - -$OpenBSD: PROTOCOL.agent,v 1.19 2023/04/12 08:53:54 jsg Exp $ +$OpenBSD: PROTOCOL.agent,v 1.14 2020/10/06 07:12:04 dtucker Exp $ diff -ruN openssh-9.4p1/PROTOCOL.certkeys openssh-9.4p1+x509-14.2.1/PROTOCOL.certkeys --- openssh-9.4p1/PROTOCOL.certkeys 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/PROTOCOL.certkeys 2023-08-20 10:07:00.000000000 +0300 @@ -259,14 +259,6 @@ certificates may be presented from any source address. -verify-required empty Flag indicating that signatures made - with this certificate must assert FIDO - user verification (e.g. PIN or - biometric). This option only makes sense - for the U2F/FIDO security key types that - support this feature in their signature - formats. - Extensions ---------- @@ -287,13 +279,6 @@ Name Format Description ----------------------------------------------------------------------------- -no-touch-required empty Flag indicating that signatures made - with this certificate need not assert - FIDO user presence. This option only - makes sense for the U2F/FIDO security - key types that support this feature in - their signature formats. - permit-X11-forwarding empty Flag indicating that X11 forwarding should be permitted. X11 forwarding will be refused if this option is absent. diff -ruN openssh-9.4p1/PROTOCOL.chacha20poly1305 openssh-9.4p1+x509-14.2.1/PROTOCOL.chacha20poly1305 --- openssh-9.4p1/PROTOCOL.chacha20poly1305 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/PROTOCOL.chacha20poly1305 2023-08-20 10:07:00.000000000 +0300 @@ -104,4 +104,3 @@ http://tools.ietf.org/html/draft-agl-tls-chacha20poly1305-03 $OpenBSD: PROTOCOL.chacha20poly1305,v 1.5 2020/02/21 00:04:43 dtucker Exp $ - diff -ruN openssh-9.4p1/PROTOCOL.krl openssh-9.4p1+x509-14.2.1/PROTOCOL.krl --- openssh-9.4p1/PROTOCOL.krl 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/PROTOCOL.krl 2023-08-20 10:07:00.000000000 +0300 @@ -194,8 +194,7 @@ 6. KRL signature sections Note: KRL signatures are not supported by OpenSSH. OpenSSH >= 9.4 will -refuse to load KRLs that contain signatures. We recommend the use -of SSHSIG (`ssh-keygen -Y sign ...`) style signatures for KRLs instead. +refuse to load KRLs that contain signatures. The KRL_SECTION_SIGNATURE section serves a different purpose to the preceding ones: to provide cryptographic authentication of a KRL that diff -ruN openssh-9.4p1/PROTOCOL.sshsig openssh-9.4p1+x509-14.2.1/PROTOCOL.sshsig --- openssh-9.4p1/PROTOCOL.sshsig 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/PROTOCOL.sshsig 1970-01-01 02:00:00.000000000 +0200 @@ -1,100 +0,0 @@ -This document describes a lightweight SSH Signature format -that is compatible with SSH keys and wire formats. - -At present, only detached and armored signatures are supported. - -1. Armored format - -The Armored SSH signatures consist of a header, a base64 -encoded blob, and a footer. - -The header is the string "-----BEGIN SSH SIGNATURE-----" -followed by a newline. The footer is the string -"-----END SSH SIGNATURE-----" immediately after a newline. - -The header MUST be present at the start of every signature. -Files containing the signature MUST start with the header. -Likewise, the footer MUST be present at the end of every -signature. - -The base64 encoded blob SHOULD be broken up by newlines -every 76 characters. - -Example: - ------BEGIN SSH SIGNATURE----- -U1NIU0lHAAAAAQAAADMAAAALc3NoLWVkMjU1MTkAAAAgJKxoLBJBivUPNTUJUSslQTt2hD -jozKvHarKeN8uYFqgAAAADZm9vAAAAAAAAAFMAAAALc3NoLWVkMjU1MTkAAABAKNC4IEbt -Tq0Fb56xhtuE1/lK9H9RZJfON4o6hE9R4ZGFX98gy0+fFJ/1d2/RxnZky0Y7GojwrZkrHT -FgCqVWAQ== ------END SSH SIGNATURE----- - -2. Blob format - -#define MAGIC_PREAMBLE "SSHSIG" -#define SIG_VERSION 0x01 - - byte[6] MAGIC_PREAMBLE - uint32 SIG_VERSION - string publickey - string namespace - string reserved - string hash_algorithm - string signature - -The publickey field MUST contain the serialisation of the -public key used to make the signature using the usual SSH -encoding rules, i.e RFC4253, RFC5656, -draft-ietf-curdle-ssh-ed25519-ed448, etc. - -Verifiers MUST reject signatures with versions greater than those -they support. - -The purpose of the namespace value is to specify a unambiguous -interpretation domain for the signature, e.g. file signing. -This prevents cross-protocol attacks caused by signatures -intended for one intended domain being accepted in another. -The namespace value MUST NOT be the empty string. - -The reserved value is present to encode future information -(e.g. tags) into the signature. Implementations should ignore -the reserved field if it is not empty. - -Data to be signed is first hashed with the specified hash_algorithm. -This is done to limit the amount of data presented to the signature -operation, which may be of concern if the signing key is held in limited -or slow hardware or on a remote ssh-agent. The supported hash algorithms -are "sha256" and "sha512". - -The signature itself is made using the SSH signature algorithm and -encoding rules for the chosen key type. For RSA signatures, the -signature algorithm must be "rsa-sha2-512" or "rsa-sha2-256" (i.e. -not the legacy RSA-SHA1 "ssh-rsa"). - -This blob is encoded as a string using the RFC4253 encoding -rules and base64 encoded to form the middle part of the -armored signature. - - -3. Signed Data, of which the signature goes into the blob above - -#define MAGIC_PREAMBLE "SSHSIG" - - byte[6] MAGIC_PREAMBLE - string namespace - string reserved - string hash_algorithm - string H(message) - -The preamble is the six-byte sequence "SSHSIG". It is included to -ensure that manual signatures can never be confused with any message -signed during SSH user or host authentication. - -The reserved value is present to encode future information -(e.g. tags) into the signature. Implementations should ignore -the reserved field if it is not empty. - -The data is concatenated and passed to the SSH signing -function. - -$OpenBSD: PROTOCOL.sshsig,v 1.4 2020/08/31 00:17:41 djm Exp $ diff -ruN openssh-9.4p1/PROTOCOL.u2f openssh-9.4p1+x509-14.2.1/PROTOCOL.u2f --- openssh-9.4p1/PROTOCOL.u2f 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/PROTOCOL.u2f 1970-01-01 02:00:00.000000000 +0200 @@ -1,309 +0,0 @@ -This document describes OpenSSH's support for U2F/FIDO security keys. - -Background ----------- - -U2F is an open standard for two-factor authentication hardware, widely -used for user authentication to websites. U2F tokens are ubiquitous, -available from a number of manufacturers and are currently by far the -cheapest way for users to achieve hardware-backed credential storage. - -The U2F protocol however cannot be trivially used as an SSH protocol key -type as both the inputs to the signature operation and the resultant -signature differ from those specified for SSH. For similar reasons, -integration of U2F devices cannot be achieved via the PKCS#11 API. - -U2F also offers a number of features that are attractive in the context -of SSH authentication. They can be configured to require indication -of "user presence" for each signature operation (typically achieved -by requiring the user touch the key). They also offer an attestation -mechanism at key enrollment time that can be used to prove that a -given key is backed by hardware. Finally the signature format includes -a monotonic signature counter that can be used (at scale) to detect -concurrent use of a private key, should it be extracted from hardware. - -U2F private keys are generated through an enrollment operation, -which takes an application ID - a URL-like string, typically "ssh:" -in this case, but a HTTP origin for the case of web authentication, -and a challenge string (typically randomly generated). The enrollment -operation returns a public key, a key handle that must be used to invoke -the hardware-backed private key, some flags and signed attestation -information that may be used to verify that a private key is hosted on a -particular hardware instance. - -It is common for U2F hardware to derive private keys from the key handle -in conjunction with a small per-device secret that is unique to the -hardware, thus requiring little on-device storage for an effectively -unlimited number of supported keys. This drives the requirement that -the key handle be supplied for each signature operation. U2F tokens -primarily use ECDSA signatures in the NIST-P256 field, though the FIDO2 -standard specifies additional key types, including one based on Ed25519. - -Use of U2F security keys does not automatically imply multi-factor -authentication. From sshd's perspective, a security key constitutes a -single factor of authentication, even if protected by a PIN or biometric -authentication. To enable multi-factor authentication in ssh, please -refer to the AuthenticationMethods option in sshd_config(5). - - -SSH U2F Key formats -------------------- - -OpenSSH integrates U2F as new key and corresponding certificate types: - - sk-ecdsa-sha2-nistp256@openssh.com - sk-ecdsa-sha2-nistp256-cert-v01@openssh.com - sk-ssh-ed25519@openssh.com - sk-ssh-ed25519-cert-v01@openssh.com - -While each uses ecdsa-sha256-nistp256 as the underlying signature primitive, -keys require extra information in the public and private keys, and in -the signature object itself. As such they cannot be made compatible with -the existing ecdsa-sha2-nistp* key types. - -The format of a sk-ecdsa-sha2-nistp256@openssh.com public key is: - - string "sk-ecdsa-sha2-nistp256@openssh.com" - string curve name - ec_point Q - string application (user-specified, but typically "ssh:") - -The corresponding private key contains: - - string "sk-ecdsa-sha2-nistp256@openssh.com" - string curve name - ec_point Q - string application (user-specified, but typically "ssh:") - uint8 flags - string key_handle - string reserved - -The format of a sk-ssh-ed25519@openssh.com public key is: - - string "sk-ssh-ed25519@openssh.com" - string public key - string application (user-specified, but typically "ssh:") - -With a private half consisting of: - - string "sk-ssh-ed25519@openssh.com" - string public key - string application (user-specified, but typically "ssh:") - uint8 flags - string key_handle - string reserved - -The certificate form for SSH U2F keys appends the usual certificate -information to the public key: - - string "sk-ecdsa-sha2-nistp256-cert-v01@openssh.com" - string nonce - string curve name - ec_point Q - string application - uint64 serial - uint32 type - string key id - string valid principals - uint64 valid after - uint64 valid before - string critical options - string extensions - string reserved - string signature key - string signature - -and for security key ed25519 certificates: - - string "sk-ssh-ed25519-cert-v01@openssh.com" - string nonce - string public key - string application - uint64 serial - uint32 type - string key id - string valid principals - uint64 valid after - uint64 valid before - string critical options - string extensions - string reserved - string signature key - string signature - -Both security key certificates use the following encoding for private keys: - - string type (e.g. "sk-ssh-ed25519-cert-v01@openssh.com") - string pubkey (the above key/cert structure) - string application - uint8 flags - string key_handle - string reserved - -During key generation, the hardware also returns attestation information -that may be used to cryptographically prove that a given key is -hardware-backed. Unfortunately, the protocol required for this proof is -not privacy-preserving and may be used to identify U2F tokens with at -least manufacturer and batch number granularity. For this reason, we -choose not to include this information in the public key or save it by -default. - -Attestation information is useful for out-of-band key and certificate -registration workflows, e.g. proving to a CA that a key is backed -by trusted hardware before it will issue a certificate. To support this -case, OpenSSH optionally allows retaining the attestation information -at the time of key generation. It will take the following format: - - string "ssh-sk-attest-v01" - string attestation certificate - string enrollment signature - string authenticator data (CBOR encoded) - uint32 reserved flags - string reserved string - -A previous version of this format, emitted prior to OpenSSH 8.4 omitted -the authenticator data. - - string "ssh-sk-attest-v00" - string attestation certificate - string enrollment signature - uint32 reserved flags - string reserved string - -OpenSSH treats the attestation certificate and enrollment signatures as -opaque objects and does no interpretation of them itself. - -SSH U2F signatures ------------------- - -In addition to the message to be signed, the U2F signature operation -requires the key handle and a few additional parameters. The signature -is signed over a blob that consists of: - - byte[32] SHA256(application) - byte flags (including "user present", extensions present) - uint32 counter - byte[] extensions - byte[32] SHA256(message) - -No extensions are yet defined for SSH use. If any are defined in the future, -it will be possible to infer their presence from the contents of the "flags" -value. - -The signature returned from U2F hardware takes the following format: - - byte flags (including "user present") - uint32 counter - byte[] ecdsa_signature (in X9.62 format). - -For use in the SSH protocol, we wish to avoid server-side parsing of ASN.1 -format data in the pre-authentication attack surface. Therefore, the -signature format used on the wire in SSH2_USERAUTH_REQUEST packets will -be reformatted to better match the existing signature encoding: - - string "sk-ecdsa-sha2-nistp256@openssh.com" - string ecdsa_signature - byte flags - uint32 counter - -Where the "ecdsa_signature" field follows the RFC5656 ECDSA signature -encoding: - - mpint r - mpint s - -For Ed25519 keys the signature is encoded as: - - string "sk-ssh-ed25519@openssh.com" - string signature - byte flags - uint32 counter - -webauthn signatures -------------------- - -The W3C/FIDO webauthn[1] standard defines a mechanism for a web browser to -interact with FIDO authentication tokens. This standard builds upon the -FIDO standards, but requires different signature contents to raw FIDO -messages. OpenSSH supports ECDSA/p256 webauthn signatures through the -"webauthn-sk-ecdsa-sha2-nistp256@openssh.com" signature algorithm. - -The wire encoding for a webauthn-sk-ecdsa-sha2-nistp256@openssh.com -signature is similar to the sk-ecdsa-sha2-nistp256@openssh.com format: - - string "webauthn-sk-ecdsa-sha2-nistp256@openssh.com" - string ecdsa_signature - byte flags - uint32 counter - string origin - string clientData - string extensions - -Where "origin" is the HTTP origin making the signature, "clientData" is -the JSON-like structure signed by the browser and "extensions" are any -extensions used in making the signature. - -[1] https://www.w3.org/TR/webauthn-2/ - -ssh-agent protocol extensions ------------------------------ - -ssh-agent requires a protocol extension to support U2F keys. At -present the closest analogue to Security Keys in ssh-agent are PKCS#11 -tokens, insofar as they require a middleware library to communicate with -the device that holds the keys. Unfortunately, the protocol message used -to add PKCS#11 keys to ssh-agent does not include any way to send the -key handle to the agent as U2F keys require. - -To avoid this, without having to add wholly new messages to the agent -protocol, we will use the existing SSH2_AGENTC_ADD_ID_CONSTRAINED message -with a new key constraint extension to encode a path to the middleware -library for the key. The format of this constraint extension would be: - - byte SSH_AGENT_CONSTRAIN_EXTENSION - string sk-provider@openssh.com - string middleware path - -This constraint-based approach does not present any compatibility -problems. - -OpenSSH integration -------------------- - -U2F tokens may be attached via a number of means, including USB and NFC. -The USB interface is standardised around a HID protocol, but we want to -be able to support other transports as well as dummy implementations for -regress testing. For this reason, OpenSSH shall support a dynamically- -loaded middleware libraries to communicate with security keys, but offer -support for the common case of USB HID security keys internally. - -The middleware library need only expose a handful of functions and -numbers listed in sk-api.h. Included in the defined numbers is a -SSH_SK_VERSION_MAJOR that should be incremented for each incompatible -API change. - -miscellaneous options may be passed to the middleware as a NULL- -terminated array of pointers to struct sk_option. The middleware may -ignore unsupported or unknown options unless the "required" flag is set, -in which case it should return failure if an unsupported option is -requested. - -At present the following options names are supported: - - "device" - - Specifies a specific FIDO device on which to perform the - operation. The value in this field is interpreted by the - middleware but it would be typical to specify a path to - a /dev node for the device in question. - - "user" - - Specifies the FIDO2 username used when enrolling a key, - overriding OpenSSH's default of using an all-zero username. - -In OpenSSH, the middleware will be invoked by using a similar mechanism to -ssh-pkcs11-helper to provide address-space containment of the -middleware from ssh-agent. - -$OpenBSD: PROTOCOL.u2f,v 1.26 2020/09/09 03:08:01 djm Exp $ diff -ruN openssh-9.4p1/readconf.c openssh-9.4p1+x509-14.2.1/readconf.c --- openssh-9.4p1/readconf.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/readconf.c 2023-08-20 10:07:01.000000000 +0300 @@ -10,6 +10,28 @@ * software must be clearly marked as such, and if the derived work is * incompatible with the protocol description in the RFC file, it must be * called by a name other than "ssh" or "Secure Shell". + * + * Copyright (c) 2002-2023 Roumen Petrov. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "includes.h" @@ -57,7 +79,6 @@ #include "xmalloc.h" #include "ssh.h" -#include "ssherr.h" #include "cipher.h" #include "pathnames.h" #include "log.h" @@ -66,8 +87,8 @@ #include "readconf.h" #include "match.h" #include "kex.h" +#include "ssh-xkalg.h" #include "mac.h" -#include "uidswap.h" #include "myproposal.h" #include "digest.h" @@ -132,6 +153,9 @@ */ +/* used in ssh-rsa.c */ +extern int required_rsa_size; + static int read_config_file_depth(const char *filename, struct passwd *pw, const char *host, const char *original_host, Options *options, int flags, int *activep, int *want_final_pass, int depth); @@ -144,6 +168,21 @@ typedef enum { oBadOption, + /* X.509 Standard Options */ + oHostbasedAlgorithms, + oPubkeyAlgorithms, + oX509KeyAlgorithm, + oAllowedServerCertPurpose, + oMandatoryCRL, + oCACertificateFile, oCACertificatePath, + oCARevocationFile, oCARevocationPath, + oCAStoreURI, + oCAldapVersion, oCAldapURL, + oUserCACertificateFile, oUserCACertificatePath, + oUserCARevocationFile, oUserCARevocationPath, + oVAType, oVACertificateFile, + oVAOCSPResponderURL, + /* Standard Options */ oHost, oMatch, oInclude, oTag, oForwardAgent, oForwardX11, oForwardX11Trusted, oForwardX11Timeout, oGatewayPorts, oExitOnForwardFailure, @@ -198,14 +237,16 @@ { "useroaming", oDeprecated }, { "usersh", oDeprecated }, { "useprivilegedport", oDeprecated }, + { "rsaauthentication", oDeprecated }, + { "rhostsrsaauthentication", oDeprecated }, + { "skeyauthentication", oDeprecated }, + { "tisauthentication", oDeprecated }, + { "compressionlevel", oDeprecated }, /* Unsupported options */ { "afstokenpassing", oUnsupported }, { "kerberosauthentication", oUnsupported }, { "kerberostgtpassing", oUnsupported }, - { "rsaauthentication", oUnsupported }, - { "rhostsrsaauthentication", oUnsupported }, - { "compressionlevel", oUnsupported }, /* Sometimes-unsupported options */ #if defined(GSSAPI) @@ -216,13 +257,37 @@ { "gssapidelegatecredentials", oUnsupported }, #endif #ifdef ENABLE_PKCS11 + { "smartcarddevice", oDeprecated }, { "pkcs11provider", oPKCS11Provider }, - { "smartcarddevice", oPKCS11Provider }, # else { "smartcarddevice", oUnsupported }, { "pkcs11provider", oUnsupported }, #endif + { "securitykeyprovider", oSecurityKeyProvider }, + /* X.509 Standard Options */ + { "hostbasedalgorithms", oHostbasedAlgorithms }, + { "pubkeyalgorithms", oPubkeyAlgorithms }, + { "x509keyalgorithm", oX509KeyAlgorithm }, + { "allowedcertpurpose", oAllowedServerCertPurpose }, + { "mandatorycrl", oMandatoryCRL }, + { "cacertificatefile", oCACertificateFile }, + { "cacertificatepath", oCACertificatePath }, + { "carevocationfile", oCARevocationFile }, + { "carevocationpath", oCARevocationPath }, + { "castoreuri", oCAStoreURI }, /* experimental, i.e. no documentation */ + { "caldapversion", oCAldapVersion }, + { "caldapurl", oCAldapURL }, + { "usercacertificatefile", oUserCACertificateFile }, + { "usercacertificatepath", oUserCACertificatePath }, + { "usercarevocationfile", oUserCARevocationFile }, + { "usercarevocationpath", oUserCARevocationPath }, + { "usercaldapversion", oCAldapVersion }, + { "usercaldapurl", oCAldapURL }, + { "vatype", oVAType }, + { "vacertificatefile", oVACertificateFile }, + { "vaocspresponderurl", oVAOCSPResponderURL }, + /* Standard Options */ { "forwardagent", oForwardAgent }, { "forwardx11", oForwardX11 }, { "forwardx11trusted", oForwardX11Trusted }, @@ -234,8 +299,6 @@ { "kbdinteractiveauthentication", oKbdInteractiveAuthentication }, { "kbdinteractivedevices", oKbdInteractiveDevices }, { "challengeresponseauthentication", oKbdInteractiveAuthentication }, /* alias */ - { "skeyauthentication", oKbdInteractiveAuthentication }, /* alias */ - { "tisauthentication", oKbdInteractiveAuthentication }, /* alias */ { "pubkeyauthentication", oPubkeyAuthentication }, { "dsaauthentication", oPubkeyAuthentication }, /* alias */ { "hostbasedauthentication", oHostbasedAuthentication }, @@ -323,7 +386,6 @@ { "pubkeyacceptedkeytypes", oPubkeyAcceptedAlgorithms }, /* obsolete */ { "ignoreunknown", oIgnoreUnknown }, { "proxyjump", oProxyJump }, - { "securitykeyprovider", oSecurityKeyProvider }, { "knownhostscommand", oKnownHostsCommand }, { "requiredrsasize", oRequiredRSASize }, { "enableescapecommandline", oEnableEscapeCommandline }, @@ -333,21 +395,6 @@ static const char *lookup_opcode_name(OpCodes code); -const char * -kex_default_pk_alg(void) -{ - static char *pkalgs; - - if (pkalgs == NULL) { - char *all_key; - - all_key = sshkey_alg_list(0, 0, 1, ','); - pkalgs = match_filter_allowlist(KEX_DEFAULT_PK_ALG, all_key); - free(all_key); - } - return pkalgs; -} - char * ssh_connection_hash(const char *thishost, const char *host, const char *portstr, const char *user) @@ -588,7 +635,7 @@ static int check_match_ifaddrs(const char *addrlist) { -#ifdef HAVE_IFADDRS_H +#ifdef HAVE_GETIFADDRS struct ifaddrs *ifa, *ifaddrs = NULL; int r, found = 0; char addr[NI_MAXHOST]; @@ -636,10 +683,11 @@ } freeifaddrs(ifaddrs); return found; -#else /* HAVE_IFADDRS_H */ +#else /* HAVE_GETIFADDRS */ + UNUSED(addrlist); error("match localnetwork: not supported on this platform"); return 0; -#endif /* HAVE_IFADDRS_H */ +#endif /* HAVE_GETIFADDRS */ } /* @@ -650,11 +698,9 @@ const char *host_arg, const char *original_host, int final_pass, int *want_final_pass, const char *filename, int linenum) { - char *arg, *oattrib, *attrib, *cmd, *cp = *condition, *host, *criteria; + char *arg, *oattrib, *attrib, *cp = *condition, *host; const char *ruser; - int r, port, this_result, result = 1, attributes = 0, negate; - char thishost[NI_MAXHOST], shorthost[NI_MAXHOST], portstr[NI_MAXSERV]; - char uidstr[32]; + int r, port, result = 1, attributes = 0; /* * Configuration is likely to be incomplete at this point so we @@ -675,33 +721,28 @@ debug2("checking match for '%s' host %s originally %s", cp, host, original_host); while ((oattrib = attrib = strdelim(&cp)) && *attrib != '\0') { - /* Terminate on comment */ - if (*attrib == '#') { - cp = NULL; /* mark all arguments consumed */ - break; - } - arg = criteria = NULL; - this_result = 1; - if ((negate = (attrib[0] == '!'))) + char *criteria = NULL; + int this_result = 1; + int negate = attrib[0] == '!'; + + if (negate) attrib++; /* Criterion "all" has no argument and must appear alone */ if (strcasecmp(attrib, "all") == 0) { if (attributes > 1 || ((arg = strdelim(&cp)) != NULL && - *arg != '\0' && *arg != '#')) { + *arg != '\0')) { error("%.200s line %d: '%s' cannot be combined " "with other Match attributes", filename, linenum, oattrib); result = -1; goto out; } - if (arg != NULL && *arg == '#') - cp = NULL; /* mark all arguments consumed */ if (result) result = negate ? 0 : 1; goto out; } attributes++; - /* criteria "final" and "canonical" have no argument */ + /* Criteria "final" and "canonical" have no argument */ if (strcasecmp(attrib, "canonical") == 0 || strcasecmp(attrib, "final") == 0) { /* @@ -721,7 +762,7 @@ } /* All other criteria require an argument */ if ((arg = strdelim(&cp)) == NULL || - *arg == '\0' || *arg == '#') { + *arg == '\0') { error("Missing Match criteria for %s", attrib); result = -1; goto out; @@ -762,7 +803,9 @@ if (r == (negate ? 1 : 0)) this_result = result = 0; } else if (strcasecmp(attrib, "exec") == 0) { - char *conn_hash_hex, *keyalias; + char thishost[NI_MAXHOST], shorthost[NI_MAXHOST]; + char portstr[NI_MAXSERV], uidstr[32]; + char *cmd, *conn_hash_hex, *keyalias; if (gethostname(thishost, sizeof(thishost)) == -1) fatal("gethostname: %s", strerror(errno)); @@ -776,18 +819,19 @@ keyalias = options->host_key_alias ? options->host_key_alias : host; + /* keep synchronised with sshconnect.h */ cmd = percent_expand(arg, "C", conn_hash_hex, "L", shorthost, - "d", pw->pw_dir, - "h", host, + "i", uidstr, "k", keyalias, "l", thishost, "n", original_host, "p", portstr, + "h", host, "r", ruser, + "d", pw->pw_dir, "u", pw->pw_name, - "i", uidstr, (char *)NULL); free(conn_hash_hex); if (result != 1) { @@ -814,7 +858,7 @@ result = -1; goto out; } - debug3("%.200s line %d: %smatched '%s%s%.100s%s' ", + debug3("%.200s line %d: %smatched '%s%s%.100s%s'", filename, linenum, this_result ? "": "not ", oattrib, criteria == NULL ? "" : " \"", criteria == NULL ? "" : criteria, @@ -834,36 +878,6 @@ return result; } -/* Remove environment variable by pattern */ -static void -rm_env(Options *options, const char *arg, const char *filename, int linenum) -{ - u_int i, j, onum_send_env = options->num_send_env; - - /* Remove an environment variable */ - for (i = 0; i < options->num_send_env; ) { - if (!match_pattern(options->send_env[i], arg + 1)) { - i++; - continue; - } - debug3("%s line %d: removing environment %s", - filename, linenum, options->send_env[i]); - free(options->send_env[i]); - options->send_env[i] = NULL; - for (j = i; j < options->num_send_env - 1; j++) { - options->send_env[j] = options->send_env[j + 1]; - options->send_env[j + 1] = NULL; - } - options->num_send_env--; - /* NB. don't increment i */ - } - if (onum_send_env != options->num_send_env) { - options->send_env = xrecallocarray(options->send_env, - onum_send_env, options->num_send_env, - sizeof(*options->send_env)); - } -} - /* * Returns the number of the token pointed to by cp or oBadOption. */ @@ -884,43 +898,62 @@ return oBadOption; } +static int +parse_time(const char *arg, const char *filename, int linenum) +{ + long t = convtime(arg); + + if (t == -1) { + error("%s line %d: invalid time value.", filename, linenum); + return -1; + } +#if SIZEOF_LONG_INT > SIZEOF_INT + if (t > INT_MAX) { + error("%s line %d: too high time value.", filename, linenum); + return -1; + } +#endif + return (int)t; /*safe cast*/ +} + /* Multistate option parsing */ struct multistate { - char *key; + const char *key; int value; }; +/* use true and false at end for compatibility */ static const struct multistate multistate_flag[] = { - { "true", 1 }, - { "false", 0 }, { "yes", 1 }, { "no", 0 }, + { "true", 1 }, + { "false", 0 }, { NULL, -1 } }; static const struct multistate multistate_yesnoask[] = { - { "true", 1 }, - { "false", 0 }, { "yes", 1 }, { "no", 0 }, { "ask", 2 }, + { "true", 1 }, + { "false", 0 }, { NULL, -1 } }; static const struct multistate multistate_strict_hostkey[] = { - { "true", SSH_STRICT_HOSTKEY_YES }, - { "false", SSH_STRICT_HOSTKEY_OFF }, { "yes", SSH_STRICT_HOSTKEY_YES }, { "no", SSH_STRICT_HOSTKEY_OFF }, { "ask", SSH_STRICT_HOSTKEY_ASK }, { "off", SSH_STRICT_HOSTKEY_OFF }, { "accept-new", SSH_STRICT_HOSTKEY_NEW }, + { "true", SSH_STRICT_HOSTKEY_YES }, + { "false", SSH_STRICT_HOSTKEY_OFF }, { NULL, -1 } }; static const struct multistate multistate_yesnoaskconfirm[] = { - { "true", 1 }, - { "false", 0 }, { "yes", 1 }, { "no", 0 }, { "ask", 2 }, { "confirm", 3 }, + { "true", 1 }, + { "false", 0 }, { NULL, -1 } }; static const struct multistate multistate_addressfamily[] = { @@ -930,31 +963,31 @@ { NULL, -1 } }; static const struct multistate multistate_controlmaster[] = { - { "true", SSHCTL_MASTER_YES }, { "yes", SSHCTL_MASTER_YES }, - { "false", SSHCTL_MASTER_NO }, { "no", SSHCTL_MASTER_NO }, { "auto", SSHCTL_MASTER_AUTO }, { "ask", SSHCTL_MASTER_ASK }, { "autoask", SSHCTL_MASTER_AUTO_ASK }, + { "true", SSHCTL_MASTER_YES }, + { "false", SSHCTL_MASTER_NO }, { NULL, -1 } }; static const struct multistate multistate_tunnel[] = { { "ethernet", SSH_TUNMODE_ETHERNET }, { "point-to-point", SSH_TUNMODE_POINTOPOINT }, - { "true", SSH_TUNMODE_DEFAULT }, { "yes", SSH_TUNMODE_DEFAULT }, - { "false", SSH_TUNMODE_NO }, { "no", SSH_TUNMODE_NO }, + { "true", SSH_TUNMODE_DEFAULT }, + { "false", SSH_TUNMODE_NO }, { NULL, -1 } }; static const struct multistate multistate_requesttty[] = { - { "true", REQUEST_TTY_YES }, { "yes", REQUEST_TTY_YES }, - { "false", REQUEST_TTY_NO }, { "no", REQUEST_TTY_NO }, { "force", REQUEST_TTY_FORCE }, { "auto", REQUEST_TTY_AUTO }, + { "true", REQUEST_TTY_YES }, + { "false", REQUEST_TTY_NO }, { NULL, -1 } }; static const struct multistate multistate_sessiontype[] = { @@ -964,38 +997,23 @@ { NULL, -1 } }; static const struct multistate multistate_canonicalizehostname[] = { - { "true", SSH_CANONICALISE_YES }, - { "false", SSH_CANONICALISE_NO }, { "yes", SSH_CANONICALISE_YES }, { "no", SSH_CANONICALISE_NO }, { "always", SSH_CANONICALISE_ALWAYS }, - { NULL, -1 } -}; -static const struct multistate multistate_pubkey_auth[] = { - { "true", SSH_PUBKEY_AUTH_ALL }, - { "false", SSH_PUBKEY_AUTH_NO }, - { "yes", SSH_PUBKEY_AUTH_ALL }, - { "no", SSH_PUBKEY_AUTH_NO }, - { "unbound", SSH_PUBKEY_AUTH_UNBOUND }, - { "host-bound", SSH_PUBKEY_AUTH_HBOUND }, - { NULL, -1 } -}; -static const struct multistate multistate_compression[] = { -#ifdef WITH_ZLIB - { "yes", COMP_ZLIB }, -#endif - { "no", COMP_NONE }, + { "true", SSH_CANONICALISE_YES }, + { "false", SSH_CANONICALISE_NO }, { NULL, -1 } }; static int -parse_multistate_value(const char *arg, const char *filename, int linenum, - const struct multistate *multistate_ptr) +parse_multistate_value(const char *arg, const struct multistate *multistate_ptr, + const char *filename, int linenum, const char* keyword) { int i; - if (!arg || *arg == '\0') { - error("%s line %d: missing argument.", filename, linenum); + if (arg == NULL || *arg == '\0') { + error("%s line %d: %s missing argument.", + filename, linenum, keyword); return -1; } for (i = 0; multistate_ptr[i].key != NULL; i++) { @@ -1024,11 +1042,13 @@ const char *original_host, char *line, const char *filename, int linenum, int *activep, int flags, int *want_final_pass, int depth) { - char *str, **charptr, *endofnumber, *keyword, *arg, *arg2, *p; + char *str, **charptr, *endofnumber, *keyword, *arg, *arg2; + char **oav = NULL, **av; + int oac = 0, ac; char **cpptr, ***cppptr, fwdarg[256]; - u_int i, *uintptr, uvalue, max_entries = 0; - int r, oactive, negated, opcode, *intptr, value, value2, cmdline = 0; - int remotefwd, dynamicfwd, ca_only = 0; + u_int i, *uintptr, max_entries = 0; + int r, oactive, negated, opcode, *intptr, value, value2, cmdline = 0, found; + int remotefwd, dynamicfwd, ca_only; LogLevel *log_level_ptr; SyslogFacility *log_facility_ptr; long long val64; @@ -1038,8 +1058,6 @@ struct allowed_cname *cname; glob_t gl; const char *errstr; - char **oav = NULL, **av; - int oac = 0, ac; int ret = -1; if (activep == NULL) { /* We are processing a command line directive */ @@ -1063,7 +1081,7 @@ /* Ignore leading whitespace. */ if (*keyword == '\0') keyword = strdelim(&str); - if (keyword == NULL || !*keyword || *keyword == '\n' || *keyword == '#') + if (keyword == NULL || *keyword == '\0' || *keyword == '\n' || *keyword == '#') return 0; /* Match lowercase keyword */ lowercase(keyword); @@ -1076,14 +1094,17 @@ filename, linenum, keyword); return -1; } + opcode = parse_token(keyword, filename, linenum, options->ignored_unknown); + if (argv_split(str, &oac, &oav, 1) != 0) { error("%s line %d: invalid quotes", filename, linenum); return -1; } ac = oac; av = oav; + ca_only = 0; switch (opcode) { case oBadOption: @@ -1097,21 +1118,191 @@ filename, linenum, keyword); argv_consume(&ac); break; + /* X.509 Standard Options */ + case oHostbasedAcceptedAlgorithms: /* compatibility ;) */ + case oHostbasedAlgorithms: + charptr = (char**)&options->hostbased_algorithms; + arg = argv_next(&ac, &av); + if (arg == NULL || *arg == '\0') { + error("%s line %d: %s missing argument.", + filename, linenum, keyword); + goto out; + } + /* cannot validate here - depend from X509KeyAlgorithm */ + if (*activep && *charptr == NULL) + *charptr = xstrdup(arg); + break; + + case oPubkeyAcceptedAlgorithms: /* compatibility ;) */ + case oPubkeyAlgorithms: + charptr = (char**)&options->pubkey_algorithms; + arg = argv_next(&ac, &av); + if (arg == NULL || *arg == '\0') { + error("%s line %d: %s missing argument.", + filename, linenum, keyword); + goto out; + } + /* cannot validate here - depend from X509KeyAlgorithm */ + if (*activep && *charptr == NULL) + *charptr = xstrdup(arg); + break; + + case oX509KeyAlgorithm: + arg = argv_next(&ac, &av); + if (arg == NULL || *arg == '\0') { + error("%s line %d: %s missing argument.", + filename, linenum, keyword); + goto out; + } + + if (*activep) { + if (ssh_add_x509key_alg(arg) < 0) { + error("%.200s line %d: Bad X.509 key algorithm '%.200s'.", + filename, linenum, arg); + goto out; + } + } + break; + + case oAllowedServerCertPurpose: + intptr = &options->x509flags->allowedcertpurpose; + arg = argv_next(&ac, &av); + if (arg != NULL && *arg != '\0') { + if (strcasecmp(arg, "skip") == 0) goto skip_purpose; + + /* convert string to OpenSSL index */ + value = ssh_get_x509purpose_s (0, arg); + if (value < 0) { + error("%.200s line %d: Bad certificate purpose '%.30s'.", + filename, linenum, arg); + goto out; + } + + if (*activep && *intptr == -1) + *intptr = value; + } else { +skip_purpose: + if (*activep && *intptr == -1) { + *intptr = -2; + verbose("%.200s line %d: option is set to don`t check certificate purpose.", + filename, linenum); + } + } + break; + + case oMandatoryCRL: + intptr = &options->x509flags->mandatory_crl; + goto parse_flag; + + case oCACertificateFile: + /*X509StoreOptions preffered type is 'const char*' */ + charptr = (char**)&options->ca.certificate_file; + goto parse_string; + + case oCACertificatePath: + /*X509StoreOptions preffered type is 'const char*' */ + charptr = (char**)&options->ca.certificate_path; + goto parse_string; + + case oCARevocationFile: + /*X509StoreOptions preffered type is 'const char*' */ + charptr = (char**)&options->ca.revocation_file; + goto parse_string; + + case oCARevocationPath: + /*X509StoreOptions preffered type is 'const char*' */ + charptr = (char**)&options->ca.revocation_path; + goto parse_string; + + case oUserCACertificateFile: + /*X509StoreOptions preffered type is 'const char*' */ + charptr = (char**)&options->userca.certificate_file; + goto parse_string; + + case oUserCACertificatePath: + /*X509StoreOptions preffered type is 'const char*' */ + charptr = (char**)&options->userca.certificate_path; + goto parse_string; + + case oUserCARevocationFile: + /*X509StoreOptions preffered type is 'const char*' */ + charptr = (char**)&options->userca.revocation_file; + goto parse_string; + + case oUserCARevocationPath: + /*X509StoreOptions preffered type is 'const char*' */ + charptr = (char**)&options->userca.revocation_path; + goto parse_string; + +#ifdef USE_OPENSSL_STORE2 + case oCAStoreURI: + arg = argv_next(&ac, &av); + if (arg == NULL || *arg == '\0') { + error("%s line %d: %s missing argument.", + filename, linenum, keyword); + goto out; + } + opt_array_append(filename, linenum, "CAStoreURI", + (char***)&options->store_uri, &options->num_store_uri, + arg); + break; +#endif /*def USE_OPENSSL_STORE2*/ + +#ifdef LDAP_ENABLED + case oCAldapVersion: + charptr = (char**)&options->ca_ldap_ver; + goto parse_string; + case oCAldapURL: + charptr = (char**)&options->ca_ldap_url; + goto parse_string; +#endif /*def LDAP_ENABLED*/ + +#ifdef SSH_OCSP_ENABLED + case oVAType: + intptr = &options->va.type; + arg = argv_next(&ac, &av); + if (arg == NULL || *arg == '\0') { + error("%s line %d: %s missing argument.", + filename, linenum, keyword); + goto out; + } + + value = ssh_get_vatype_s(arg); + if (value < 0) { + error("%.200s line %d: Bad OCSP responder type '%.30s'.", + filename, linenum, arg); + goto out; + } + + if (*activep && *intptr == -1) + *intptr = value; + break; + + case oVACertificateFile: + /* VAOptions preffered type is 'const char*' */ + charptr = (char**)&options->va.certificate_file; + goto parse_string; + + case oVAOCSPResponderURL: + /* VAOptions preffered type is 'const char*' */ + charptr = (char**)&options->va.responder_url; + goto parse_string; +#endif /*def SSH_OCSP_ENABLED*/ + /* Other Standard Options */ case oConnectTimeout: intptr = &options->connection_timeout; parse_time: arg = argv_next(&ac, &av); - if (!arg || *arg == '\0') { + if (arg == NULL || *arg == '\0') { error("%s line %d: missing time value.", filename, linenum); goto out; } if (strcmp(arg, "none") == 0) value = -1; - else if ((value = convtime(arg)) == -1) { - error("%s line %d: invalid time value.", - filename, linenum); - goto out; + else { + value = parse_time(arg, filename, linenum); + if (value == -1) goto out; } if (*activep && *intptr == -1) *intptr = value; @@ -1121,20 +1312,8 @@ intptr = &options->forward_agent; arg = argv_next(&ac, &av); - if (!arg || *arg == '\0') { - error("%s line %d: missing argument.", - filename, linenum); - goto out; - } - - value = -1; - multistate_ptr = multistate_flag; - for (i = 0; multistate_ptr[i].key != NULL; i++) { - if (strcasecmp(arg, multistate_ptr[i].key) == 0) { - value = multistate_ptr[i].value; - break; - } - } + value = parse_multistate_value(arg, multistate_flag, + filename, linenum, keyword); if (value != -1) { if (*activep && *intptr == -1) *intptr = value; @@ -1153,8 +1332,9 @@ multistate_ptr = multistate_flag; parse_multistate: arg = argv_next(&ac, &av); - if ((value = parse_multistate_value(arg, filename, linenum, - multistate_ptr)) == -1) { + value = parse_multistate_value(arg, multistate_ptr, + filename, linenum, keyword); + if (value == -1) { error("%s line %d: unsupported option \"%s\".", filename, linenum, arg); goto out; @@ -1192,9 +1372,8 @@ goto parse_string; case oPubkeyAuthentication: - multistate_ptr = multistate_pubkey_auth; intptr = &options->pubkey_authentication; - goto parse_multistate; + goto parse_flag; case oHostbasedAuthentication: intptr = &options->hostbased_authentication; @@ -1228,8 +1407,7 @@ case oCompression: intptr = &options->compression; - multistate_ptr = multistate_compression; - goto parse_multistate; + goto parse_flag; case oTCPKeepAlive: intptr = &options->tcp_keep_alive; @@ -1245,9 +1423,9 @@ case oRekeyLimit: arg = argv_next(&ac, &av); - if (!arg || *arg == '\0') { - error("%.200s line %d: Missing argument.", filename, - linenum); + if (arg == NULL || *arg == '\0') { + error("%s line %d: %s missing argument.", + filename, linenum, keyword); goto out; } if (strcmp(arg, "default") == 0) { @@ -1266,7 +1444,7 @@ } if (*activep && options->rekey_limit == -1) options->rekey_limit = val64; - if (ac != 0) { /* optional rekey interval present */ + if (ac > 0) { /* optional rekey interval present */ if (strcmp(av[0], "none") == 0) { (void)argv_next(&ac, &av); /* discard */ break; @@ -1278,9 +1456,9 @@ case oIdentityFile: arg = argv_next(&ac, &av); - if (!arg || *arg == '\0') { - error("%.200s line %d: Missing argument.", - filename, linenum); + if (arg == NULL || *arg == '\0') { + error("%s line %d: %s missing argument.", + filename, linenum, keyword); goto out; } if (*activep) { @@ -1298,9 +1476,9 @@ case oCertificateFile: arg = argv_next(&ac, &av); - if (!arg || *arg == '\0') { - error("%.200s line %d: Missing argument.", - filename, linenum); + if (arg == NULL || *arg == '\0') { + error("%s line %d: %s missing argument.", + filename, linenum, keyword); goto out; } if (*activep) { @@ -1325,9 +1503,9 @@ charptr = &options->user; parse_string: arg = argv_next(&ac, &av); - if (!arg || *arg == '\0') { - error("%.200s line %d: Missing argument.", - filename, linenum); + if (arg == NULL || *arg == '\0') { + error("%s line %d: %s missing argument.", + filename, linenum, keyword); goto out; } if (*activep && *charptr == NULL) @@ -1339,8 +1517,8 @@ uintptr = &options->num_system_hostfiles; max_entries = SSH_MAX_HOSTS_FILES; parse_char_array: + found = *uintptr > 0; i = 0; - value = *uintptr == 0; /* was array empty when we started? */ while ((arg = argv_next(&ac, &av)) != NULL) { if (*arg == '\0') { error("%s line %d: keyword %s empty argument", @@ -1357,10 +1535,10 @@ } } i++; - if (*activep && value) { + if (*activep && !found) { if ((*uintptr) >= max_entries) { error("%s line %d: too many %s " - "entries.", filename, linenum, + "entries", filename, linenum, keyword); goto out; } @@ -1403,9 +1581,11 @@ charptr = &options->pkcs11_provider; goto parse_string; +#ifdef ENABLE_SK case oSecurityKeyProvider: charptr = &options->sk_provider; goto parse_string; +#endif case oKnownHostsCommand: charptr = &options->known_hosts_command; @@ -1417,11 +1597,6 @@ if (options->jump_host != NULL) charptr = &options->jump_host; /* Skip below */ parse_command: - if (str == NULL) { - error("%.200s line %d: Missing argument.", - filename, linenum); - goto out; - } len = strspn(str, WHITESPACE "="); if (*activep && *charptr == NULL) *charptr = xstrdup(str + len); @@ -1429,13 +1604,7 @@ break; case oProxyJump: - if (str == NULL) { - error("%.200s line %d: Missing argument.", - filename, linenum); - goto out; - } len = strspn(str, WHITESPACE "="); - /* XXX use argv? */ if (parse_jump(str + len, options, *activep) == -1) { error("%.200s line %d: Invalid ProxyJump \"%s\"", filename, linenum, str + len); @@ -1446,9 +1615,9 @@ case oPort: arg = argv_next(&ac, &av); - if (!arg || *arg == '\0') { - error("%.200s line %d: Missing argument.", - filename, linenum); + if (arg == NULL || *arg == '\0') { + error("%s line %d: %s missing argument.", + filename, linenum, keyword); goto out; } value = a2port(arg); @@ -1476,9 +1645,9 @@ case oCiphers: arg = argv_next(&ac, &av); - if (!arg || *arg == '\0') { - error("%.200s line %d: Missing argument.", - filename, linenum); + if (arg == NULL || *arg == '\0') { + error("%s line %d: %s missing argument.", + filename, linenum, keyword); goto out; } if (*arg != '-' && @@ -1493,9 +1662,9 @@ case oMacs: arg = argv_next(&ac, &av); - if (!arg || *arg == '\0') { - error("%.200s line %d: Missing argument.", - filename, linenum); + if (arg == NULL || *arg == '\0') { + error("%s line %d: %s missing argument.", + filename, linenum, keyword); goto out; } if (*arg != '-' && @@ -1510,9 +1679,9 @@ case oKexAlgorithms: arg = argv_next(&ac, &av); - if (!arg || *arg == '\0') { - error("%.200s line %d: Missing argument.", - filename, linenum); + if (arg == NULL || *arg == '\0') { + error("%s line %d: %s missing argument.", + filename, linenum, keyword); goto out; } if (*arg != '-' && @@ -1528,14 +1697,15 @@ case oHostKeyAlgorithms: charptr = &options->hostkeyalgorithms; - ca_only = 0; -parse_pubkey_algos: +parse_key_algorithms: arg = argv_next(&ac, &av); - if (!arg || *arg == '\0') { - error("%.200s line %d: Missing argument.", - filename, linenum); + if (arg == NULL || *arg == '\0') { + error("%s line %d: %s missing argument.", + filename, linenum, keyword); goto out; } + /* cannot validate here - depend from X509KeyAlgorithm */ + if (ca_only) { if (*arg != '-' && !sshkey_names_valid2(*arg == '+' || *arg == '^' ? arg + 1 : arg, 1, ca_only)) { @@ -1543,6 +1713,7 @@ filename, linenum, arg ? arg : ""); goto out; } + } if (*activep && *charptr == NULL) *charptr = xstrdup(arg); break; @@ -1550,7 +1721,7 @@ case oCASignatureAlgorithms: charptr = &options->ca_sign_algorithms; ca_only = 1; - goto parse_pubkey_algos; + goto parse_key_algorithms; case oLogLevel: log_level_ptr = &options->log_level; @@ -1579,8 +1750,7 @@ break; case oLogVerbose: - cppptr = &options->log_verbose; - uintptr = &options->num_log_verbose; + found = options->num_log_verbose > 0; i = 0; while ((arg = argv_next(&ac, &av)) != NULL) { if (*arg == '\0') { @@ -1598,11 +1768,11 @@ } } i++; - if (*activep && *uintptr == 0) { - *cppptr = xrecallocarray(*cppptr, *uintptr, - *uintptr + 1, sizeof(**cppptr)); - (*cppptr)[(*uintptr)++] = xstrdup(arg); - } + if (!*activep || found) + continue; + opt_array_append(filename, linenum, + lookup_opcode_name(opcode), + &options->log_verbose, &options->num_log_verbose, arg); } break; @@ -1610,9 +1780,9 @@ case oRemoteForward: case oDynamicForward: arg = argv_next(&ac, &av); - if (!arg || *arg == '\0') { - error("%.200s line %d: Missing argument.", - filename, linenum); + if (arg == NULL || *arg == '\0') { + error("%s line %d: %s missing argument.", + filename, linenum, keyword); goto out; } @@ -1650,19 +1820,32 @@ } else { add_local_forward(options, &fwd); } + } else { + free(fwd.connect_host); + fwd.connect_host = NULL; + free(fwd.connect_path); + fwd.connect_path = NULL; + free(fwd.listen_host); + fwd.listen_host = NULL; + free(fwd.listen_path); + fwd.listen_path = NULL; } break; - case oPermitRemoteOpen: + case oPermitRemoteOpen: { uintptr = &options->num_permitted_remote_opens; cppptr = &options->permitted_remote_opens; - uvalue = *uintptr; /* modified later */ + found = *uintptr > 0; i = 0; while ((arg = argv_next(&ac, &av)) != NULL) { + if (*arg == '\0') { + error("%s line %d: keyword %s empty argument", + filename, linenum, keyword); + goto out; + } arg2 = xstrdup(arg); /* Allow any/none only in first position */ - if (strcasecmp(arg, "none") == 0 || - strcasecmp(arg, "any") == 0) { + if (strcmp(arg, "any") == 0 || strcmp(arg, "none") == 0) { if (i > 0 || ac > 0) { error("%s line %d: keyword %s \"%s\" " "argument must appear alone.", @@ -1671,36 +1854,38 @@ goto out; } } else { - p = hpdelim(&arg); + { char *p = hpdelim(&arg); if (p == NULL) { - fatal("%s line %d: missing host in %s", + error("%s line %d: missing host in %s", filename, linenum, lookup_opcode_name(opcode)); + free(arg2); + goto out; } p = cleanhostname(p); + } /* * don't want to use permitopen_port to avoid * dependency on channels.[ch] here. */ - if (arg == NULL || (strcmp(arg, "*") != 0 && - a2port(arg) <= 0)) { - fatal("%s line %d: bad port number " - "in %s", filename, linenum, + if (arg == NULL || + (strcmp(arg, "*") != 0 && a2port(arg) <= 0)) { + error("%s line %d: bad port number in %s", + filename, linenum, lookup_opcode_name(opcode)); + free(arg2); + goto out; } } - if (*activep && uvalue == 0) { + i++; + if (*activep && !found) { opt_array_append(filename, linenum, lookup_opcode_name(opcode), cppptr, uintptr, arg2); } free(arg2); - i++; } - if (i == 0) - fatal("%s line %d: missing %s specification", - filename, linenum, lookup_opcode_name(opcode)); - break; + } break; case oClearAllForwardings: intptr = &options->clear_forwardings; @@ -1766,7 +1951,6 @@ * If match_cfg_line() didn't consume all its arguments then * arrange for the extra arguments check below to fail. */ - if (str == NULL || *str == '\0') argv_consume(&ac); break; @@ -1774,9 +1958,9 @@ case oEscapeChar: intptr = &options->escape_char; arg = argv_next(&ac, &av); - if (!arg || *arg == '\0') { - error("%.200s line %d: Missing argument.", - filename, linenum); + if (arg == NULL || *arg == '\0') { + error("%s line %d: %s missing argument.", + filename, linenum, keyword); goto out; } if (strcmp(arg, "none") == 0) @@ -1818,18 +2002,18 @@ case oSendEnv: while ((arg = argv_next(&ac, &av)) != NULL) { - if (*arg == '\0' || strchr(arg, '=') != NULL) { + if (*arg == '\0') { + error("%s line %d: keyword %s empty argument", + filename, linenum, keyword); + goto out; + } + if (strchr(arg, '=') != NULL) { error("%s line %d: Invalid environment name.", filename, linenum); goto out; } if (!*activep) continue; - if (*arg == '-') { - /* Removing an env var */ - rm_env(options, arg, filename, linenum); - continue; - } opt_array_append(filename, linenum, lookup_opcode_name(opcode), &options->send_env, &options->num_send_env, arg); @@ -1837,14 +2021,18 @@ break; case oSetEnv: - value = options->num_setenv; while ((arg = argv_next(&ac, &av)) != NULL) { + if (*arg == '\0') { + error("%s line %d: keyword %s empty argument", + filename, linenum, keyword); + goto out; + } if (strchr(arg, '=') == NULL) { - error("%s line %d: Invalid SetEnv.", + error("%s line %d: Invalid environment name.", filename, linenum); goto out; } - if (!*activep || value != 0) + if (!*activep) continue; if (lookup_setenv_in_list(arg, options->setenv, options->num_setenv) != NULL) { @@ -1871,23 +2059,13 @@ /* no/false/yes/true, or a time spec */ intptr = &options->control_persist; arg = argv_next(&ac, &av); - if (!arg || *arg == '\0') { - error("%.200s line %d: Missing ControlPersist" - " argument.", filename, linenum); - goto out; - } - value = 0; + value = parse_multistate_value(arg, multistate_flag, + filename, linenum, keyword); value2 = 0; /* timeout */ - if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0) - value = 0; - else if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0) - value = 1; - else if ((value2 = convtime(arg)) >= 0) + if (value == -1) { value = 1; - else { - error("%.200s line %d: Bad ControlPersist argument.", - filename, linenum); - goto out; + value2 = parse_time(arg, filename, linenum); + if (value2 == -1) goto out; } if (*activep && *intptr == -1) { *intptr = value; @@ -1906,9 +2084,9 @@ case oTunnelDevice: arg = argv_next(&ac, &av); - if (!arg || *arg == '\0') { - error("%.200s line %d: Missing argument.", - filename, linenum); + if (arg == NULL || *arg == '\0') { + error("%s line %d: %s missing argument.", + filename, linenum, keyword); goto out; } value = a2tun(arg, &value2); @@ -2063,7 +2241,7 @@ goto parse_flag; case oCanonicalDomains: - value = options->num_canonical_domains != 0; + found = options->num_canonical_domains > 0; i = 0; while ((arg = argv_next(&ac, &av)) != NULL) { if (*arg == '\0') { @@ -2086,7 +2264,7 @@ errstr); goto out; } - if (!*activep || value) + if (!*activep || found) continue; if (options->num_canonical_domains >= MAX_CANON_DOMAINS) { @@ -2100,9 +2278,14 @@ break; case oCanonicalizePermittedCNAMEs: - value = options->num_permitted_cnames != 0; + found = options->num_permitted_cnames > 0; i = 0; while ((arg = argv_next(&ac, &av)) != NULL) { + if (*arg == '\0') { + error("%s line %d: keyword %s empty argument", + filename, linenum, keyword); + goto out; + } /* * Either 'none' (only in first position), '*' for * everything or 'list:list' @@ -2130,7 +2313,7 @@ arg2++; } i++; - if (!*activep || value) + if (!*activep || found) continue; if (options->num_permitted_cnames >= MAX_CANON_DOMAINS) { @@ -2160,7 +2343,7 @@ case oStreamLocalBindMask: arg = argv_next(&ac, &av); - if (!arg || *arg == '\0') { + if (arg == NULL || *arg == '\0') { error("%.200s line %d: Missing StreamLocalBindMask " "argument.", filename, linenum); goto out; @@ -2185,9 +2368,9 @@ case oFingerprintHash: intptr = &options->fingerprint_hash; arg = argv_next(&ac, &av); - if (!arg || *arg == '\0') { - error("%.200s line %d: Missing argument.", - filename, linenum); + if (arg == NULL || *arg == '\0') { + error("%s line %d: %s missing argument.", + filename, linenum, keyword); goto out; } if ((value = ssh_digest_alg_by_name(arg)) == -1) { @@ -2204,35 +2387,19 @@ multistate_ptr = multistate_yesnoask; goto parse_multistate; - case oHostbasedAcceptedAlgorithms: - charptr = &options->hostbased_accepted_algos; - ca_only = 0; - goto parse_pubkey_algos; - - case oPubkeyAcceptedAlgorithms: - charptr = &options->pubkey_accepted_algos; - ca_only = 0; - goto parse_pubkey_algos; - case oAddKeysToAgent: arg = argv_next(&ac, &av); arg2 = argv_next(&ac, &av); - value = parse_multistate_value(arg, filename, linenum, - multistate_yesnoaskconfirm); + value = parse_multistate_value(arg, multistate_yesnoaskconfirm, + filename, linenum, keyword); value2 = 0; /* unlimited lifespan by default */ if (value == 3 && arg2 != NULL) { /* allow "AddKeysToAgent confirm 5m" */ - if ((value2 = convtime(arg2)) == -1) { - error("%s line %d: invalid time value.", - filename, linenum); - goto out; - } + value2 = parse_time(arg2, filename, linenum); + if (value2 == -1) goto out; } else if (value == -1 && arg2 == NULL) { - if ((value2 = convtime(arg)) == -1) { - error("%s line %d: unsupported option", - filename, linenum); - goto out; - } + value2 = parse_time(arg, filename, linenum); + if (value2 == -1) goto out; value = 1; /* yes */ } else if (value == -1 || arg2 != NULL) { error("%s line %d: unsupported option", @@ -2248,9 +2415,9 @@ case oIdentityAgent: charptr = &options->identity_agent; arg = argv_next(&ac, &av); - if (!arg || *arg == '\0') { - error("%.200s line %d: Missing argument.", - filename, linenum); + if (arg == NULL || *arg == '\0') { + error("%s line %d: %s missing argument.", + filename, linenum, keyword); goto out; } parse_agent_path: @@ -2286,6 +2453,21 @@ argv_consume(&ac); break; +#ifndef USE_OPENSSL_STORE2 + case oCAStoreURI: +#endif +#ifndef LDAP_ENABLED + case oCAldapVersion: + case oCAldapURL: +#endif /*ndef LDAP_ENABLED*/ +#ifndef SSH_OCSP_ENABLED + case oVAType: + case oVACertificateFile: + case oVAOCSPResponderURL: +#endif /*ndef SSH_OCSP_ENABLED*/ +#ifndef ENABLE_SK + case oSecurityKeyProvider: +#endif case oUnsupported: error("%s line %d: Unsupported option \"%s\"", filename, linenum, keyword); @@ -2300,7 +2482,7 @@ /* Check that there is no garbage at end of line. */ if (ac > 0) { - error("%.200s line %d: keyword %s extra arguments " + error("%s line %d: keyword %s extra arguments " "at end of line", filename, linenum, keyword); goto out; } @@ -2347,13 +2529,10 @@ return 0; if (flags & SSHCONF_CHECKPERM) { - struct stat sb; - - if (fstat(fileno(f), &sb) == -1) - fatal("fstat %s: %s", filename, strerror(errno)); - if (((sb.st_uid != 0 && sb.st_uid != getuid()) || - (sb.st_mode & 022) != 0)) - fatal("Bad owner or permissions on %s", filename); + char errmsg[1024]; + if (safe_usr_fileno(fileno(f), filename, + errmsg, sizeof(errmsg)) == -1) + fatal("%s", errmsg); } debug("Reading configuration data %.200s", filename); @@ -2364,15 +2543,14 @@ */ linenum = 0; while (getline(&line, &linesize, f) != -1) { + /* strip whitespace, preserve newlines, they are needed + * to reproduce line numbers later for error messages + */ + char *cp = line + strspn(line, " \t\r"); /* Update line number counter. */ linenum++; - /* - * Trim out comments and strip whitespace. - * NB - preserve newlines, they are needed to reproduce - * line numbers later for error messages. - */ if (process_config_line_depth(options, pw, host, original_host, - line, filename, linenum, activep, flags, want_final_pass, + cp, filename, linenum, activep, flags, want_final_pass, depth) != 0) bad_options++; } @@ -2416,6 +2594,29 @@ initialize_options(Options * options) { memset(options, 'X', sizeof(*options)); + /* X.509 Standard Options */ + options->hostbased_algorithms = NULL; + options->pubkey_algorithms = NULL; + /* Supported X.509 key algorithms and signatures + are defined is external source. */ + options->x509flags = &ssh_x509flags; + ssh_x509flags_initialize(options->x509flags, 0); + X509StoreOptions_init(&options->ca); + X509StoreOptions_init(&options->userca); +#ifdef LDAP_ENABLED + options->ca_ldap_url = NULL; + options->ca_ldap_ver = NULL; +#endif +#ifdef USE_OPENSSL_STORE2 + options->num_store_uri = 0; + options->store_uri = NULL; +#endif +#ifdef SSH_OCSP_ENABLED + options->va.type = -1; + options->va.certificate_file = NULL; + options->va.responder_url = NULL; +#endif /*def SSH_OCSP_ENABLED*/ + /* Standard Options */ options->host_arg = NULL; options->forward_agent = -1; options->forward_agent_sock_path = NULL; @@ -2453,9 +2654,7 @@ options->hostkeyalgorithms = NULL; options->ca_sign_algorithms = NULL; options->num_identity_files = 0; - memset(options->identity_keys, 0, sizeof(options->identity_keys)); options->num_certificate_files = 0; - memset(options->certificates, 0, sizeof(options->certificates)); options->hostname = NULL; options->host_key_alias = NULL; options->proxy_command = NULL; @@ -2525,14 +2724,19 @@ options->revoked_host_keys = NULL; options->fingerprint_hash = -1; options->update_hostkeys = -1; - options->hostbased_accepted_algos = NULL; - options->pubkey_accepted_algos = NULL; options->known_hosts_command = NULL; options->required_rsa_size = -1; options->enable_escape_commandline = -1; options->tag = NULL; } +void +cleanup_options(Options *options) { + ssh_x509store_cleanup(); + X509StoreOptions_cleanup(&options->userca); + X509StoreOptions_cleanup(&options->ca); +} + /* * A petite version of fill_default_options() that just fills the options * needed for hostname canonicalization to proceed. @@ -2555,9 +2759,7 @@ int fill_default_options(Options * options) { - char *all_cipher, *all_mac, *all_kex, *all_key, *all_sig; - char *def_cipher, *def_mac, *def_kex, *def_key, *def_sig; - int ret = 0, r; + int r; if (options->forward_agent == -1) options->forward_agent = 0; @@ -2589,7 +2791,7 @@ if (options->fwd_opts.streamlocal_bind_unlink == -1) options->fwd_opts.streamlocal_bind_unlink = 0; if (options->pubkey_authentication == -1) - options->pubkey_authentication = SSH_PUBKEY_AUTH_ALL; + options->pubkey_authentication = 1; if (options->gss_authentication == -1) options->gss_authentication = 0; if (options->gss_deleg_creds == -1) @@ -2611,7 +2813,7 @@ if (options->tcp_keep_alive == -1) options->tcp_keep_alive = 1; if (options->port == -1) - options->port = 0; /* Filled in ssh_connect. */ + options->port = 0; /* filled in ssh client */ if (options->address_family == -1) options->address_family = AF_UNSPEC; if (options->connection_attempts == -1) @@ -2619,6 +2821,7 @@ if (options->number_of_password_prompts == -1) options->number_of_password_prompts = 3; /* options->hostkeyalgorithms, default set in myproposals.h */ + /* HostKeyAlgorithms depend from X509KeyAlgorithm options */ if (options->add_keys_to_agent == -1) { options->add_keys_to_agent = 0; options->add_keys_to_agent_lifespan = 0; @@ -2627,15 +2830,13 @@ add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_RSA, 0); #ifdef OPENSSL_HAS_ECC add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_ECDSA, 0); - add_identity_file(options, "~/", - _PATH_SSH_CLIENT_ID_ECDSA_SK, 0); #endif add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_ED25519, 0); - add_identity_file(options, "~/", - _PATH_SSH_CLIENT_ID_ED25519_SK, 0); - add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_XMSS, 0); add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_DSA, 0); +#ifdef WITH_XMSS + add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_XMSS, 0); +#endif } if (options->escape_char == -1) options->escape_char = '~'; @@ -2645,15 +2846,6 @@ options->system_hostfiles[options->num_system_hostfiles++] = xstrdup(_PATH_SSH_SYSTEM_HOSTFILE2); } - if (options->update_hostkeys == -1) { - if (options->verify_host_key_dns <= 0 && - (options->num_user_hostfiles == 0 || - (options->num_user_hostfiles == 1 && strcmp(options-> - user_hostfiles[0], _PATH_SSH_USER_HOSTFILE) == 0))) - options->update_hostkeys = SSH_UPDATE_HOSTKEYS_YES; - else - options->update_hostkeys = SSH_UPDATE_HOSTKEYS_NO; - } if (options->num_user_hostfiles == 0) { options->user_hostfiles[options->num_user_hostfiles++] = xstrdup(_PATH_SSH_USER_HOSTFILE); @@ -2720,45 +2912,56 @@ options->canonicalize_hostname = SSH_CANONICALISE_NO; if (options->fingerprint_hash == -1) options->fingerprint_hash = SSH_FP_HASH_DEFAULT; -#ifdef ENABLE_SK_INTERNAL - if (options->sk_provider == NULL) - options->sk_provider = xstrdup("internal"); -#else + if (options->update_hostkeys == -1) + options->update_hostkeys = 0; if (options->sk_provider == NULL) options->sk_provider = xstrdup("$SSH_SK_PROVIDER"); -#endif if (options->required_rsa_size == -1) - options->required_rsa_size = SSH_RSA_MINIMUM_MODULUS_SIZE; + /* get default */ + options->required_rsa_size = required_rsa_size; + else { + /* transfer */ + if (options->required_rsa_size < required_rsa_size) { + error("RSA key size %d is less then minimum %d.", + options->required_rsa_size, required_rsa_size); + return -1; + } + required_rsa_size = options->required_rsa_size; + } if (options->enable_escape_commandline == -1) +#ifndef HAVE_PLEDGE + options->enable_escape_commandline = 1; +#else options->enable_escape_commandline = 0; +#endif - /* Expand KEX name lists */ - all_cipher = cipher_alg_list(',', 0); - all_mac = mac_alg_list(','); - all_kex = kex_alg_list(','); - all_key = sshkey_alg_list(0, 0, 1, ','); - all_sig = sshkey_alg_list(0, 1, 1, ','); - /* remove unsupported algos from default lists */ - def_cipher = match_filter_allowlist(KEX_CLIENT_ENCRYPT, all_cipher); - def_mac = match_filter_allowlist(KEX_CLIENT_MAC, all_mac); - def_kex = match_filter_allowlist(KEX_CLIENT_KEX, all_kex); - def_key = match_filter_allowlist(KEX_DEFAULT_PK_ALG, all_key); - def_sig = match_filter_allowlist(SSH_ALLOWED_CA_SIGALGS, all_sig); + /* expand KEX and etc. name lists */ +{ char *all; #define ASSEMBLE(what, defaults, all) \ do { \ - if ((r = kex_assemble_names(&options->what, \ - defaults, all)) != 0) { \ + char *def = match_filter_allowlist(defaults, all); \ + r = kex_assemble_names(&options->what, def, all); \ + free(def); \ + free(all); \ + if (r != 0) { \ error_fr(r, "%s", #what); \ - goto fail; \ + return -1; \ } \ } while (0) - ASSEMBLE(ciphers, def_cipher, all_cipher); - ASSEMBLE(macs, def_mac, all_mac); - ASSEMBLE(kex_algorithms, def_kex, all_kex); - ASSEMBLE(hostbased_accepted_algos, def_key, all_key); - ASSEMBLE(pubkey_accepted_algos, def_key, all_key); - ASSEMBLE(ca_sign_algorithms, def_sig, all_sig); + + all = cipher_alg_list(',', 0); + ASSEMBLE(ciphers, KEX_CLIENT_ENCRYPT, all); + + all = mac_alg_list(','); + ASSEMBLE(macs, KEX_CLIENT_MAC, all); + + all = kex_alg_list(','); + ASSEMBLE(kex_algorithms, KEX_CLIENT_KEX, all); + + all = sshkey_alg_list(0, 1, 1, ','); + ASSEMBLE(ca_sign_algorithms, SSH_ALLOWED_CA_SIGALGS, all); #undef ASSEMBLE +} #define CLEAR_ON_NONE(v) \ do { \ @@ -2796,102 +2999,57 @@ /* options->host_key_alias should not be set by default */ /* options->preferred_authentications will be set in ssh */ - /* success */ - ret = 0; - fail: - free(all_cipher); - free(all_mac); - free(all_kex); - free(all_key); - free(all_sig); - free(def_cipher); - free(def_mac); - free(def_kex); - free(def_key); - free(def_sig); - return ret; -} + /* options->hostbased_algorithms */ + /* options->pubkey_algorithms */ + fill_default_xkalg(); + ssh_x509flags_defaults(options->x509flags); + X509StoreOptions_system_defaults(&options->ca); + X509StoreOptions_user_defaults(&options->userca, getuid()); + + (void)ssh_x509store_addlocations(&options->userca); + (void)ssh_x509store_addlocations(&options->ca); +#ifdef LDAP_ENABLED + (void)ssh_x509store_addldapurl(options->ca_ldap_url, options->ca_ldap_ver); +#endif +#ifdef USE_OPENSSL_STORE2 + (void)ssh_x509store_adduri(options->store_uri, options->num_store_uri); +#endif +#ifdef SSH_OCSP_ENABLED + if (options->va.type == -1) + options->va.type = ssh_get_default_vatype(); + ssh_set_validator(&options->va); +#endif /*def SSH_OCSP_ENABLED*/ -void -free_options(Options *o) -{ - int i; + if (options->hostkeyalgorithms != NULL) { + char *arg = options->hostkeyalgorithms; + if (*arg != '-' && + !sshkey_names_valid2(*arg == '+' || *arg == '^' ? + arg + 1 : arg, 1, 0)) { + error("Bad protocol 2 hostkey algorithms '%s'.", + options->hostkeyalgorithms); + return -1; + } + } - if (o == NULL) - return; + if (options->hostbased_algorithms != NULL) { + if (!sshkey_names_valid2(options->hostbased_algorithms, 1, 0)) { + error("Bad protocol 2 hostbased key algorithms '%s'.", + options->hostbased_algorithms); + return -1; + } + } else + options->hostbased_algorithms = xstrdup("*"); -#define FREE_ARRAY(type, n, a) \ - do { \ - type _i; \ - for (_i = 0; _i < (n); _i++) \ - free((a)[_i]); \ - } while (0) + if (options->pubkey_algorithms != NULL) { + if (!sshkey_names_valid2(options->pubkey_algorithms, 1, 0)) { + error("Bad protocol 2 public key algorithms '%s'.", + options->pubkey_algorithms); + return -1; + } + } else + options->pubkey_algorithms = xstrdup("*"); - free(o->forward_agent_sock_path); - free(o->xauth_location); - FREE_ARRAY(u_int, o->num_log_verbose, o->log_verbose); - free(o->log_verbose); - free(o->ciphers); - free(o->macs); - free(o->hostkeyalgorithms); - free(o->kex_algorithms); - free(o->ca_sign_algorithms); - free(o->hostname); - free(o->host_key_alias); - free(o->proxy_command); - free(o->user); - FREE_ARRAY(u_int, o->num_system_hostfiles, o->system_hostfiles); - FREE_ARRAY(u_int, o->num_user_hostfiles, o->user_hostfiles); - free(o->preferred_authentications); - free(o->bind_address); - free(o->bind_interface); - free(o->pkcs11_provider); - free(o->sk_provider); - for (i = 0; i < o->num_identity_files; i++) { - free(o->identity_files[i]); - sshkey_free(o->identity_keys[i]); - } - for (i = 0; i < o->num_certificate_files; i++) { - free(o->certificate_files[i]); - sshkey_free(o->certificates[i]); - } - free(o->identity_agent); - for (i = 0; i < o->num_local_forwards; i++) { - free(o->local_forwards[i].listen_host); - free(o->local_forwards[i].listen_path); - free(o->local_forwards[i].connect_host); - free(o->local_forwards[i].connect_path); - } - free(o->local_forwards); - for (i = 0; i < o->num_remote_forwards; i++) { - free(o->remote_forwards[i].listen_host); - free(o->remote_forwards[i].listen_path); - free(o->remote_forwards[i].connect_host); - free(o->remote_forwards[i].connect_path); - } - free(o->remote_forwards); - free(o->stdio_forward_host); - FREE_ARRAY(u_int, o->num_send_env, o->send_env); - free(o->send_env); - FREE_ARRAY(u_int, o->num_setenv, o->setenv); - free(o->setenv); - free(o->control_path); - free(o->local_command); - free(o->remote_command); - FREE_ARRAY(int, o->num_canonical_domains, o->canonical_domains); - for (i = 0; i < o->num_permitted_cnames; i++) { - free(o->permitted_cnames[i].source_list); - free(o->permitted_cnames[i].target_list); - } - free(o->revoked_host_keys); - free(o->hostbased_accepted_algos); - free(o->pubkey_accepted_algos); - free(o->jump_user); - free(o->jump_host); - free(o->jump_extra); - free(o->ignored_unknown); - explicit_bzero(o, sizeof(*o)); -#undef FREE_ARRAY + return 0; } struct fwdarg { @@ -3122,17 +3280,17 @@ active &= o->proxy_command == NULL && o->jump_host == NULL; - orig = sdup = xstrdup(s); - - /* Remove comment and trailing whitespace */ - if ((cp = strchr(orig, '#')) != NULL) - *cp = '\0'; - rtrim(orig); + if (strcasecmp(s, "none") == 0) { + if (active) { + o->jump_host = xstrdup("none"); + o->jump_port = 0; + } + return 0; + } + orig = sdup = xstrdup(s); first = active; do { - if (strcasecmp(s, "none") == 0) - break; if ((cp = strrchr(sdup, ',')) == NULL) cp = sdup; /* last */ else @@ -3155,19 +3313,14 @@ } while (cp != sdup); /* success */ if (active) { - if (strcasecmp(s, "none") == 0) { - o->jump_host = xstrdup("none"); - o->jump_port = 0; - } else { - o->jump_user = user; - o->jump_host = host; - o->jump_port = port; - o->proxy_command = xstrdup("none"); - user = host = NULL; - if ((cp = strrchr(s, ',')) != NULL && cp != s) { - o->jump_extra = xstrdup(s); - o->jump_extra[cp - s] = '\0'; - } + o->jump_user = user; + o->jump_host = host; + o->jump_port = port; + o->proxy_command = xstrdup("none"); + user = host = NULL; + if ((cp = strrchr(s, ',')) != NULL && cp != s) { + o->jump_extra = xstrdup(s); + o->jump_extra[cp - s] = '\0'; } } ret = 0; @@ -3224,6 +3377,10 @@ if (val == -1) return "unset"; switch (code) { +#ifdef SSH_OCSP_ENABLED + case oVAType: + return ssh_get_vatype_i(val); +#endif case oAddressFamily: return fmt_multistate_int(val, multistate_addressfamily); case oVerifyHostKeyDNS: @@ -3243,8 +3400,6 @@ return fmt_multistate_int(val, multistate_canonicalizehostname); case oAddKeysToAgent: return fmt_multistate_int(val, multistate_yesnoaskconfirm); - case oPubkeyAuthentication: - return fmt_multistate_int(val, multistate_pubkey_auth); case oFingerprintHash: return ssh_digest_alg_name(val); default: @@ -3303,10 +3458,14 @@ dump_cfg_strarray_oneline(OpCodes code, u_int count, char **vals) { u_int i; + const char *def = ""; + + if ((int)count < 0) return; - printf("%s", lookup_opcode_name(code)); if (count == 0) - printf(" none"); + def = " none"; + + printf("%s%s", lookup_opcode_name(code), def); for (i = 0; i < count; i++) printf(" %s", vals[i]); printf("\n"); @@ -3353,20 +3512,8 @@ void dump_client_config(Options *o, const char *host) { - int i, r; - char buf[8], *all_key; - - /* - * Expand HostKeyAlgorithms name lists. This isn't handled in - * fill_default_options() like the other algorithm lists because - * the host key algorithms are by default dynamically chosen based - * on the host's keys found in known_hosts. - */ - all_key = sshkey_alg_list(0, 0, 1, ','); - if ((r = kex_assemble_names(&o->hostkeyalgorithms, kex_default_pk_alg(), - all_key)) != 0) - fatal_fr(r, "expand HostKeyAlgorithms"); - free(all_key); + int i; + char buf[8]; /* Most interesting options first: user, host, port */ dump_cfg_string(oHost, o->host_arg); @@ -3374,6 +3521,28 @@ dump_cfg_string(oHostname, host); dump_cfg_int(oPort, o->port); + /* X.509 options */ + dump_cfg_string(oHostbasedAlgorithms, o->hostbased_algorithms); + dump_cfg_string(oPubkeyAlgorithms, o->pubkey_algorithms); + /* TODO to implement dump of sX509KeyAlgorithm */ + /* sshd PKI(X509) flags */ + /* sshd PKI(X509) system store */ + dump_cfg_string(oCACertificateFile, o->ca.certificate_file); + dump_cfg_string(oCACertificatePath, o->ca.certificate_path); + dump_cfg_string(oCARevocationFile , o->ca.revocation_file ); + dump_cfg_string(oCARevocationPath , o->ca.revocation_path ); + /* sshd PKI(X509) user store */ + dump_cfg_string(oUserCACertificateFile, o->userca.certificate_file); + dump_cfg_string(oUserCACertificatePath, o->userca.certificate_path); + dump_cfg_string(oUserCARevocationFile , o->userca.revocation_file ); + dump_cfg_string(oUserCARevocationPath , o->userca.revocation_path ); +#ifdef SSH_OCSP_ENABLED + /* ssh X.509 extra validation */ + dump_cfg_fmtint(oVAType , o->va.type ); + dump_cfg_string(oVACertificateFile , o->va.certificate_file); + dump_cfg_string(oVAOCSPResponderURL, o->va.responder_url ); +#endif /*def SSH_OCSP_ENABLED*/ + /* Flag options */ dump_cfg_fmtint(oAddressFamily, o->address_family); dump_cfg_fmtint(oBatchMode, o->batch_mode); @@ -3431,7 +3600,6 @@ dump_cfg_string(oControlPath, o->control_path); dump_cfg_string(oHostKeyAlgorithms, o->hostkeyalgorithms); dump_cfg_string(oHostKeyAlias, o->host_key_alias); - dump_cfg_string(oHostbasedAcceptedAlgorithms, o->hostbased_accepted_algos); dump_cfg_string(oIdentityAgent, o->identity_agent); dump_cfg_string(oIgnoreUnknown, o->ignored_unknown); dump_cfg_string(oKbdInteractiveDevices, o->kbd_interactive_devices); @@ -3444,9 +3612,10 @@ #ifdef ENABLE_PKCS11 dump_cfg_string(oPKCS11Provider, o->pkcs11_provider); #endif +#ifdef ENABLE_SK dump_cfg_string(oSecurityKeyProvider, o->sk_provider); +#endif dump_cfg_string(oPreferredAuthentications, o->preferred_authentications); - dump_cfg_string(oPubkeyAcceptedAlgorithms, o->pubkey_accepted_algos); dump_cfg_string(oRevokedHostKeys, o->revoked_host_keys); dump_cfg_string(oXAuthLocation, o->xauth_location); dump_cfg_string(oKnownHostsCommand, o->known_hosts_command); diff -ruN openssh-9.4p1/readconf.h openssh-9.4p1+x509-14.2.1/readconf.h --- openssh-9.4p1/readconf.h 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/readconf.h 2023-08-20 10:07:00.000000000 +0300 @@ -1,5 +1,4 @@ /* $OpenBSD: readconf.h,v 1.151 2023/07/17 04:08:31 djm Exp $ */ - /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -11,11 +10,34 @@ * software must be clearly marked as such, and if the derived work is * incompatible with the protocol description in the RFC file, it must be * called by a name other than "ssh" or "Secure Shell". + * + * Copyright (c) 2002-2021 Roumen Petrov. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef READCONF_H #define READCONF_H +#include "x509store.h" /* Data structure for representing option data. */ #define SSH_MAX_HOSTS_FILES 32 @@ -54,8 +76,8 @@ int ip_qos_bulk; /* IP ToS/DSCP/class for bulk traffic */ SyslogFacility log_facility; /* Facility for system logging. */ LogLevel log_level; /* Level for logging. */ - u_int num_log_verbose; /* Verbose log overrides */ - char **log_verbose; + u_int num_log_verbose; /* Verbose log overrides */ + char **log_verbose; int port; /* Port to connect. */ int address_family; int connection_attempts; /* Max attempts (seconds) before @@ -66,7 +88,7 @@ * prompts. */ char *ciphers; /* SSH2 ciphers in order of preference. */ char *macs; /* SSH2 macs in order of preference. */ - char *hostkeyalgorithms; /* SSH2 server key types in order of preference. */ + char *hostkeyalgorithms; /* SSH2 server host-key algorithms in order of preference. */ char *kex_algorithms; /* SSH2 kex methods in order of preference. */ char *ca_sign_algorithms; /* Allowed CA signature algorithms */ char *hostname; /* Real host to connect. */ @@ -138,6 +160,31 @@ int hash_known_hosts; + char* hostbased_algorithms; /* Allowed hostbased algorithms. */ + char* pubkey_algorithms; /* Allowed pubkey algorithms. */ + + /* Supported X.509 key algorithms and signatures + are defined is external source. */ + + /* ssh PKI(X509) flags */ + SSH_X509Flags *x509flags; + /* sshd PKI(X509) system store */ + X509StoreOptions ca; + /* sshd PKI(X509) user store */ + X509StoreOptions userca; +#ifdef LDAP_ENABLED + const char *ca_ldap_url; + const char *ca_ldap_ver; /* outdated */ +#endif +#ifdef USE_OPENSSL_STORE2 + u_int num_store_uri; + const char **store_uri; +#endif +#ifdef SSH_OCSP_ENABLED + /* ssh X.509 extra validation */ + VAOptions va; +#endif /*def SSH_OCSP_ENABLED*/ + int tun_open; /* tun(4) */ int tun_local; /* force tun device (optional) */ int tun_remote; /* force tun device (optional) */ @@ -168,9 +215,6 @@ int update_hostkeys; /* one of SSH_UPDATE_HOSTKEYS_* */ - char *hostbased_accepted_algos; - char *pubkey_accepted_algos; - char *jump_user; char *jump_host; int jump_port; @@ -184,11 +228,6 @@ char *ignored_unknown; /* Pattern list of unknown tokens to ignore */ } Options; -#define SSH_PUBKEY_AUTH_NO 0x00 -#define SSH_PUBKEY_AUTH_UNBOUND 0x01 -#define SSH_PUBKEY_AUTH_HBOUND 0x02 -#define SSH_PUBKEY_AUTH_ALL 0x03 - #define SSH_CANONICALISE_NO 0 #define SSH_CANONICALISE_YES 1 #define SSH_CANONICALISE_ALWAYS 2 @@ -222,13 +261,12 @@ #define SSH_STRICT_HOSTKEY_YES 2 #define SSH_STRICT_HOSTKEY_ASK 3 -const char *kex_default_pk_alg(void); char *ssh_connection_hash(const char *thishost, const char *host, const char *portstr, const char *user); -void initialize_options(Options *); -int fill_default_options(Options *); +void initialize_options(Options *); +void cleanup_options(Options *); +int fill_default_options(Options *); void fill_default_options_for_canonicalization(Options *); -void free_options(Options *o); int process_config_line(Options *, struct passwd *, const char *, const char *, char *, const char *, int, int *, int); int read_config_file(const char *, struct passwd *, const char *, diff -ruN openssh-9.4p1/README openssh-9.4p1+x509-14.2.1/README --- openssh-9.4p1/README 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/README 1970-01-01 02:00:00.000000000 +0200 @@ -1,53 +0,0 @@ -See https://www.openssh.com/releasenotes.html#9.4p1 for the release -notes. - -Please read https://www.openssh.com/report.html for bug reporting -instructions and note that we do not use Github for bug reporting or -patch/pull-request management. - -This is the port of OpenBSD's excellent OpenSSH[0] to Linux and other -Unices. - -OpenSSH is based on the last free version of Tatu Ylonen's sample -implementation with all patent-encumbered algorithms removed (to -external libraries), all known security bugs fixed, new features -reintroduced and many other clean-ups. OpenSSH has been created by -Aaron Campbell, Bob Beck, Markus Friedl, Niels Provos, Theo de Raadt, -and Dug Song. It has a homepage at https://www.openssh.com/ - -This port consists of the re-introduction of autoconf support, PAM -support, EGD/PRNGD support and replacements for OpenBSD library -functions that are (regrettably) absent from other unices. This port -has been best tested on AIX, Cygwin, HP-UX, Linux, MacOS/X, -FreeBSD, NetBSD, OpenBSD, OpenServer, Solaris and UnixWare. - -This version actively tracks changes in the OpenBSD CVS repository. - -The PAM support is now more functional than the popular packages of -commercial ssh-1.2.x. It checks "account" and "session" modules for -all logins, not just when using password authentication. - -There is now several mailing lists for this port of OpenSSH. Please -refer to https://www.openssh.com/list.html for details on how to join. - -Please send bug reports and patches to https://bugzilla.mindrot.org or -the mailing list openssh-unix-dev@mindrot.org. To mitigate spam, the -list only allows posting from subscribed addresses. Code contribution -are welcomed, but please follow the OpenBSD style guidelines[1]. - -Please refer to the INSTALL document for information on dependencies and -how to install OpenSSH on your system. - -Damien Miller - -Miscellania - - -This version of OpenSSH is based upon code retrieved from the OpenBSD CVS -repository which in turn was based on the last free sample implementation -released by Tatu Ylonen. - -References - - -[0] https://www.openssh.com/ -[1] https://man.openbsd.org/style.9 - diff -ruN openssh-9.4p1/README.adoc openssh-9.4p1+x509-14.2.1/README.adoc --- openssh-9.4p1/README.adoc 1970-01-01 02:00:00.000000000 +0200 +++ openssh-9.4p1+x509-14.2.1/README.adoc 2023-08-20 10:07:00.000000000 +0300 @@ -0,0 +1,40 @@ +PKIX-SSH - an advanced secure shell implementation +================================================== + +https://roumenpetrov.info/secsh[Project page] + + +Implementation includes some of functionality provided by OpenSSH. +OpenSSH itself is derivative of the original and free ssh 1.2.12 +release by Tatu Ylonen. Aaron Campbell, Bob Beck, Markus Friedl, +Niels Provos, Theo de Raadt, and Dug Song removed many bugs, +re-added newer features and created OpenSSH. +Roumen Petrov adds X.509 certificate support, modernize use of +cryptography library including FIPS mode and creates PKIX-SSH. + +Project depend of OpenSSL an excellent cryptography library. +Precise autoconf based testings of available functionality +allows PKIX-SSH to work fine not only with current stable releases +but with upcoming versions or other compatible libraries. +Ancient versions are still supported. + +Functional testing ensures portability to many platforms. The list +includes but is not limited to Linux, Android, Solaris, BSD variants +Cygwin, Darwin and AIX. + +Enhanced key management allows use of key material stored not only on +file system, but provided from external sources like PKCS#11 module, +loadable cryptography module (engine) or OpenSSL store interface. +Each key material could be used in all supported algorithms. +For instance each server host-key is announced in all supported and +allowed algorithms. +For a key used as client identity adaptive algorithm selection allows +client to chose automatically most suitable algorithm for connection. + + +Please see INSTALL document for hints how to install PKIX-SSH on you +platform. + +For information how to contribute to project please refer to the +https://roumenpetrov.info/secsh/#support[Support section] +of the project page. diff -ruN openssh-9.4p1/README.dns openssh-9.4p1+x509-14.2.1/README.dns --- openssh-9.4p1/README.dns 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/README.dns 2023-08-20 10:07:00.000000000 +0300 @@ -1,10 +1,12 @@ -How to verify host keys using OpenSSH and DNS +How to verify host keys using PKIX-SSH and DNS --------------------------------------------- -OpenSSH contains support for verifying host keys using DNS as described +PKIX-SSH contains support for verifying host keys using DNS as described in https://tools.ietf.org/html/rfc4255. The document contains very brief instructions on how to use this feature. Configuring DNS is out of the scope of this document. +Note that public host key file may contain X.509 certificate. In this case +is used CERT RR as is described in rfc2538 obsoleted by rfc4398. (1) Server: Generate and publish the DNS RR @@ -26,6 +28,17 @@ To publish the fingerprint using the DNS you must add the generated RR to your DNS zone file and sign your zone. +To create a DNS CERT resource record containing X.509 host key, use the +following command: + + ssh-keygen -r hostname -f keyfile + +In the example above, ssh-keygen will print a standard CERT RR. Key +algorithms are described in rfc2535 obsoleted by rfc4034. If algorithm +is not parsable by name server you should use -g flag and ssh-keygen +will print the CERT RR in a generic format parsable by most modern +name server. + (2) Client: Enable ssh to verify host keys using DNS @@ -35,13 +48,14 @@ VerifyHostKeyDNS yes -Upon connection the client will try to look up the fingerprint RR -using DNS. If the fingerprint received from the DNS server matches +Upon connection the client will try to look up the CERT or SSHFP RR +using DNS. If the CERT or SSHFP received from the DNS server matches the remote host key, the user will be notified. Jakob Schlyter Wesley Griffin + Roumen Petrov $OpenBSD: README.dns,v 1.2 2003/10/14 19:43:23 jakob Exp $ diff -ruN openssh-9.4p1/README.md openssh-9.4p1+x509-14.2.1/README.md --- openssh-9.4p1/README.md 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/README.md 1970-01-01 02:00:00.000000000 +0200 @@ -1,86 +0,0 @@ -# Portable OpenSSH - -[![C/C++ CI](https://github.com/openssh/openssh-portable/actions/workflows/c-cpp.yml/badge.svg)](https://github.com/openssh/openssh-portable/actions/workflows/c-cpp.yml) -[![Fuzzing Status](https://oss-fuzz-build-logs.storage.googleapis.com/badges/openssh.svg)](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:openssh) -[![Coverity Status](https://scan.coverity.com/projects/21341/badge.svg)](https://scan.coverity.com/projects/openssh-portable) - -OpenSSH is a complete implementation of the SSH protocol (version 2) for secure remote login, command execution and file transfer. It includes a client ``ssh`` and server ``sshd``, file transfer utilities ``scp`` and ``sftp`` as well as tools for key generation (``ssh-keygen``), run-time key storage (``ssh-agent``) and a number of supporting programs. - -This is a port of OpenBSD's [OpenSSH](https://openssh.com) to most Unix-like operating systems, including Linux, OS X and Cygwin. Portable OpenSSH polyfills OpenBSD APIs that are not available elsewhere, adds sshd sandboxing for more operating systems and includes support for OS-native authentication and auditing (e.g. using PAM). - -## Documentation - -The official documentation for OpenSSH are the man pages for each tool: - -* [ssh(1)](https://man.openbsd.org/ssh.1) -* [sshd(8)](https://man.openbsd.org/sshd.8) -* [ssh-keygen(1)](https://man.openbsd.org/ssh-keygen.1) -* [ssh-agent(1)](https://man.openbsd.org/ssh-agent.1) -* [scp(1)](https://man.openbsd.org/scp.1) -* [sftp(1)](https://man.openbsd.org/sftp.1) -* [ssh-keyscan(8)](https://man.openbsd.org/ssh-keyscan.8) -* [sftp-server(8)](https://man.openbsd.org/sftp-server.8) - -## Stable Releases - -Stable release tarballs are available from a number of [download mirrors](https://www.openssh.com/portable.html#downloads). We recommend the use of a stable release for most users. Please read the [release notes](https://www.openssh.com/releasenotes.html) for details of recent changes and potential incompatibilities. - -## Building Portable OpenSSH - -### Dependencies - -Portable OpenSSH is built using autoconf and make. It requires a working C compiler, standard library and headers. - -``libcrypto`` from either [LibreSSL](https://www.libressl.org/) or [OpenSSL](https://www.openssl.org) may also be used. OpenSSH may be built without either of these, but the resulting binaries will have only a subset of the cryptographic algorithms normally available. - -[zlib](https://www.zlib.net/) is optional; without it transport compression is not supported. - -FIDO security token support needs [libfido2](https://github.com/Yubico/libfido2) and its dependencies and will be enabled automatically if they are found. - -In addition, certain platforms and build-time options may require additional dependencies; see README.platform for details about your platform. - -### Building a release - -Releases include a pre-built copy of the ``configure`` script and may be built using: - -``` -tar zxvf openssh-X.YpZ.tar.gz -cd openssh -./configure # [options] -make && make tests -``` - -See the [Build-time Customisation](#build-time-customisation) section below for configure options. If you plan on installing OpenSSH to your system, then you will usually want to specify destination paths. - -### Building from git - -If building from git, you'll need [autoconf](https://www.gnu.org/software/autoconf/) installed to build the ``configure`` script. The following commands will check out and build portable OpenSSH from git: - -``` -git clone https://github.com/openssh/openssh-portable # or https://anongit.mindrot.org/openssh.git -cd openssh-portable -autoreconf -./configure -make && make tests -``` - -### Build-time Customisation - -There are many build-time customisation options available. All Autoconf destination path flags (e.g. ``--prefix``) are supported (and are usually required if you want to install OpenSSH). - -For a full list of available flags, run ``./configure --help`` but a few of the more frequently-used ones are described below. Some of these flags will require additional libraries and/or headers be installed. - -Flag | Meaning ---- | --- -``--with-pam`` | Enable [PAM](https://en.wikipedia.org/wiki/Pluggable_authentication_module) support. [OpenPAM](https://www.openpam.org/), [Linux PAM](http://www.linux-pam.org/) and Solaris PAM are supported. -``--with-libedit`` | Enable [libedit](https://www.thrysoee.dk/editline/) support for sftp. -``--with-kerberos5`` | Enable Kerberos/GSSAPI support. Both [Heimdal](https://www.h5l.org/) and [MIT](https://web.mit.edu/kerberos/) Kerberos implementations are supported. -``--with-selinux`` | Enable [SELinux](https://en.wikipedia.org/wiki/Security-Enhanced_Linux) support. - -## Development - -Portable OpenSSH development is discussed on the [openssh-unix-dev mailing list](https://lists.mindrot.org/mailman/listinfo/openssh-unix-dev) ([archive mirror](https://marc.info/?l=openssh-unix-dev)). Bugs and feature requests are tracked on our [Bugzilla](https://bugzilla.mindrot.org/). - -## Reporting bugs - -_Non-security_ bugs may be reported to the developers via [Bugzilla](https://bugzilla.mindrot.org/) or via the mailing list above. Security bugs should be reported to [openssh@openssh.com](mailto:openssh.openssh.com). diff -ruN openssh-9.4p1/README.platform openssh-9.4p1+x509-14.2.1/README.platform --- openssh-9.4p1/README.platform 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/README.platform 2023-08-20 10:07:00.000000000 +0300 @@ -1,6 +1,7 @@ This file contains notes about OpenSSH on specific platforms. AIX +=== Beginning with OpenSSH 3.8p1, sshd will honour an account's password expiry settings, where prior to that it did not. Because of this, @@ -41,14 +42,16 @@ Cygwin ------- +====== + To build on Cygwin, OpenSSH requires the following packages: gcc, gcc-mingw-core, mingw-runtime, binutils, make, openssl, openssl-devel, zlib, minres, minires-devel. Darwin and MacOS X ------------------- +================== + Darwin does not provide a tun(4) driver required for OpenSSH-based virtual private networks. The BSD manpage still exists, but the driver has been removed in recent releases of Darwin and MacOS X. @@ -60,7 +63,7 @@ Linux ------ +===== Some Linux distributions (including Red Hat/Fedora/CentOS) include headers and library links in the -devel RPMs rather than the main @@ -72,7 +75,8 @@ Solaris -------- +======= + If you enable BSM auditing on Solaris, you need to update audit_event(4) for praudit(1m) to give sensible output. The following line needs to be added to /etc/security/audit_event: @@ -87,7 +91,8 @@ Platforms using PAM -------------------- +=================== + As of OpenSSH 4.3p1, sshd will no longer check /etc/nologin itself when PAM is enabled. To maintain existing behaviour, pam_nologin should be added to sshd's session stack which will prevent users from starting shell diff -ruN openssh-9.4p1/README.privsep openssh-9.4p1+x509-14.2.1/README.privsep --- openssh-9.4p1/README.privsep 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/README.privsep 2023-08-20 10:07:00.000000000 +0300 @@ -5,10 +5,13 @@ More information is available at: http://www.citi.umich.edu/u/provos/ssh/privsep.html -Privilege separation is now mandatory. During the pre-authentication -phase sshd will chroot(2) to "/var/empty" and change its privileges to the -"sshd" user and its primary group. sshd is a pseudo-account that should -not be used by other daemons, and must be locked and should contain a +Privilege separation is now enabled by default; see the +UsePrivilegeSeparation option in sshd_config(5). + +When privsep is enabled, during the pre-authentication phase sshd will +chroot(2) to "/var/empty" and change its privileges to the "sshd" user +and its primary group. sshd is a pseudo-account that should not be +used by other daemons, and must be locked and should contain a "nologin" or invalid shell. You should do something like the following to prepare the privsep @@ -28,7 +31,7 @@ --with-privsep-path=xxx Path for privilege separation chroot --with-privsep-user=user Specify non-privileged user for privilege separation -PAM-enabled OpenSSH is known to function with privsep on AIX, FreeBSD, +PAM-enabled OpenSSH is known to function with privsep on AIX, FreeBSD, HP-UX (including Trusted Mode), Linux, NetBSD and Solaris. On Cygwin, Tru64 Unix and OpenServer only the pre-authentication part diff -ruN openssh-9.4p1/README.x509v3 openssh-9.4p1+x509-14.2.1/README.x509v3 --- openssh-9.4p1/README.x509v3 1970-01-01 02:00:00.000000000 +0200 +++ openssh-9.4p1+x509-14.2.1/README.x509v3 2023-08-19 18:29:51.000000000 +0300 @@ -0,0 +1,616 @@ + Roumen Petrov + Sofia, Bulgaria + Wed Feb 8 2023 + +How to use X.509 certificates with SSH? + + +Identity or hostkey file contain private key and may contain X.509 +certificate that match it. Note that key and X.509 certificate has to +be in PEM format. To use X.509 certificate as identity or hostkey user +should convert certificate in PEM format and append to file. After this +with "ssh-keygen -y ..." user must update "pub" file. +File (identity or hostkey) with X.509 certificate (RSA key): +-----BEGIN RSA PRIVATE KEY----- +..... +-----END RSA PRIVATE KEY----- +-----BEGIN CERTIFICATE----- +..... +-----END CERTIFICATE----- +File may contain extra X.509 certificates. Extra certificates along +with certificates from X.509 store are used to build chain of X.509 +certificates leading to a trusted certificate authority if required by +public key algorithm format. Those algorithms are defined in RFC6187. +Supported are x509v3-ecdsa-sha2-*, x509v3-rsa2048-sha256, +x509v3-ssh-rsa and x509v3-ssh-dss. Algorithm x509v3-ssh-ed25519 uses +public key format described in RFC6187 signature format described +in RFC8709. + + +1.) server configuration: + +1.1.) .../sshd_config + +1.1.1.) AllowedCertPurpose sslclient + The intended use of the X.509 client certificate. + +1.1.2.) "X509 store". + Server use "X509 store" to verify and validate client keys. + +1.1.2.1.) CACertificateFile /etc/ssh/ca/ca-bundle.crt + This file contain multiple certificates of certificate signers in PEM +format concatenated together. You can get a copy from openssl, apache, +KDE, mutt, etc. packages. Original file might is exported from Mozilla +certificate database. + +1.1.2.2.) CACertificatePath /etc/ssh/ca/crt + "Hash dir" with certificates of certificate signers. Each certificate +should be stored in separate file with name [HASH].[NUMBER], where +[HASH] is certificate hash value and [NUMBER] is an integer starting +from zero. Hash is result from command like this: +$ openssl x509 -in certificate_file_name -noout -hash + +1.1.2.3.) CARevocationFile /etc/ssh/ca/ca-bundle.crl + This file contain multiple "Certificate Revocation List" (CRL) of +certificate signers in PEM format concatenated together. + +1.1.2.4.) CARevocationPath /etc/ssh/ca/crl + "Hash dir" with "Certificate Revocation List" (CRL) of certificate +signers. Each CRL should be stored in separate file with name +[HASH].r[NUMBER], where [HASH] is CRL hash value and [NUMBER] is an +integer starting from zero. Hash is result from command like this: +$ openssl crl -in crl_file_name -noout -hash + +1.1.2.5.) CAldapVersion + LDAP protocol version. Default depend from LDAP library. + +1.1.2.6.) CAldapURL + Hostport and dn of LDAP URL. No default value. + +1.1.3.) HostKey files... + Host key may contain X.509 certificate concatenated to private key +both in PEM format. + +1.1.4.) X509KeyAlgorithm + The option list multiple "X509 Key Algorithms Formats" + supported by server. + The format and algorithm precedence are described in sshd_config(5). + Note first listed format for RSA or DSA key-type is used as default in + signing. The server will accept all listed formats. + +NOTES: +- versions before 7.1 use rsa-md5 first. Starting from 7.1 rsa-sha1 is + preffered and client and server identify itself as PKIX in comment + section of ssh identification string. +- ECDSA support was added in version 8.0. In version 10.0 implementation + is corrected to conform strictly to RFC 6187 description. +- x509v3-ssh-* support was added in version 10.0. + +1.1.5.) VAType none + Specifies whether 'Online Certificate Status Protocol' (OCSP) is used + to validate client X.509 certificates. Specified value is used only + when SSH is build with OCSP support. See sshd_config(5) man page + for allowed values and other VA* options. + +1.1.6.) KeyAllowSelfIssued no + Specifies whether self-issued X.509 certificate can be allowed only + by entry in AuthorizedKeysFile that contain matching public key or + certificate blob. + +1.2.) user files on the server + Append in USER_HOME/.ssh/authorized_keys a record with following +format: +{|CertBlob} +where: +KEY_TYPE:=x509v3-sign-rsa|x509v3-sign-dss (case sensitive !) +WORDDN:={Distinguished Name| + Distinguished-Name| + Distinguished_Name| + DistinguishedName| + DN| + Subject} +WORDDNSUFF:='='|':'|'' +NOTES: +- WORDDN is case insensitive ! + +- is like output from command: +$ openssl x509 -noout -subject -in A_CERTIFICATE_FILE -nameopt oneline + +- can be in RFC2253 format like output from command: +$ openssl x509 -noout -subject -in A_CERTIFICATE_FILE -nameopt RFC2253 + +IMPORTANT NOTE (if a distinguished name contain non-ascii characters): +- for versions 6.+: + ALWAIS use "openssl x509" command option -nameopt ! + The parser don't and won't support output without -nameopt +- for versions prior 6.0: + The program couldn't parse non-latin subject. Use "blob" format (see below). + +- Order of items in is not important and separator +can be symbol "/", "," or mixed. All following subjects are equal: +a)CN=dsa test certificate,OU=SSH Testers,O=Test Team,ST=World,C=XX +b)/C=XX/ST=World/O=Test Team/OU=SSH Testers/CN=dsa test certificate +c)/O=Test Team/OU=SSH Testers/C=XX/ST=World/CN=dsa test certificate +d)O=Test Team,OU=SSH Testers/C=XX,ST=World/CN=dsa test certificate + +- CertBlob is base64 encoded sequence of bytes in only one line. + +Shell sample: +- "Distinguished Name" format (rsa key): +$ ( printf 'x509v3-sign-rsa '; + openssl x509 -noout -subject \ + -in A_SSH_IDENTITY_FILE \ + -nameopt oneline \ + ) >> $HOME/.ssh/authorized_keys + +- "blob" format: +$ cat A_SSH_IDENTITY_FILE.pub \ + >> $HOME/.ssh/authorized_keys + +NOTES: +- adjust user authorized_keys file ownership - user must have at least +read access. + +- When SSH is build with "--disable-x509store" YOU CANNOT USE +"Distinguished Name" format. You should use ONLY "blob" format. + Option "--disable-x509store" was removed in PKIX-SSH version 9.0. + + +2.) client settings: + +2.1.) IdentityFile + Depends from client. To use X.509 certificate "SSH id-file" must +contain both sections - private key and certificate in PEM format: +Note: Don't forget to update public key file with command: +$ ssh-keygen -y -f IDENTITY_FILE > IDENTITY_FILE.pub +Command ssh-add use public key file! + +2.2.) global ssh_config, $HOME/.ssh/config or command line + +2.2.1.) AllowedCertPurpose sslserver + The intended use of the X.509 server certificate. + +2.2.2.) "X509 store". + Client use "X509 store" to verify and validate server hostkey. + See p. 1.1.2.) and check the options: +- [User]CACertificatePath; +- [User]CACertificateFile; +- [User]CARevocationFile; +- [User]CARevocationPath; +- [User]CAldapVersion; +- [User]CAldapURL. + +Note: When we use own CA we must import CA certificate[s] to +"X509 store". More info on: + https://roumenpetrov.info/domino_CA/#dca2bundle + +2.2.3.) X509KeyAlgorithm + The meaning of options is same as in server. + See p. 1.1.4.) + +2.2.4.) VAType none + Specifies whether `Online Certificate Status Protocol' (OCSP) is used + to validate server X.509 certificates. Specified value is used only + when SSH is build with OCSP support. See ssh_config(5) man page + for allowed values and other VA* options. + + +3.) test X.509 certificates. + +3.1.) In SSH build dir run "make check" or "make tests". + Both commands are equivalent and run regression tests. + If you want to test only X.509 certificates you can run +$ make check-certs + + If certificate test scripts fail might you should setup test +configuration in the file SSH_SOURCE_PATH/tests/CA/config or +use some environment variables. Used variables are described +later in the document. + + Output from "make check-certs" is in color and when is redirected to +file later we can see content best with command "less -r ...". + When script run a test command print star '*' followed by simple +information about command. When command succeed script print at right +"done" in GREEN(!) otherwise "failed" in RED(!). After failed command +script show on next lines in RED(!) response, skip execution of next +command/script, print message like this: +.... +Testing client and server with X.509 certificates finished. + status: failed +.... + Note that failed is in RED(!) and exit code is NONZERO(!). + Some command in a test script must fail. Part of "simple information" +about command expected to fail is in RED(!). When command fail script +print "done" (THIS IS CORRECT - COMMAND MUST FAIL) and on next lines +print in GREEN(!) response. Usually this occur when server reject logon. +WHEN ALL TESTS SUCCEED output is: +.... +Testing client and server with X.509 certificates finished. + status: done +.... + Note that "done" is in GREEN(!) and exit code is ZERO(!). + +3.1.1.) Description of variables in Makefile file: + - SHELL + Used shell to run tests. Supported shell are bash, ksh, zsh and ash. + Test scripts runs on standard unix sh. + Example: + $ make check-certs SHELL=/bin/zsh + + See below how to specify shell at configure time. This is preffered + setup instead to override shell. + +3.1.2.) Description of variables in config file: + +3.1.2.1.) main variables: + - SUDO + (environment or config) by default is not set. + on some system sshd must be started as root. + If necessary configure sudo'ers first and then set variable to sudo + for test pusposed. + - TMPDIR + (environment or config) + directory for temporary files. If not set its value is selected + from /tmp, /var/tmp or /usr/tmp. + - SSH_X509TESTS + (environment or config) + list with test scripts. A test script is in file with following + name: test-.sh.inc. + - OPENSSL_FIPS + (environment) + applicable for build with FIPS capable OpenSSL + see notes below + +3.1.2.2.) openssl: + - OPENSSL + (environment or config) + path to openssl binary. The default is result from command: + `which openssl`. + - RSA_DIGEST_LIST + (environment or config) + list with RSA digests in support of openssl. The default value is + build at run time from following digest list "sha1 md5 mdc2 md4 + rmd160" and contain only supported by openssl. + +3.1.2.3.) server section: + Read sshd_config.5 manual page for valid values. + - SSHD_PORT + (environment or config) + Specifies the port number that server listens on and client connect + to on SSHD_LISTENADDRESS. The default is 20022. + - SSHD_LISTENADDRESS + (only in config) + Same as sshd option "ListenAddress" but without(!) port number. + The default is "127.0.0.1". + - SSHSERVER_USEPRIVILEGESEPARATION="yes": + (only in config) + sshd "UsePrivilegeSeparation" option. + if necessary set to "no", to disable privilege separation. + - SSHSERVER_SYSLOGFACILITY=AUTH + (only in config) + sshd "SyslogFacility" option. + - SSHSERVER_LOGLEVEL=INFO + (only in config) + sshd 'LogLevel' option. + +3.1.2.4.) certificates: + - Variables related to test certificates and CA. + (only in config) + +3.1.2.5.) OCSP responder: + Used only when SSH is build with OCSP support! + Variables related to OCSP tests. + - SSH_VA_BASEPORT + (environment or config) + Test script run one or more OCSP responders at same once. First + responder listen on specified port, second on port plus one and + etc. The default is 20080. + - SSH_OPENSSL_OCSP_TMOUT=60 + (config) + Wait specified number of seconds sockets opened by OCSP responders + to close. After this test script continue with next step. + This is work around for missing SO_REUSEADDR socket option in + OpenSSL OCSP responder. + +3.1.2.5.) LDAP: + In use only when SSH is build with LDAP support! + - SSH_LDAP_DB + (config) + Specifies LDAP database type. The default is ldbm. + - SSH_LDAP_DC + (config) + Specifies domain name component in LDAP distinguished name. + The default is "dc=example,dc=com". + - LDAPD_PORT + (environment or config) + LDAP daemon run by test script run listens on SSHD_LISTENADDRESS + and this port. The default is 20389. + +3.1.2.6.) Key&Certificate from "devices": + Starting from version 7.0 of X.509 certificate support in ssh client + you could use X.509 certificates and respective key stored in + external devices. Access is based on OpenSSL engine. + +3.1.2.6.1.) OpenSSL NSS engine (cryptographic module) + Next sample show how to use client with "OpenSSL NSS engine" + ( https://roumenpetrov.info/e_nss/ ). + + First lets list certificates: +$ openssl engine e_nss -t -post LIST_CERTS:1 +....E_NSS:CMD_LIST_CERT:DB is not initialized:e_nss_cmd.c:77: + + Above failure show that engine is not properly configured. + + You should find NSS db directory and to configure. For instance: + $HOME/.mozilla/firefox/.default + $HOME/.mozilla/seamonkey/.default + , where is created when you create profile + for Mozillas application. + In case of doubt where is located NSS database just run +$ find $HOME/.mozilla -name cert8.db + + Next samples will use "test/nssdb" as path to NSS database. + +$ openssl engine e_nss -t \ + -post CONFIG_DIR:test/nssdb \ + -post LIST_CERTS:1 +(e_nss) NSS engine support (0.2.1) + [ available ] +[Success]: CONFIG_DIR:test/nssdb +nickname='SSH DSA test certificate(rsa_sha1) - SSH Te......... + subject_name='E=email@not.set,CN=SSH DSA test certific.......... + email_addr ='email@not.set' +nickname='SSH RSA test certificate(rsa_sha1) - SSH Te......... + subject_name='E=email@not.set,CN=SSH RSA test certific.......... + email_addr ='email@not.set' +[Success]: LIST_CERTS:1 + + Next setup ssh_engine: +$ cat ssh_engine +Engine e_nss + CONFIG_DIR test/nssdb + The SSH configuration match above openssl test command. + Ref. to manual page ssh_engine(5) for details. + + Lets assume that ssh server is setup to accept you certificate. +$ ssh -E ssh_engine \ + -i engine:e_nss:"\"SSH RSA test certificate(rsa_sha1) -....\"" \ + .... + where dots replace part of actual nickname, -E specify engine + configuration file instead default one, -i specify IdentityFile in + format engine:[ENGNAME]:[KEY_SEARCH_CRITERIA] + Note quote of nickname is it contain space characters + +3.1.2.7.) FIPS capable openssl: + Starting from version 7.1 of X.509 certificate support all programs + initialize openssl in FIPS mode if environment variable OPENSSL_FIPS + is set. + Note that you could run X.509 certificate tests in FIPS mode but + you must ensure that test certificates are created in fips mode. + So first go to $(top_builddir)/tests/CA and run "make clean". + Then return to top build directory and run the tests again. + OPENSSL_FIPS=1 make check-certs .... + + +3.1.3.) Sample commands to run tests: +$ OPENSSL=/usr/local/ssl/bin/openssl make check-certs +$ SSHD_PORT=1122 SSH_X509TESTS="agent blob_auth" make check-certs +$ RSA_DIGEST_LIST="sha1 md5" make check-certs +$ make check-certs SHELL=/bin/ksh + +When check fail see "Troubleshooting" later in document. + +Note: starting from version 7.0 of X.509 certificate support test use +shell specified during configuration by CONFIG_SHELL=..., i.e. +$ CONFIG_SHELL=/bin/ksh .../configure ... +$ ... +$ make check-certs + +3.2.) Current test scripts uses only rsa as server hostkey. + To test sshd with X.509 certificate please find in file +ssh_tests.sh variable TEST_SSHD_HOSTKEY and change it. Sample: +TEST_SSH_HOSTKEY="$CWD/testhostkey_rsa-rsa_sha1" + + +3.3.) Test SecSH from "Microsoft Windows OS-es". + This is not part of document. +Tips: use created after "make check-certs" files: +- convert SSH_BUILD_PATH/tests/CA/ca-test/crt/*crt.pem CA + certificates from PEM to DER format and import in + "Windows keystore"; +- import SSH_BUILD_PATH/tests/CA/testid_*.p12 files in + "Windows keystore"; +- setup your client to use certificate[s](see SecSH client manuals). +DON'T FORGET TO REMOVE entries from "Windows keystore" after test! + + +3.4.) Go to SSH_BUILD_PATH/tests/CA and run command "make clean" to +remove all client/server and CA files. + + +3.5.) files in SSH_SOURCE_PATH/tests/CA directory: +config: + Configuration file. + +env.in: + Template file. + Currently contain variables related to LDAP directories. + +shell.rc: + Shell settings. + +1-cre_cadb.sh: + Create "Test CA" directories and files. + +2-cre_key.sh + Create ssh keys. Use test configuration, i.e. + run ssh-keygen in FIPS mode if requested. + +2-cre_cakeys.sh: + Create "Test CA" private keys and certificates. + +3-cre_certs.sh: + Create client/server certificates. + This command create files with mask + "PATH_TO_KEYFILEn-[.]" + , where is in format "rsa_" or "dsa". + DIGEST are form variable "RSA_DIGEST_LIST" specified in "config" + file. Files without suffix are SSH identity or hostkey files. + File with .pub suffix contain SSH public key (BLOB format). + File with .crt suffix contain OpenSSL "text output" for identity + files. Files with .p12 suffix are for "Microsoft Windows keystore". + Note: .p12 = .pfx for Windows. + +4-cre_crls.sh: + Revoke part of client certificates. + +5-cre_ldap.sh + Create LDAP ldif files and slapd config. + +verify.sh: + To check certificates against "Test CA". Note: check only + testid_*.crt and testhostkey_*.crt files in current directory. + +functions: + Common useful functions. + +ssh_tests.sh: + Main test script - call other testscripts. + +test-blob_auth.sh.inc, +test-dn_auth_file.sh.inc, +test-dn_auth_path.sh.inc, +test-agent.sh.inc, +test-crl.sh.inc, +test-self.sh.inc, +test-alg.sh.inc, +test-hostalg.sh.inc, +test-algfmt.sh.inc, +test-store_file.sh.inc, +test-ocsp.sh.inc, +test-by_ldap.sh.inc: + Test shell scripts listed in execution order. + See DESCRIPTION in each file. + +Note that hostbased authentication we cannot test without to install. +Generated testhostkey_* certificates are with sslserver and sslclient +purposes and you can use them to test manually hostbased authentication. + + +4.) Troubleshooting +"make check-certs" fails on: + +4.1.) "generating a new ... private key for the TEST CA ..." +Usually this happen on system without /dev/{u}random. +In file [BUILDDIR]/tests/CA/ca-2.log we can see a message: +"... PRNG not seeded ...". +Read again WARNING.RNG from SSH sourcedir and/or +https://www.openssl.org/support/faq.html + +4.1.1.) reconfigure your system and/or openssl +4.1.2.) or do next +4.1.2.1.) install SSH :-( otherwise later "make check-certs" +(ssh-keygen) fail with message: +"couldn't exec '.../libexec/ssh-rand-helper': ..." +and second ./ssh-rand-helper fail with message: +"couldn't read entropy commands file ../ssh_prng_cmds: ..." +Tip: configure SSH with prefix for example $HOME/test + +4.1.2.2.) run: +ssh-rand-helper +rm -f $HOME/.rnd +ln -s .ssh/prng_seed $HOME/.rnd +Note: Support for ssh-rand-helper was removed in 2011. + +4.1.2.3.) test openssl with command: +/usr/local/ssl/bin/openssl genrsa -des3 -passout pass:change_it +Tip: before to create every key with OpenSSL run ssh-rand-helper ! + +4.1.2.4.) run again "... make check-certs ..." + +4.2.) fail on first check: "* rsa_sha1 valid blob failed" +- Usually SUDO command is not set. See p. 3.1.2.1. +- When you build with tcpwrappers your hosts.allow must permit +connections from localhost, otherwise you can see in failed message +text like this: "... connection closed by remote host ..." + +4.3.) fail on "starting OCSP responder(XXX) on YYY:NNNNN failed" +- Ensure sequence of about six free ports and use SSH_VA_BASEPORT + to specify first of them. +- Ensure enough timeout previous running OCSP responders to free + ports. Increase value of SSH_OPENSSL_OCSP_TMOUT in test config file. + + +5.) FAQ + +Q.) How to convert a certificate from DER to PEM format? +A.) Run command "openssl x509 ..." with command line options +-inform/-outform - you can select one of formats: DER, NET or PEM. +The default is PEM. + +Q.) How to convert pfx to p12 file? +A.) Just change file extension ;-). + +Q.) How to use my p12 file in SSH as identity? +A.) Run commands: +$ openssl pkcs12 -in FILE.p12 -clcerts > id_x509 +$ ssh-keygen -f id_x509 -y > id_x509.pub + Don't forget to set properly permition on file id_x509, as +example "chmod 600 id_x509". + Note name of identity file can be one of defaults: + 'id_rsa', 'id_dsa' or 'id_ecdsa'. + Configure client. + +Q.) How to use p12 file in SSH as hostkey? +A.) Note that host keys are password less! + It is similar to client identity. + Remember umask settings. + Run as root commands: +# umask 0077 +# openssl pkcs12 -in FILE.p12 -clcerts > ssh_host_x509 + Note: you must enter export password! +# ssh-keygen -p -f ssh_host_x509 -N '' + Now hostkey file is password less ! +# ssh-keygen -f ssh_host_x509 -y > ssh_host_x509.pub + Restore umask settings. + Note name of hostkey file can be one of defaults: + 'ssh_host_rsa_key', 'ssh_host_dsa_key' or 'ssh_host_ecdsa_key'. + Configure server, test configuration with command +# sshd -t ..../sshd_config + and start/restart the server. Don't forget to inform users + that hostkey is changed! + +Q.) How to import CA certificates and/or CRLs in LDAP? +A.) You should create a ldif file with LDAP entries that contains + binary attributes "cACertificate" and/or "certificateRevocationList" + and to specify path to file with certificate or CRL in DER format. + Entry should contain objectClass "pkiCA". See definition in core + LDAP schema. After this to use command ldapadd or ldapmodify to + add/modify LDAP data. See command manual pages. + + As example when you build SSH with ldap queries after + regression test see content of file + $(top_builddir)/tests/CA/ldap/ca.ldif . + This file is created by the script + $(srcdir)/tests/CA/5-cre_ldap.sh + and entries are added to LDAP with command: +$ ldapadd -x -w secret -D cn=... -H ldap://... \ + -f .../ca.ldif . + See ldapadd manual page for options meaning. + +Q.) How to build with FIPS capable OpenSSL ? +A.) At configure time you must set environment variables: + CC : openssl fips compiler - fipsld + FIPSLD_CC : actual compiler to be used by openssl fips compiler + + Sample command: +$ CC=gcc FIPSLD_CC=fipsld .../configure ... + + Next verify configure script output: +.... + Actual compiler: gcc + Compiler: FIPSLD_CC=$(FIPSLD_CC) fipsld +.... + + +Enjoy ;-) diff -ruN openssh-9.4p1/readpass.c openssh-9.4p1+x509-14.2.1/readpass.c --- openssh-9.4p1/readpass.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/readpass.c 2023-08-20 10:07:01.000000000 +0300 @@ -1,6 +1,7 @@ -/* $OpenBSD: readpass.c,v 1.70 2022/05/27 04:27:49 dtucker Exp $ */ +/* $OpenBSD: readpass.c,v 1.69 2021/07/23 05:56:47 djm Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. + * Copyright (c) 2019-2020 Roumen Petrov. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -45,10 +46,9 @@ #include "pathnames.h" #include "log.h" #include "ssh.h" -#include "uidswap.h" static char * -ssh_askpass(char *askpass, const char *msg, const char *env_hint) +ssh_askpass(const char *askpass, const char *msg, const char *env_hint) { pid_t pid, ret; size_t len; @@ -122,14 +122,18 @@ char * read_passphrase(const char *prompt, int flags) { - char cr = '\r', *askpass = NULL, *ret, buf[1024]; - int rppflags, ttyfd, use_askpass = 0, allow_askpass = 0; - const char *askpass_hint = NULL; + char *ret; + int rppflags, use_askpass = 0, allow_askpass; const char *s; - if ((s = getenv("DISPLAY")) != NULL) - allow_askpass = *s != '\0'; - if ((s = getenv(SSH_ASKPASS_REQUIRE_ENV)) != NULL) { +#ifdef __ANDROID__ + allow_askpass = 1; +#else + s = getenv("DISPLAY"); + allow_askpass = (s != NULL) && (*s != '\0'); +#endif + s = getenv(SSH_ASKPASS_REQUIRE_ENV); + if (s != NULL) { if (strcasecmp(s, "force") == 0) { use_askpass = 1; allow_askpass = 1; @@ -150,16 +154,17 @@ use_askpass = 1; } } else { + int ttyfd; rppflags |= RPP_REQUIRE_TTY; ttyfd = open(_PATH_TTY, O_RDWR); - if (ttyfd >= 0) { + if (ttyfd != -1) { /* * If we're on a tty, ensure that show the prompt at * the beginning of the line. This will hopefully * clobber any password characters the user has * optimistically typed before echo is disabled. */ - (void)write(ttyfd, &cr, 1); + (void)write(ttyfd, "\r", 1); close(ttyfd); } else { debug_f("can't open %s: %s", _PATH_TTY, @@ -168,14 +173,17 @@ } } +#if 0 /* pointless in context of environment managed askpass */ if ((flags & RP_USE_ASKPASS) && !allow_askpass) return (flags & RP_ALLOW_EOF) ? NULL : xstrdup(""); +#endif if (use_askpass && allow_askpass) { - if (getenv(SSH_ASKPASS_ENV)) - askpass = getenv(SSH_ASKPASS_ENV); - else - askpass = _PATH_SSH_ASKPASS_DEFAULT; + const char *askpass = getenv(SSH_ASKPASS_ENV); + const char *askpass_hint = NULL; + + if (askpass == NULL || *askpass == '\0') + askpass = _PATH_SSH_ASKPASS; if ((flags & RP_ASK_PERMISSION) != 0) askpass_hint = "confirm"; if ((ret = ssh_askpass(askpass, prompt, askpass_hint)) == NULL) @@ -184,6 +192,7 @@ return ret; } +{ char buf[1024]; if (readpassphrase(prompt, buf, sizeof buf, rppflags) == NULL) { if (flags & RP_ALLOW_EOF) return NULL; @@ -192,6 +201,7 @@ ret = xstrdup(buf); explicit_bzero(buf, sizeof(buf)); +} return ret; } @@ -221,112 +231,3 @@ return (allowed); } - -static void -writemsg(const char *msg) -{ - (void)write(STDERR_FILENO, "\r", 1); - (void)write(STDERR_FILENO, msg, strlen(msg)); - (void)write(STDERR_FILENO, "\r\n", 2); -} - -struct notifier_ctx { - pid_t pid; - void (*osigchld)(int); -}; - -struct notifier_ctx * -notify_start(int force_askpass, const char *fmt, ...) -{ - va_list args; - char *prompt = NULL; - pid_t pid = -1; - void (*osigchld)(int) = NULL; - const char *askpass, *s; - struct notifier_ctx *ret = NULL; - - va_start(args, fmt); - xvasprintf(&prompt, fmt, args); - va_end(args); - - if (fflush(NULL) != 0) - error_f("fflush: %s", strerror(errno)); - if (!force_askpass && isatty(STDERR_FILENO)) { - writemsg(prompt); - goto out_ctx; - } - if ((askpass = getenv("SSH_ASKPASS")) == NULL) - askpass = _PATH_SSH_ASKPASS_DEFAULT; - if (*askpass == '\0') { - debug3_f("cannot notify: no askpass"); - goto out; - } - if (getenv("DISPLAY") == NULL && - ((s = getenv(SSH_ASKPASS_REQUIRE_ENV)) == NULL || - strcmp(s, "force") != 0)) { - debug3_f("cannot notify: no display"); - goto out; - } - osigchld = ssh_signal(SIGCHLD, SIG_DFL); - if ((pid = fork()) == -1) { - error_f("fork: %s", strerror(errno)); - ssh_signal(SIGCHLD, osigchld); - free(prompt); - return NULL; - } - if (pid == 0) { - if (stdfd_devnull(1, 1, 0) == -1) - fatal_f("stdfd_devnull failed"); - closefrom(STDERR_FILENO + 1); - setenv("SSH_ASKPASS_PROMPT", "none", 1); /* hint to UI */ - execlp(askpass, askpass, prompt, (char *)NULL); - error_f("exec(%s): %s", askpass, strerror(errno)); - _exit(1); - /* NOTREACHED */ - } - out_ctx: - if ((ret = calloc(1, sizeof(*ret))) == NULL) { - if (pid != -1) - kill(pid, SIGTERM); - fatal_f("calloc failed"); - } - ret->pid = pid; - ret->osigchld = osigchld; - out: - free(prompt); - return ret; -} - -void -notify_complete(struct notifier_ctx *ctx, const char *fmt, ...) -{ - int ret; - char *msg = NULL; - va_list args; - - if (ctx != NULL && fmt != NULL && ctx->pid == -1) { - /* - * notify_start wrote to stderr, so send conclusion message - * there too - */ - va_start(args, fmt); - xvasprintf(&msg, fmt, args); - va_end(args); - writemsg(msg); - free(msg); - } - - if (ctx == NULL || ctx->pid <= 0) { - free(ctx); - return; - } - kill(ctx->pid, SIGTERM); - while ((ret = waitpid(ctx->pid, NULL, 0)) == -1) { - if (errno != EINTR) - break; - } - if (ret == -1) - fatal_f("waitpid: %s", strerror(errno)); - ssh_signal(SIGCHLD, ctx->osigchld); - free(ctx); -} diff -ruN openssh-9.4p1/regress/addrmatch.sh openssh-9.4p1+x509-14.2.1/regress/addrmatch.sh --- openssh-9.4p1/regress/addrmatch.sh 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/addrmatch.sh 2023-08-20 10:07:00.000000000 +0300 @@ -53,7 +53,7 @@ fi # -# Check that we catch invalid address/mask in Match Address/Localaddress +# Check that we catch invalid address/mask in Match Address/LocalAddress # for i in 10.0.1.0/8 10.0.0.1/24 2000:aa:bb:01::/56; do for a in address localaddress; do diff -ruN openssh-9.4p1/regress/agent-getpeereid.sh openssh-9.4p1+x509-14.2.1/regress/agent-getpeereid.sh --- openssh-9.4p1/regress/agent-getpeereid.sh 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/agent-getpeereid.sh 2023-08-20 10:07:00.000000000 +0300 @@ -1,4 +1,3 @@ -# $OpenBSD: agent-getpeereid.sh,v 1.15 2023/02/08 08:06:03 dtucker Exp $ # $OpenBSD: agent-getpeereid.sh,v 1.13 2021/09/01 00:50:27 dtucker Exp $ # Placed in the Public Domain. @@ -13,7 +12,7 @@ if config_defined HAVE_GETPEEREID HAVE_GETPEERUCRED HAVE_SO_PEERCRED ; then : else - skip "skipped (not supported on this platform)" + skip "not supported on this platform" fi if test "x$USER" = "xroot"; then skip "skipped (running as root)" @@ -28,24 +27,24 @@ esac trace "start agent" -eval `${SSHAGENT} ${EXTRA_AGENT_ARGS} -s -a ${ASOCK}` >$OBJ/ssh-agent.log 2>&1 +eval `$SSHAGENT $EXTRA_AGENT_ARGS -s -a $ASOCK` >$OBJ/ssh-agent.log 2>&1 r=$? if [ $r -ne 0 ]; then fail "could not start ssh-agent: exit code $r" else chmod 644 ${SSH_AUTH_SOCK} - ${SSHADD} -vvv -l >>$OBJ/ssh-add.log 2>&1 + $SSHADD -vvv -l >>$OBJ/ssh-add.log 2>&1 r=$? if [ $r -ne 1 ]; then fail "ssh-add failed with $r != 1" fi if test -z "$sudo" ; then # doas - ${SUDO} -n -u ${UNPRIV} ${SSHADD} -l 2>/dev/null + $SUDO -n -u $UNPRIV $SSHADD -l >>$OBJ/ssh-add.log 2>&1 else # sudo - < /dev/null ${SUDO} -S -u ${UNPRIV} ${SSHADD} -vvv -l >>$OBJ/ssh-add.log 2>&1 + < /dev/null $SUDO -S -u $UNPRIV $SSHADD -vvv -l >>$OBJ/ssh-add.log 2>&1 fi r=$? if [ $r -lt 2 ]; then @@ -54,7 +53,7 @@ fi trace "kill agent" - ${SSHAGENT} -k >>$OBJ/ssh-agent.log 2>&1 + $SSHAGENT -k >>$OBJ/ssh-agent.log 2>&1 fi rm -f ${OBJ}/agent diff -ruN openssh-9.4p1/regress/agent-pkcs11.sh openssh-9.4p1+x509-14.2.1/regress/agent-pkcs11.sh --- openssh-9.4p1/regress/agent-pkcs11.sh 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/agent-pkcs11.sh 2023-08-20 10:07:00.000000000 +0300 @@ -1,53 +1,16 @@ -# $OpenBSD: agent-pkcs11.sh,v 1.9 2021/07/25 12:13:03 dtucker Exp $ +# $OpenBSD: agent-pkcs11.sh,v 1.8 2021/05/24 10:25:18 dtucker Exp $ # Placed in the Public Domain. tid="pkcs11 agent test" -try_token_libs() { - for _lib in "$@" ; do - if test -f "$_lib" ; then - verbose "Using token library $_lib" - TEST_SSH_PKCS11="$_lib" - return - fi - done - echo "skipped: Unable to find PKCS#11 token library" - exit 0 -} - -try_token_libs \ - /usr/local/lib/softhsm/libsofthsm2.so \ - /usr/lib64/pkcs11/libsofthsm2.so \ - /usr/lib/x86_64-linux-gnu/softhsm/libsofthsm2.so - -TEST_SSH_PIN=1234 -TEST_SSH_SOPIN=12345678 -if [ "x$TEST_SSH_SSHPKCS11HELPER" != "x" ]; then - SSH_PKCS11_HELPER="${TEST_SSH_SSHPKCS11HELPER}" - export SSH_PKCS11_HELPER -fi +TEST_SSH_PIN="" +TEST_SSH_PKCS11=/usr/local/lib/soft-pkcs11.so.0.0 test -f "$TEST_SSH_PKCS11" || fatal "$TEST_SSH_PKCS11 does not exist" -# setup environment for softhsm2 token -DIR=$OBJ/SOFTHSM -rm -rf $DIR -TOKEN=$DIR/tokendir -mkdir -p $TOKEN -SOFTHSM2_CONF=$DIR/softhsm2.conf -export SOFTHSM2_CONF -cat > $SOFTHSM2_CONF << EOF -# SoftHSM v2 configuration file -directories.tokendir = ${TOKEN} -objectstore.backend = file -# ERROR, WARNING, INFO, DEBUG -log.level = DEBUG -# If CKF_REMOVABLE_DEVICE flag should be set -slots.removable = false -EOF -out=$(softhsm2-util --init-token --free --label token-slot-0 --pin "$TEST_SSH_PIN" --so-pin "$TEST_SSH_SOPIN") -slot=$(echo -- $out | sed 's/.* //') - +# setup environment for soft-pkcs11 token +SOFTPKCS11RC=$OBJ/pkcs11.info +export SOFTPKCS11RC # prevent ssh-agent from calling ssh-askpass SSH_ASKPASS=/usr/bin/true export SSH_ASKPASS @@ -56,30 +19,25 @@ # start command w/o tty, so ssh-add accepts pin from stdin notty() { perl -e 'use POSIX; POSIX::setsid(); - if (fork) { wait; exit($? >> 8); } else { exec(@ARGV) }' "$@" + if (fork) { wait; exit($? >> 8); } else { exec(@ARGV) }' ${1+"$@"} } -trace "generating keys" -RSA=${DIR}/RSA -EC=${DIR}/EC -$OPENSSL_BIN genpkey -algorithm rsa > $RSA -$OPENSSL_BIN pkcs8 -nocrypt -in $RSA |\ - softhsm2-util --slot "$slot" --label 01 --id 01 --pin "$TEST_SSH_PIN" --import /dev/stdin -$OPENSSL_BIN genpkey \ - -genparam \ - -algorithm ec \ - -pkeyopt ec_paramgen_curve:prime256v1 |\ - $OPENSSL_BIN genpkey \ - -paramfile /dev/stdin > $EC -$OPENSSL_BIN pkcs8 -nocrypt -in $EC |\ - softhsm2-util --slot "$slot" --label 02 --id 02 --pin "$TEST_SSH_PIN" --import /dev/stdin - trace "start agent" eval `${SSHAGENT} ${EXTRA_AGENT_ARGS} -s` > /dev/null r=$? if [ $r -ne 0 ]; then fail "could not start ssh-agent: exit code $r" else + trace "generating key/cert" + rm -f $OBJ/pkcs11.key $OBJ/pkcs11.crt + $OPENSSL genrsa -out $OBJ/pkcs11.key 2048 > /dev/null 2>&1 + chmod 600 $OBJ/pkcs11.key + $OPENSSL req -key $OBJ/pkcs11.key -new -x509 \ + -out $OBJ/pkcs11.crt -text -subj '/CN=pkcs11 test' > /dev/null + printf "a\ta\t$OBJ/pkcs11.crt\t$OBJ/pkcs11.key" > $SOFTPKCS11RC + # add to authorized keys + ${SSHKEYGEN} -y -f $OBJ/pkcs11.key > $OBJ/authorized_keys_$USER + trace "add pkcs11 key to agent" echo ${TEST_SSH_PIN} | notty ${SSHADD} -s ${TEST_SSH_PKCS11} > /dev/null 2>&1 r=$? @@ -94,23 +52,12 @@ fail "ssh-add -l failed: exit code $r" fi - for k in $RSA $EC; do - trace "testing $k" - chmod 600 $k - ssh-keygen -y -f $k > $k.pub - pub=$(cat $k.pub) - ${SSHADD} -L | grep -q "$pub" || fail "key $k missing in ssh-add -L" - ${SSHADD} -T $k.pub || fail "ssh-add -T with $k failed" - - # add to authorized keys - cat $k.pub > $OBJ/authorized_keys_$USER - trace "pkcs11 connect via agent ($k)" - ${SSH} -F $OBJ/ssh_proxy somehost exit 5 - r=$? - if [ $r -ne 5 ]; then - fail "ssh connect failed (exit code $r)" - fi - done + trace "pkcs11 connect via agent" + ${SSH} -F $OBJ/ssh_proxy somehost exit 5 + r=$? + if [ $r -ne 5 ]; then + fail "ssh connect failed (exit code $r)" + fi trace "remove pkcs11 keys" echo ${TEST_SSH_PIN} | notty ${SSHADD} -e ${TEST_SSH_PKCS11} > /dev/null 2>&1 diff -ruN openssh-9.4p1/regress/agent-ptrace.sh openssh-9.4p1+x509-14.2.1/regress/agent-ptrace.sh --- openssh-9.4p1/regress/agent-ptrace.sh 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/agent-ptrace.sh 2023-08-20 10:07:00.000000000 +0300 @@ -1,4 +1,4 @@ -# $OpenBSD: agent-ptrace.sh,v 1.5 2022/04/22 05:08:43 anton Exp $ +# $OpenBSD: agent-ptrace.sh,v 1.3 2015/09/11 04:55:01 djm Exp $ # Placed in the Public Domain. tid="disallow agent ptrace attach" @@ -6,34 +6,29 @@ if have_prog uname ; then case `uname` in AIX|CYGWIN*|OSF1) - echo "skipped (not supported on this platform)" - exit 0 + skip "not supported on this platform" ;; esac fi if [ "x$USER" = "xroot" ]; then - echo "Skipped: running as root" - exit 0 + skip "running as root" fi if have_prog gdb ; then : ok else - echo "skipped (gdb not found)" - exit 0 + skip "gdb not found" fi if $OBJ/setuid-allowed ${SSHAGENT} ; then : ok else - echo "skipped (${SSHAGENT} is mounted on a no-setuid filesystem)" - exit 0 + skip "$SSHAGENT is mounted on a no-setuid filesystem" fi if test -z "$SUDO" ; then - echo "skipped (SUDO not set)" - exit 0 + skip "SUDO not set" else $SUDO chown 0 ${SSHAGENT} $SUDO chgrp 0 ${SSHAGENT} diff -ruN openssh-9.4p1/regress/agent-restrict.sh openssh-9.4p1+x509-14.2.1/regress/agent-restrict.sh --- openssh-9.4p1/regress/agent-restrict.sh 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/agent-restrict.sh 1970-01-01 02:00:00.000000000 +0200 @@ -1,495 +0,0 @@ -# $OpenBSD: agent-restrict.sh,v 1.6 2023/03/01 09:29:32 dtucker Exp $ -# Placed in the Public Domain. - -tid="agent restrictions" - -SSH_AUTH_SOCK="$OBJ/agent.sock" -export SSH_AUTH_SOCK -rm -f $SSH_AUTH_SOCK $OBJ/agent.log $OBJ/host_[abcdex]* $OBJ/user_[abcdex]* -rm -f $OBJ/sshd_proxy_host* $OBJ/ssh_output* $OBJ/expect_* -rm -f $OBJ/ssh_proxy[._]* $OBJ/command - -verbose "generate keys" -for h in a b c d e x ca ; do - $SSHKEYGEN -q -t ed25519 -C host_$h -N '' -f $OBJ/host_$h || \ - fatal "ssh-keygen hostkey failed" - $SSHKEYGEN -q -t ed25519 -C user_$h -N '' -f $OBJ/user_$h || \ - fatal "ssh-keygen userkey failed" -done - -# Make some hostcerts -for h in d e ; do - id="host_$h" - $SSHKEYGEN -q -s $OBJ/host_ca -I $id -n $id -h $OBJ/host_${h}.pub || \ - fatal "ssh-keygen certify failed" -done - -verbose "prepare client config" -egrep -vi '(identityfile|hostname|hostkeyalias|proxycommand)' \ - $OBJ/ssh_proxy > $OBJ/ssh_proxy.bak -cat << _EOF > $OBJ/ssh_proxy -IdentitiesOnly yes -ForwardAgent yes -ExitOnForwardFailure yes -_EOF -cp $OBJ/ssh_proxy $OBJ/ssh_proxy_noid -for h in a b c d e ; do - cat << _EOF >> $OBJ/ssh_proxy -Host host_$h - Hostname host_$h - HostkeyAlias host_$h - IdentityFile $OBJ/user_$h - ProxyCommand ${SUDO} env SSH_SK_HELPER=\"$SSH_SK_HELPER\" ${OBJ}/sshd-log-wrapper.sh -i -f $OBJ/sshd_proxy_host_$h -_EOF - # Variant with no specified keys. - cat << _EOF >> $OBJ/ssh_proxy_noid -Host host_$h - Hostname host_$h - HostkeyAlias host_$h - ProxyCommand ${SUDO} env SSH_SK_HELPER=\"$SSH_SK_HELPER\" ${OBJ}/sshd-log-wrapper.sh -i -f $OBJ/sshd_proxy_host_$h -_EOF -done -cat $OBJ/ssh_proxy.bak >> $OBJ/ssh_proxy -cat $OBJ/ssh_proxy.bak >> $OBJ/ssh_proxy_noid - -LC_ALL=C -export LC_ALL -echo "SetEnv LC_ALL=${LC_ALL}" >> sshd_proxy - -verbose "prepare known_hosts" -rm -f $OBJ/known_hosts -for h in a b c x ; do - (printf "host_$h " ; cat $OBJ/host_${h}.pub) >> $OBJ/known_hosts -done -(printf "@cert-authority host_* " ; cat $OBJ/host_ca.pub) >> $OBJ/known_hosts - -verbose "prepare server configs" -egrep -vi '(hostkey|pidfile)' $OBJ/sshd_proxy \ - > $OBJ/sshd_proxy.bak -for h in a b c d e; do - cp $OBJ/sshd_proxy.bak $OBJ/sshd_proxy_host_$h - cat << _EOF >> $OBJ/sshd_proxy_host_$h -ExposeAuthInfo yes -PidFile none -Hostkey $OBJ/host_$h -_EOF -done -for h in d e ; do - echo "HostCertificate $OBJ/host_${h}-cert.pub" \ - >> $OBJ/sshd_proxy_host_$h -done -# Create authorized_keys with canned command. -reset_keys() { - _whichcmd="$1" - _command="" - case "$_whichcmd" in - authinfo) _command="cat \$SSH_USER_AUTH" ;; - keylist) _command="$SSHADD -L | cut -d' ' -f-2 | sort" ;; - *) fatal "unsupported command $_whichcmd" ;; - esac - trace "reset keys" - >$OBJ/authorized_keys_$USER - for h in e d c b a; do - (printf "%s" "restrict,agent-forwarding,command=\"$_command\" "; - cat $OBJ/user_$h.pub) >> $OBJ/authorized_keys_$USER - done -} -# Prepare a key for comparison with ExposeAuthInfo/$SSH_USER_AUTH. -expect_key() { - _key="$OBJ/${1}.pub" - _file="$OBJ/$2" - (printf "publickey " ; cut -d' ' -f-2 $_key) > $_file -} -# Prepare expect_* files to compare against authinfo forced command to ensure -# keys used for authentication match. -reset_expect_keys() { - for u in a b c d e; do - expect_key user_$u expect_$u - done -} -# ssh to host, expecting success and that output matched expectation for -# that host (expect_$h file). -expect_succeed() { - _id="$1" - _case="$2" - shift; shift; _extra="$@" - _host="host_$_id" - trace "connect $_host expect success" - rm -f $OBJ/ssh_output - ${SSH} $_extra -F $OBJ/ssh_proxy $_host true > $OBJ/ssh_output - _s=$? - test $_s -eq 0 || fail "host $_host $_case fail, exit status $_s" - diff $OBJ/ssh_output $OBJ/expect_${_id} || - fail "unexpected ssh output" -} -# ssh to host using explicit key, expecting success and that the key was -# actually used for authentication. -expect_succeed_key() { - _id="$1" - _key="$2" - _case="$3" - shift; shift; shift; _extra="$@" - _host="host_$_id" - trace "connect $_host expect success, with key $_key" - _keyfile="$OBJ/$_key" - rm -f $OBJ/ssh_output - ${SSH} $_extra -F $OBJ/ssh_proxy_noid \ - -oIdentityFile=$_keyfile $_host true > $OBJ/ssh_output - _s=$? - test $_s -eq 0 || fail "host $_host $_key $_case fail, exit status $_s" - expect_key $_key expect_key - diff $OBJ/ssh_output $OBJ/expect_key || - fail "incorrect key used for authentication" -} -# ssh to a host, expecting it to fail. -expect_fail() { - _host="$1" - _case="$2" - shift; shift; _extra="$@" - trace "connect $_host expect failure" - ${SSH} $_extra -F $OBJ/ssh_proxy $_host true >/dev/null && \ - fail "host $_host $_case succeeded unexpectedly" -} -# ssh to a host using an explicit key, expecting it to fail. -expect_fail_key() { - _id="$1" - _key="$2" - _case="$3" - shift; shift; shift; _extra="$@" - _host="host_$_id" - trace "connect $_host expect failure, with key $_key" - _keyfile="$OBJ/$_key" - ${SSH} $_extra -F $OBJ/ssh_proxy_noid -oIdentityFile=$_keyfile \ - $_host true > $OBJ/ssh_output && \ - fail "host $_host $_key $_case succeeded unexpectedly" -} -# Move the private key files out of the way to force use of agent-hosted keys. -hide_privatekeys() { - trace "hide private keys" - for u in a b c d e x; do - mv $OBJ/user_$u $OBJ/user_x$u || fatal "hide privkey $u" - done -} -# Put the private key files back. -restore_privatekeys() { - trace "restore private keys" - for u in a b c d e x; do - mv $OBJ/user_x$u $OBJ/user_$u || fatal "restore privkey $u" - done -} -clear_agent() { - ${SSHADD} -D > /dev/null 2>&1 || fatal "clear agent failed" -} - -reset_keys authinfo -reset_expect_keys - -verbose "authentication w/o agent" -for h in a b c d e ; do - expect_succeed $h "w/o agent" - wrongkey=user_e - test "$h" = "e" && wrongkey=user_a - expect_succeed_key $h $wrongkey "\"wrong\" key w/o agent" -done -hide_privatekeys -for h in a b c d e ; do - expect_fail $h "w/o agent" -done -restore_privatekeys - -verbose "start agent" -${SSHAGENT} ${EXTRA_AGENT_ARGS} -d -a $SSH_AUTH_SOCK > $OBJ/agent.log 2>&1 & -AGENT_PID=$! -trap "kill $AGENT_PID" EXIT -sleep 4 # Give it a chance to start -# Check that it's running. -${SSHADD} -l > /dev/null 2>&1 -if [ $? -ne 1 ]; then - fail "ssh-add -l did not fail with exit code 1" -fi - -verbose "authentication with agent (no restrict)" -for u in a b c d e x; do - $SSHADD -q $OBJ/user_$u || fatal "add key $u unrestricted" -done -hide_privatekeys -for h in a b c d e ; do - expect_succeed $h "with agent" - wrongkey=user_e - test "$h" = "e" && wrongkey=user_a - expect_succeed_key $h $wrongkey "\"wrong\" key with agent" -done - -verbose "unrestricted keylist" -reset_keys keylist -rm -f $OBJ/expect_list.pre -# List of keys from agent should contain everything. -for u in a b c d e x; do - cut -d " " -f-2 $OBJ/user_${u}.pub >> $OBJ/expect_list.pre -done -sort $OBJ/expect_list.pre > $OBJ/expect_list -for h in a b c d e; do - cp $OBJ/expect_list $OBJ/expect_$h - expect_succeed $h "unrestricted keylist" -done -restore_privatekeys - -verbose "authentication with agent (basic restrict)" -reset_keys authinfo -reset_expect_keys -for h in a b c d e; do - $SSHADD -h host_$h -H $OBJ/known_hosts -q $OBJ/user_$h \ - || fatal "add key $u basic restrict" -done -# One more, unrestricted -$SSHADD -q $OBJ/user_x || fatal "add unrestricted key" -hide_privatekeys -# Authentication to host with expected key should work. -for h in a b c d e ; do - expect_succeed $h "with agent" -done -# Authentication to host with incorrect key should fail. -verbose "authentication with agent incorrect key (basic restrict)" -for h in a b c d e ; do - wrongkey=user_e - test "$h" = "e" && wrongkey=user_a - expect_fail_key $h $wrongkey "wrong key with agent (basic restrict)" -done - -verbose "keylist (basic restrict)" -reset_keys keylist -# List from forwarded agent should contain only user_x - the unrestricted key. -cut -d " " -f-2 $OBJ/user_x.pub > $OBJ/expect_list -for h in a b c d e; do - cp $OBJ/expect_list $OBJ/expect_$h - expect_succeed $h "keylist (basic restrict)" -done -restore_privatekeys - -verbose "username" -reset_keys authinfo -reset_expect_keys -for h in a b c d e; do - $SSHADD -h "${USER}@host_$h" -H $OBJ/known_hosts -q $OBJ/user_$h \ - || fatal "add key $u basic restrict" -done -hide_privatekeys -for h in a b c d e ; do - expect_succeed $h "wildcard user" -done -restore_privatekeys - -verbose "username wildcard" -reset_keys authinfo -reset_expect_keys -for h in a b c d e; do - $SSHADD -h "*@host_$h" -H $OBJ/known_hosts -q $OBJ/user_$h \ - || fatal "add key $u basic restrict" -done -hide_privatekeys -for h in a b c d e ; do - expect_succeed $h "wildcard user" -done -restore_privatekeys - -verbose "username incorrect" -reset_keys authinfo -reset_expect_keys -for h in a b c d e; do - $SSHADD -h "--BADUSER@host_$h" -H $OBJ/known_hosts -q $OBJ/user_$h \ - || fatal "add key $u basic restrict" -done -hide_privatekeys -for h in a b c d e ; do - expect_fail $h "incorrect user" -done -restore_privatekeys - - -verbose "agent restriction honours certificate principal" -reset_keys authinfo -reset_expect_keys -clear_agent -$SSHADD -h host_e -H $OBJ/known_hosts -q $OBJ/user_d || fatal "add key" -hide_privatekeys -expect_fail d "restricted agent w/ incorrect cert principal" -restore_privatekeys - -# Prepares the script used to drive chained ssh connections for the -# multihop tests. Believe me, this is easier than getting the escaping -# right for 5 hops on the command-line... -prepare_multihop_script() { - MULTIHOP_RUN=$OBJ/command - cat << _EOF > $MULTIHOP_RUN -#!/bin/sh -#set -x -me="\$1" ; shift -next="\$1" -if test ! -z "\$me" ; then - rm -f $OBJ/done - echo "HOSTNAME host_\$me" - echo "AUTHINFO" - cat \$SSH_USER_AUTH -fi -echo AGENT -$SSHADD -L | egrep "^ssh" | cut -d" " -f-2 | sort -if test -z "\$next" ; then - touch $OBJ/done - echo "FINISH" - e=0 -else - echo NEXT - ${SSH} -F $OBJ/ssh_proxy_noid -oIdentityFile=$OBJ/user_a \ - host_\$next $MULTIHOP_RUN "\$@" - e=\$? -fi -echo "COMPLETE \"\$me\"" -if test ! -z "\$me" ; then - if test ! -f $OBJ/done ; then - echo "DONE MARKER MISSING" - test \$e -eq 0 && e=63 - fi -fi -exit \$e -_EOF - chmod u+x $MULTIHOP_RUN -} - -# Prepare expected output for multihop tests at expect_a -prepare_multihop_expected() { - _keys="$1" - _hops="a b c d e" - test -z "$2" || _hops="$2" - _revhops=$(echo "$_hops" | rev) - _lasthop=$(echo "$_hops" | sed 's/.* //') - - rm -f $OBJ/expect_keys - for h in a b c d e; do - cut -d" " -f-2 $OBJ/user_${h}.pub >> $OBJ/expect_keys - done - rm -f $OBJ/expect_a - echo "AGENT" >> $OBJ/expect_a - test "x$_keys" = "xnone" || sort $OBJ/expect_keys >> $OBJ/expect_a - echo "NEXT" >> $OBJ/expect_a - for h in $_hops ; do - echo "HOSTNAME host_$h" >> $OBJ/expect_a - echo "AUTHINFO" >> $OBJ/expect_a - (printf "publickey " ; cut -d" " -f-2 $OBJ/user_a.pub) >> $OBJ/expect_a - echo "AGENT" >> $OBJ/expect_a - if test "x$_keys" = "xall" ; then - sort $OBJ/expect_keys >> $OBJ/expect_a - fi - if test "x$h" != "x$_lasthop" ; then - if test "x$_keys" = "xfiltered" ; then - cut -d" " -f-2 $OBJ/user_a.pub >> $OBJ/expect_a - fi - echo "NEXT" >> $OBJ/expect_a - fi - done - echo "FINISH" >> $OBJ/expect_a - for h in $_revhops "" ; do - echo "COMPLETE \"$h\"" >> $OBJ/expect_a - done -} - -prepare_multihop_script -cp $OBJ/user_a.pub $OBJ/authorized_keys_$USER # only one key used. - -verbose "multihop without agent" -clear_agent -prepare_multihop_expected none -$MULTIHOP_RUN "" a b c d e > $OBJ/ssh_output || fail "multihop no agent ssh failed" -diff $OBJ/ssh_output $OBJ/expect_a || fail "unexpected ssh output" - -verbose "multihop agent unrestricted" -clear_agent -$SSHADD -q $OBJ/user_[abcde] -prepare_multihop_expected all -$MULTIHOP_RUN "" a b c d e > $OBJ/ssh_output || fail "multihop no agent ssh failed" -diff $OBJ/ssh_output $OBJ/expect_a || fail "unexpected ssh output" - -verbose "multihop restricted" -clear_agent -prepare_multihop_expected filtered -# Add user_a, with permission to connect through the whole chain. -$SSHADD -h host_a -h "host_a>host_b" -h "host_b>host_c" \ - -h "host_c>host_d" -h "host_d>host_e" \ - -H $OBJ/known_hosts -q $OBJ/user_a \ - || fatal "add key user_a multihop" -# Add the other keys, bound to a unused host. -$SSHADD -q -h host_x -H $OBJ/known_hosts $OBJ/user_[bcde] || fail "add keys" -hide_privatekeys -$MULTIHOP_RUN "" a b c d e > $OBJ/ssh_output || fail "multihop ssh failed" -diff $OBJ/ssh_output $OBJ/expect_a || fail "unexpected ssh output" -restore_privatekeys - -verbose "multihop username" -$SSHADD -h host_a -h "host_a>${USER}@host_b" -h "host_b>${USER}@host_c" \ - -h "host_c>${USER}@host_d" -h "host_d>${USER}@host_e" \ - -H $OBJ/known_hosts -q $OBJ/user_a || fatal "add key user_a multihop" -hide_privatekeys -$MULTIHOP_RUN "" a b c d e > $OBJ/ssh_output || fail "multihop w/ user ssh failed" -diff $OBJ/ssh_output $OBJ/expect_a || fail "unexpected ssh output" -restore_privatekeys - -verbose "multihop wildcard username" -$SSHADD -h host_a -h "host_a>*@host_b" -h "host_b>*@host_c" \ - -h "host_c>*@host_d" -h "host_d>*@host_e" \ - -H $OBJ/known_hosts -q $OBJ/user_a || fatal "add key user_a multihop" -hide_privatekeys -$MULTIHOP_RUN "" a b c d e > $OBJ/ssh_output || fail "multihop w/ user ssh failed" -diff $OBJ/ssh_output $OBJ/expect_a || fail "unexpected ssh output" -restore_privatekeys - -verbose "multihop wrong username" -$SSHADD -h host_a -h "host_a>*@host_b" -h "host_b>*@host_c" \ - -h "host_c>--BADUSER@host_d" -h "host_d>*@host_e" \ - -H $OBJ/known_hosts -q $OBJ/user_a || fatal "add key user_a multihop" -hide_privatekeys -$MULTIHOP_RUN "" a b c d e > $OBJ/ssh_output && \ - fail "multihop with wrong user succeeded unexpectedly" -restore_privatekeys - -verbose "multihop cycle no agent" -clear_agent -prepare_multihop_expected none "a b a a c d e" -$MULTIHOP_RUN "" a b a a c d e > $OBJ/ssh_output || \ - fail "multihop cycle no-agent fail" -diff $OBJ/ssh_output $OBJ/expect_a || fail "unexpected ssh output" - -verbose "multihop cycle agent unrestricted" -clear_agent -$SSHADD -q $OBJ/user_[abcde] || fail "add keys" -prepare_multihop_expected all "a b a a c d e" -$MULTIHOP_RUN "" a b a a c d e > $OBJ/ssh_output || \ - fail "multihop cycle agent ssh failed" -diff $OBJ/ssh_output $OBJ/expect_a || fail "unexpected ssh output" - -verbose "multihop cycle restricted deny" -clear_agent -$SSHADD -q -h host_x -H $OBJ/known_hosts $OBJ/user_[bcde] || fail "add keys" -$SSHADD -h host_a -h "host_a>host_b" -h "host_b>host_c" \ - -h "host_c>host_d" -h "host_d>host_e" \ - -H $OBJ/known_hosts -q $OBJ/user_a \ - || fatal "add key user_a multihop" -prepare_multihop_expected filtered "a b a a c d e" -hide_privatekeys -$MULTIHOP_RUN "" a b a a c d e > $OBJ/ssh_output && \ - fail "multihop cycle restricted deny succeded unexpectedly" -restore_privatekeys - -verbose "multihop cycle restricted allow" -clear_agent -$SSHADD -q -h host_x -H $OBJ/known_hosts $OBJ/user_[bcde] || fail "add keys" -$SSHADD -h host_a -h "host_a>host_b" -h "host_b>host_c" \ - -h "host_c>host_d" -h "host_d>host_e" \ - -h "host_b>host_a" -h "host_a>host_a" -h "host_a>host_c" \ - -H $OBJ/known_hosts -q $OBJ/user_a \ - || fatal "add key user_a multihop" -prepare_multihop_expected filtered "a b a a c d e" -hide_privatekeys -$MULTIHOP_RUN "" a b a a c d e > $OBJ/ssh_output || \ - fail "multihop cycle restricted allow failed" -diff $OBJ/ssh_output $OBJ/expect_a || fail "unexpected ssh output" -restore_privatekeys - diff -ruN openssh-9.4p1/regress/agent.sh openssh-9.4p1+x509-14.2.1/regress/agent.sh --- openssh-9.4p1/regress/agent.sh 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/agent.sh 2023-08-20 10:07:00.000000000 +0300 @@ -1,7 +1,20 @@ -# $OpenBSD: agent.sh,v 1.21 2023/03/01 09:29:32 dtucker Exp $ +# $OpenBSD: agent.sh,v 1.20 2021/02/25 03:27:34 djm Exp $ # Placed in the Public Domain. tid="simple agent test" +PLAIN_TYPES=`echo "$SSH_KEYTYPES" | sed 's/ssh-xmss@openssh.com//'` # TODO + +# cross-project configuration +if test "$sshd_type" != "pkix" ; then + for t in '' d ; do + mv $OBJ/ssh${t}_proxy $OBJ/ssh${t}_proxy.orig + ( + grep -v "PubkeyAcceptedAlgorithms" $OBJ/ssh${t}_proxy.orig + echo "PubkeyAcceptedAlgorithms *,ssh-dss*" + ) > $OBJ/ssh${t}_proxy + done +fi + SSH_AUTH_SOCK=/nonexistent ${SSHADD} -l > /dev/null 2>&1 if [ $? -ne 2 ]; then @@ -9,7 +22,7 @@ fi trace "start agent, args ${EXTRA_AGENT_ARGS} -s" -eval `${SSHAGENT} ${EXTRA_AGENT_ARGS} -s` >`ssh_logfile ssh-agent` +eval `${SSHAGENT} ${EXTRA_AGENT_ARGS} -s` > /dev/null r=$? if [ $r -ne 0 ]; then fatal "could not start ssh-agent: exit code $r" @@ -33,7 +46,7 @@ trace "overwrite authorized keys" printf '' > $OBJ/authorized_keys_$USER -for t in ${SSH_KEYTYPES}; do +for t in $PLAIN_TYPES ; do # generate user key for agent rm -f $OBJ/$t-agent $OBJ/$t-agent.pub* ${SSHKEYGEN} -q -N '' -t $t -f $OBJ/$t-agent ||\ @@ -46,13 +59,15 @@ cat $OBJ/$t-agent.pub >> $OBJ/authorized_keys_$USER # add private key to agent ${SSHADD} $OBJ/$t-agent > /dev/null 2>&1 - if [ $? -ne 0 ]; then - fail "ssh-add failed exit code $?" + r=$? + if [ $r -ne 0 ]; then + fail "ssh-add failed exit code $r" fi # add private key to second agent SSH_AUTH_SOCK=$FW_SSH_AUTH_SOCK ${SSHADD} $OBJ/$t-agent > /dev/null 2>&1 - if [ $? -ne 0 ]; then - fail "ssh-add failed exit code $?" + r=$? + if [ $r -ne 0 ]; then + fail "ssh-add failed exit code $r" fi # Move private key to ensure that we aren't accidentally using it. # Keep the corresponding public keys/certs around for later use. @@ -84,17 +99,13 @@ fail "ssh connect with failed (exit code $r)" fi -for t in ${SSH_KEYTYPES}; do +for t in $PLAIN_TYPES; do trace "connect via agent using $t key" - if [ "$t" = "ssh-dss" ]; then - echo "PubkeyAcceptedAlgorithms +ssh-dss" >> $OBJ/ssh_proxy - echo "PubkeyAcceptedAlgorithms +ssh-dss" >> $OBJ/sshd_proxy - fi ${SSH} -F $OBJ/ssh_proxy -i $OBJ/$t-agent.pub -oIdentitiesOnly=yes \ somehost exit 52 r=$? if [ $r -ne 52 ]; then - fail "ssh connect with failed (exit code $r)" + fail "ssh connect with $t failed (exit code $r)" fi done @@ -142,17 +153,15 @@ (printf 'cert-authority,principals="estragon" '; cat $OBJ/user_ca_key.pub) \ > $OBJ/authorized_keys_$USER -for t in ${SSH_KEYTYPES}; do - if [ "$t" != "ssh-dss" ]; then +for t in $PLAIN_TYPES; do trace "connect via agent using $t key" ${SSH} -F $OBJ/ssh_proxy -i $OBJ/$t-agent.pub \ -oCertificateFile=$OBJ/$t-agent-cert.pub \ -oIdentitiesOnly=yes somehost exit 52 r=$? if [ $r -ne 52 ]; then - fail "ssh connect with failed (exit code $r)" + fail "ssh connect with $t failed (exit code $r)" fi - fi done ## Deletion tests. @@ -171,7 +180,7 @@ fi trace "readd keys" # re-add keys/certs to agent -for t in ${SSH_KEYTYPES}; do +for t in $PLAIN_TYPES; do ${SSHADD} $OBJ/$t-agent-private >/dev/null 2>&1 || \ fail "ssh-add failed exit code $?" done diff -ruN openssh-9.4p1/regress/agent-subprocess.sh openssh-9.4p1+x509-14.2.1/regress/agent-subprocess.sh --- openssh-9.4p1/regress/agent-subprocess.sh 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/agent-subprocess.sh 2023-08-20 10:07:00.000000000 +0300 @@ -4,19 +4,23 @@ tid="agent subprocess" trace "ensure agent exits when run as subprocess" -${SSHAGENT} sh -c "echo \$SSH_AGENT_PID >$OBJ/pidfile; sleep 1" - +$SSHAGENT $TEST_SHELL -c "echo \$SSH_AGENT_PID >$OBJ/pidfile; sleep 1" +sleep 1 pid=`cat $OBJ/pidfile` -# Currently ssh-agent polls every 10s so we need to wait at least that long. -n=12 -while kill -0 $pid >/dev/null 2>&1 && test "$n" -gt "0"; do - n=$(($n - 1)) - sleep 1 +echo "waiting about 10s agent to exit ..." +# currently ssh-agent polls every 10s so we need to wait at least that long. +count=12 +while test $count -gt 0 ; do + sleep 1 + if ! kill -0 $pid >/dev/null 2>&1 ; then + break + fi + count=`expr $count - 1` done -if test "$n" -eq "0"; then - fail "agent still running" +if test $count -eq 0 ; then + fail "agent still running" fi rm -f $OBJ/pidfile diff -ruN openssh-9.4p1/regress/allow-deny-users.sh openssh-9.4p1+x509-14.2.1/regress/allow-deny-users.sh --- openssh-9.4p1/regress/allow-deny-users.sh 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/allow-deny-users.sh 2023-08-20 10:07:00.000000000 +0300 @@ -21,8 +21,7 @@ cp $OBJ/sshd_proxy.orig $OBJ/sshd_proxy test -z "$deny" || echo DenyUsers="$deny" >> $OBJ/sshd_proxy - test -z "$allow" || echo AllowUsers="$allow" >> $OBJ/sshd_proxy - + test -z "$allow" || echo "AllowUsers $allow" >> $OBJ/sshd_proxy ${SSH} -F $OBJ/ssh_proxy "$me@somehost" true status=$? diff -ruN openssh-9.4p1/regress/banner.sh openssh-9.4p1+x509-14.2.1/regress/banner.sh --- openssh-9.4p1/regress/banner.sh 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/banner.sh 2023-08-20 10:07:00.000000000 +0300 @@ -37,9 +37,8 @@ trace "test suppress banner (-q)" verbose "test $tid: suppress banner (-q)" -# ssh-log-wrapper drops "-q" to preserve debug output so use ssh directly -# for just this test. -( ${REAL_SSH} -q -F $OBJ/ssh_proxy otherhost true 2>$OBJ/banner.out && \ +# ssh-log-wrapper drops "-q" to preserve debug output so use -qq as work-around +( $SSH -qq -F $OBJ/ssh_proxy otherhost true 2>$OBJ/banner.out && \ cmp $OBJ/empty.in $OBJ/banner.out ) || \ fail "suppress banner (-q)" diff -ruN openssh-9.4p1/regress/cert-hostkey.sh openssh-9.4p1+x509-14.2.1/regress/cert-hostkey.sh --- openssh-9.4p1/regress/cert-hostkey.sh 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/cert-hostkey.sh 2023-08-20 10:07:00.000000000 +0300 @@ -7,21 +7,25 @@ rm -f $OBJ/cert_host_key* $OBJ/host_krl_* # Allow all hostkey/pubkey types, prefer certs for the client -rsa=0 +has_rsa=false types="" -for i in `$SSH -Q key | maybe_filter_sk`; do +for i in `$SSH -Q key | grep -v "^x509v3-"`; do if [ -z "$types" ]; then types="$i" continue fi + if config_defined HAVE_EVP_SHA256 ; then + # special treatment for RSA keys: + case "$i" in + *rsa*cert*) + i="rsa-sha2-512-cert-v01@openssh.com,$i" + i="rsa-sha2-256-cert-v01@openssh.com,$i";; + *rsa*) + has_rsa=true; + i="rsa-sha2-256,rsa-sha2-512,$i";; + esac + fi case "$i" in - # Special treatment for RSA keys. - *rsa*cert*) - types="rsa-sha2-256-cert-v01@openssh.com,$i,$types" - types="rsa-sha2-512-cert-v01@openssh.com,$types";; - *rsa*) - rsa=1 - types="$types,rsa-sha2-512,rsa-sha2-256,$i";; # Prefer certificate to plain keys. *cert*) types="$i,$types";; *) types="$types,$i";; @@ -40,13 +44,13 @@ HOSTS='localhost-with-alias,127.0.0.1,::1' kh_ca() { - for k in "$@" ; do + for k in ${1+"$@"} ; do printf "@cert-authority $HOSTS " cat $OBJ/$k || fatal "couldn't cat $k" done } kh_revoke() { - for k in "$@" ; do + for k in ${1+"$@"} ; do printf "@revoked * " cat $OBJ/$k || fatal "couldn't cat $k" done @@ -55,10 +59,12 @@ # Create a CA key and add it to known hosts. Ed25519 chosen for speed. # RSA for testing RSA/SHA2 signatures if supported. ktype2=ed25519 -[ "x$rsa" = "x1" ] && ktype2=rsa -${SSHKEYGEN} -q -N '' -t ed25519 -f $OBJ/host_ca_key ||\ +$has_rsa && ktype2=rsa +keytype_compat ed25519 +$SSHKEYGEN -q -N '' $keytype_val -f $OBJ/host_ca_key ||\ fail "ssh-keygen of host_ca_key failed" -${SSHKEYGEN} -q -N '' -t $ktype2 -f $OBJ/host_ca_key2 ||\ +keytype_compat $ktype2 +$SSHKEYGEN -q -N '' $keytype_val -f $OBJ/host_ca_key2 ||\ fail "ssh-keygen of host_ca_key failed" kh_ca host_ca_key.pub host_ca_key2.pub > $OBJ/known_hosts-cert.orig @@ -70,10 +76,13 @@ touch $OBJ/host_revoked_cert cat $OBJ/host_ca_key.pub $OBJ/host_ca_key2.pub > $OBJ/host_revoked_ca -PLAIN_TYPES=`echo "$SSH_KEYTYPES" | sed 's/^ssh-dss/ssh-dsa/g;s/^ssh-//'` +PLAIN_TYPES=`echo "$SSH_HOSTKEY_TYPES" | sed 's/^ssh-dss/ssh-dsa/g;s/^ssh-//'` +PLAIN_TYPES=`echo "$PLAIN_TYPES" | sed 's/xmss@openssh.com//'` # TODO if echo "$PLAIN_TYPES" | grep '^rsa$' >/dev/null 2>&1 ; then + if config_defined HAVE_EVP_SHA256 ; then PLAIN_TYPES="$PLAIN_TYPES rsa-sha2-256 rsa-sha2-512" + fi fi # Prepare certificate, plain key and CA KRLs @@ -88,7 +97,8 @@ for ktype in $PLAIN_TYPES ; do verbose "$tid: sign host ${ktype} cert" # Generate and sign a host key - ${SSHKEYGEN} -q -N '' -t ${ktype} \ + keytype_compat $ktype + $SSHKEYGEN -q -N '' $keytype_val \ -f $OBJ/cert_host_key_${ktype} || \ fatal "ssh-keygen of cert_host_key_${ktype} failed" ${SSHKEYGEN} -ukf $OBJ/host_krl_plain \ @@ -117,7 +127,7 @@ cp $OBJ/known_hosts-cert.orig $OBJ/known_hosts-cert ${SSH} -oUserKnownHostsFile=$OBJ/known_hosts-cert \ -oGlobalKnownHostsFile=$OBJ/known_hosts-cert \ - "$@" -F $OBJ/ssh_proxy somehost true + ${1+"$@"} -F $OBJ/ssh_proxy somehost true _r=$? if [ "x$_expect_success" = "xyes" ] ; then if [ $_r -ne 0 ]; then @@ -131,12 +141,14 @@ } # Basic connect and revocation tests. +for privsep in $SSHD_PRIVSEP ; do for ktype in $PLAIN_TYPES ; do - verbose "$tid: host ${ktype} cert connect" + verbose "$tid: host ${ktype} cert connect privsep $privsep" ( cat $OBJ/sshd_proxy_bak echo HostKey $OBJ/cert_host_key_${ktype} echo HostCertificate $OBJ/cert_host_key_${ktype}-cert.pub + echo UsePrivilegeSeparation $privsep ) > $OBJ/sshd_proxy # test name expect success @@ -158,6 +170,7 @@ attempt_connect "$ktype CA plaintext revocation" "no" \ -oRevokedHostKeys=$OBJ/host_revoked_ca done +done # Revoked certificates with key present kh_ca host_ca_key.pub host_ca_key2.pub > $OBJ/known_hosts-cert.orig @@ -166,12 +179,14 @@ kh_revoke cert_host_key_${ktype}.pub >> $OBJ/known_hosts-cert.orig done cp $OBJ/known_hosts-cert.orig $OBJ/known_hosts-cert +for privsep in $SSHD_PRIVSEP ; do for ktype in $PLAIN_TYPES ; do - verbose "$tid: host ${ktype} revoked cert" + verbose "$tid: host ${ktype} revoked cert privsep $privsep" ( cat $OBJ/sshd_proxy_bak echo HostKey $OBJ/cert_host_key_${ktype} echo HostCertificate $OBJ/cert_host_key_${ktype}-cert.pub + echo UsePrivilegeSeparation $privsep ) > $OBJ/sshd_proxy cp $OBJ/known_hosts-cert.orig $OBJ/known_hosts-cert @@ -182,6 +197,7 @@ fail "ssh cert connect succeeded unexpectedly" fi done +done # Revoked CA kh_ca host_ca_key.pub host_ca_key2.pub > $OBJ/known_hosts-cert.orig @@ -246,7 +262,7 @@ test_one "user-certificate" failure "-n $HOSTS" test_one "empty principals" success "-h" test_one "wrong principals" failure "-h -n foo" -test_one "cert not yet valid" failure "-h -V20300101:20320101" +test_one "cert not yet valid" failure "-h -V20300101:20380101" test_one "cert expired" failure "-h -V19800101:19900101" test_one "cert valid interval" success "-h -V-1w:+2w" test_one "cert has constraints" failure "-h -Oforce-command=false" @@ -256,7 +272,8 @@ rm -f $OBJ/known_hosts-cert $OBJ/cert_host_key* verbose "$tid: host ${ktype} ${v} cert downgrade to raw key" # Generate and sign a host key - ${SSHKEYGEN} -q -N '' -t ${ktype} -f $OBJ/cert_host_key_${ktype} || \ + keytype_compat $ktype + $SSHKEYGEN -q -N '' $keytype_val -f $OBJ/cert_host_key_$ktype || \ fail "ssh-keygen of cert_host_key_${ktype} failed" case $ktype in rsa-sha2-*) tflag="-t $ktype"; ca="$OBJ/host_ca_key2" ;; @@ -297,7 +314,8 @@ verbose "$tid: host ${kt} connect wrong cert" rm -f $OBJ/cert_host_key* # Self-sign key - ${SSHKEYGEN} -q -N '' -t ${kt} -f $OBJ/cert_host_key_${kt} || \ + keytype_compat $kt + $SSHKEYGEN -q -N '' $keytype_val -f $OBJ/cert_host_key_$kt || \ fail "ssh-keygen of cert_host_key_${kt} failed" case $kt in rsa-sha2-*) tflag="-t $kt" ;; diff -ruN openssh-9.4p1/regress/cert-userkey.sh openssh-9.4p1+x509-14.2.1/regress/cert-userkey.sh --- openssh-9.4p1/regress/cert-userkey.sh 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/cert-userkey.sh 2023-08-20 10:07:00.000000000 +0300 @@ -7,24 +7,25 @@ cp $OBJ/sshd_proxy $OBJ/sshd_proxy_bak cp $OBJ/ssh_proxy $OBJ/ssh_proxy_bak -PLAIN_TYPES=`$SSH -Q key-plain | maybe_filter_sk | sed 's/^ssh-dss/ssh-dsa/;s/^ssh-//'` -EXTRA_TYPES="" -rsa="" +PLAIN_TYPES=`echo "$SSH_KEYTYPES" | sed 's/^ssh-dss/ssh-dsa/;s/^ssh-//'` +PLAIN_TYPES=`echo "$PLAIN_TYPES" | sed 's/xmss@openssh.com//'` # TODO +EXTRA_TYPES= +rsa= if echo "$PLAIN_TYPES" | grep '^rsa$' >/dev/null 2>&1 ; then rsa=rsa + if config_defined HAVE_EVP_SHA256 ; then PLAIN_TYPES="$PLAIN_TYPES rsa-sha2-256 rsa-sha2-512" + fi fi kname() { case $1 in rsa-sha2-*) n="$1" ;; - sk-ecdsa-*) n="sk-ecdsa" ;; - sk-ssh-ed25519*) n="sk-ssh-ed25519" ;; # subshell because some seds will add a newline *) n=$(echo $1 | sed 's/^dsa/ssh-dss/;s/^rsa/ssh-rsa/;s/^ed/ssh-ed/') ;; esac - if [ -z "$rsa" ]; then + if test -z "$rsa" ; then echo "$n*,ssh-ed25519*" else echo "$n*,ssh-rsa*,ssh-ed25519*" @@ -32,10 +33,10 @@ } # Create a CA key -if [ ! -z "$rsa" ]; then - catype=rsa -else +if test -z "$rsa" ; then catype=ed25519 +else + catype=rsa fi ${SSHKEYGEN} -q -N '' -t $catype -f $OBJ/user_ca_key ||\ fail "ssh-keygen of user_ca_key failed" @@ -60,12 +61,14 @@ # Test explicitly-specified principals for ktype in $EXTRA_TYPES $PLAIN_TYPES ; do t=$(kname $ktype) - _prefix="${ktype}" +for privsep in $SSHD_PRIVSEP ; do + _prefix="${ktype} privsep $privsep" # Setup for AuthorizedPrincipalsFile rm -f $OBJ/authorized_keys_$USER ( cat $OBJ/sshd_proxy_bak + echo "UsePrivilegeSeparation $privsep" echo "AuthorizedPrincipalsFile " \ "$OBJ/authorized_principals_%u" echo "TrustedUserCAKeys $OBJ/user_ca_key.pub" @@ -146,6 +149,7 @@ rm -f $OBJ/authorized_principals_$USER ( cat $OBJ/sshd_proxy_bak + echo "UsePrivilegeSeparation $privsep" echo "PubkeyAcceptedAlgorithms ${t}" ) > $OBJ/sshd_proxy ( @@ -177,6 +181,7 @@ fail "ssh cert connect failed" fi done +done basic_tests() { auth=$1 @@ -193,11 +198,13 @@ for ktype in $PLAIN_TYPES ; do t=$(kname $ktype) - _prefix="${ktype} $auth" + for privsep in $SSHD_PRIVSEP ; do + _prefix="${ktype} privsep $privsep $auth" # Simple connect verbose "$tid: ${_prefix} connect" ( cat $OBJ/sshd_proxy_bak + echo "UsePrivilegeSeparation $privsep" echo "PubkeyAcceptedAlgorithms ${t}" echo "$extra_sshd" ) > $OBJ/sshd_proxy @@ -216,6 +223,7 @@ verbose "$tid: ${_prefix} revoked key" ( cat $OBJ/sshd_proxy_bak + echo "UsePrivilegeSeparation $privsep" echo "RevokedKeys $OBJ/cert_user_key_revoked" echo "PubkeyAcceptedAlgorithms ${t}" echo "$extra_sshd" @@ -245,19 +253,20 @@ fi done - # Revoked CA - verbose "$tid: ${ktype} $auth revoked CA key" - ( - cat $OBJ/sshd_proxy_bak - echo "RevokedKeys $OBJ/user_ca_key.pub" - echo "PubkeyAcceptedAlgorithms ${t}" - echo "$extra_sshd" - ) > $OBJ/sshd_proxy - ${SSH} -i $OBJ/cert_user_key_${ktype} -F $OBJ/ssh_proxy \ - somehost true >/dev/null 2>&1 - if [ $? -eq 0 ]; then - fail "ssh cert connect succeeded unexpecedly" - fi + # Revoked CA + verbose "$tid: ${ktype} $auth revoked CA key" + ( + cat $OBJ/sshd_proxy_bak + echo "RevokedKeys $OBJ/user_ca_key.pub" + echo "PubkeyAcceptedAlgorithms ${t}" + echo "$extra_sshd" + ) > $OBJ/sshd_proxy + ${SSH} -i $OBJ/cert_user_key_${ktype} -F $OBJ/ssh_proxy \ + somehost true >/dev/null 2>&1 + if [ $? -eq 0 ]; then + fail "ssh cert connect succeeded unexpecedly" + fi + done verbose "$tid: $auth CA does not authenticate" ( @@ -332,7 +341,7 @@ test_one "correct principal" success "-n ${USER}" test_one "host-certificate" failure "-n ${USER} -h" test_one "wrong principals" failure "-n foo" -test_one "cert not yet valid" failure "-n ${USER} -V20300101:20320101" +test_one "cert not yet valid" failure "-n ${USER} -V20300101:20380101" test_one "cert expired" failure "-n ${USER} -V19800101:19900101" test_one "cert valid interval" success "-n ${USER} -V-1w:+2w" test_one "wrong source-address" failure "-n ${USER} -Osource-address=10.0.0.0/8" diff -ruN openssh-9.4p1/regress/cfginclude.sh openssh-9.4p1+x509-14.2.1/regress/cfginclude.sh --- openssh-9.4p1/regress/cfginclude.sh 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/cfginclude.sh 2023-08-20 10:07:00.000000000 +0300 @@ -1,4 +1,4 @@ -# $OpenBSD: cfginclude.sh,v 1.3 2021/06/08 06:52:43 djm Exp $ +# $OpenBSD: cfginclude.sh,v 1.2 2016/05/03 15:30:46 dtucker Exp $ # Placed in the Public Domain. tid="config include" @@ -10,7 +10,7 @@ Match host a Hostname aa -Match host b # comment +Match host b Hostname bb Include $OBJ/ssh_config.i.* @@ -19,10 +19,10 @@ Hostname cc Match host m - Include $OBJ/ssh_config.i.* # comment + Include $OBJ/ssh_config.i.* Host d - Hostname dd # comment + Hostname dd Host e Hostname ee @@ -47,17 +47,17 @@ Match host b Hostname bbb -Match host c # comment +Match host c Hostname ccc -Host d # comment +Host d Hostname ddd Host e Hostname eee Host f - Hostname fff # comment + Hostname fff _EOF cat > $OBJ/ssh_config.i.2 << _EOF @@ -86,7 +86,7 @@ trial() { _host="$1" _exp="$2" - ${REAL_SSH} -F $OBJ/ssh_config.i -G "$_host" > $OBJ/ssh_config.out || + ${REAL_SSH} -F $OBJ/ssh_config.i -d "$_host" > $OBJ/ssh_config.out || fatal "ssh config parse failed" _got=`grep -i '^hostname ' $OBJ/ssh_config.out | awk '{print $2}'` if test "x$_exp" != "x$_got" ; then @@ -111,10 +111,10 @@ Junk _EOF -${REAL_SSH} -F $OBJ/ssh_config.i -G a 2>/dev/null && \ +${REAL_SSH} -F $OBJ/ssh_config.i -d a 2>/dev/null && \ fail "ssh include allowed invalid config" -${REAL_SSH} -F $OBJ/ssh_config.i -G x 2>/dev/null && \ +${REAL_SSH} -F $OBJ/ssh_config.i -d x 2>/dev/null && \ fail "ssh include allowed invalid config" rm -f $OBJ/ssh_config.i.* @@ -142,7 +142,7 @@ # cleanup rm -f $OBJ/ssh_config.i $OBJ/ssh_config.i.* $OBJ/ssh_config.out -# $OpenBSD: cfginclude.sh,v 1.3 2021/06/08 06:52:43 djm Exp $ +# $OpenBSD: cfginclude.sh,v 1.2 2016/05/03 15:30:46 dtucker Exp $ # Placed in the Public Domain. tid="config include" @@ -185,11 +185,11 @@ Match host a Hostname aaa -Match host b # comment +Match host b Hostname bbb Match host c - Hostname ccc # comment + Hostname ccc Host d Hostname ddd @@ -220,14 +220,14 @@ Host f Hostname ffff -Match all # comment - Hostname xxxx # comment +Match all + Hostname xxxx _EOF trial() { _host="$1" _exp="$2" - ${REAL_SSH} -F $OBJ/ssh_config.i -G "$_host" > $OBJ/ssh_config.out || + ${REAL_SSH} -F $OBJ/ssh_config.i -d "$_host" > $OBJ/ssh_config.out || fatal "ssh config parse failed" _got=`grep -i '^hostname ' $OBJ/ssh_config.out | awk '{print $2}'` if test "x$_exp" != "x$_got" ; then @@ -252,10 +252,10 @@ Junk _EOF -${REAL_SSH} -F $OBJ/ssh_config.i -G a 2>/dev/null && \ +${REAL_SSH} -F $OBJ/ssh_config.i -d a 2>/dev/null && \ fail "ssh include allowed invalid config" -${REAL_SSH} -F $OBJ/ssh_config.i -G x 2>/dev/null && \ +${REAL_SSH} -F $OBJ/ssh_config.i -d x 2>/dev/null && \ fail "ssh include allowed invalid config" rm -f $OBJ/ssh_config.i.* @@ -286,7 +286,7 @@ Include $OBJ/ssh_config.i _EOF -${REAL_SSH} -F $OBJ/ssh_config.i -G a 2>/dev/null && \ +${REAL_SSH} -F $OBJ/ssh_config.i -d a 2>/dev/null && \ fail "ssh include allowed infinite recursion?" # or hang... # cleanup diff -ruN openssh-9.4p1/regress/cfgmatchlisten.sh openssh-9.4p1+x509-14.2.1/regress/cfgmatchlisten.sh --- openssh-9.4p1/regress/cfgmatchlisten.sh 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/cfgmatchlisten.sh 2023-08-20 10:07:00.000000000 +0300 @@ -14,14 +14,13 @@ start_client() { rm -f $pidfile - ${SSH} -vvv $fwd "$@" somehost true >>$TEST_REGRESS_LOGFILE 2>&1 + $SSH $fwd ${1+"$@"} somehost true r=$? if [ $r -ne 0 ]; then return $r fi - ${SSH} -vvv $fwd "$@" somehost \ - exec sh -c \'"echo \$\$ > $pidfile; exec sleep 100"\' \ - >>$TEST_REGRESS_LOGFILE 2>&1 & + $SSH $fwd ${1+"$@"} somehost \ + exec sh -c \'"echo \$\$ > $pidfile; exec sleep 100"\' & client_pid=$! # Wait for remote end n=0 @@ -38,15 +37,15 @@ expect_client_ok() { - start_client "$@" || + start_client ${1+"$@"} || fail "client did not start" } expect_client_fail() { - local failmsg="$1" + failmsg="$1" shift - start_client "$@" && + start_client ${1+"$@"} && fail $failmsg } diff -ruN openssh-9.4p1/regress/cfgmatch.sh openssh-9.4p1+x509-14.2.1/regress/cfgmatch.sh --- openssh-9.4p1/regress/cfgmatch.sh 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/cfgmatch.sh 2023-08-20 10:07:00.000000000 +0300 @@ -1,4 +1,4 @@ -# $OpenBSD: cfgmatch.sh,v 1.13 2021/06/08 06:52:43 djm Exp $ +# $OpenBSD: cfgmatch.sh,v 1.12 2019/04/18 18:57:16 dtucker Exp $ # Placed in the Public Domain. tid="sshd_config match" @@ -13,9 +13,8 @@ start_client() { rm -f $pidfile - ${SSH} -q $fwd "$@" somehost \ - exec sh -c \'"echo \$\$ > $pidfile; exec sleep 100"\' \ - >>$TEST_REGRESS_LOGFILE 2>&1 & + $SSH -q $fwd ${1+"$@"} somehost \ + exec sh -c \'"echo \$\$ > $pidfile; exec sleep 100"\' & client_pid=$! # Wait for remote end n=0 @@ -26,7 +25,7 @@ kill $client_pid fatal "timeout waiting for background ssh" fi - done + done } stop_client() @@ -39,16 +38,16 @@ } cp $OBJ/sshd_proxy $OBJ/sshd_proxy_bak -echo "PermitOpen 127.0.0.1:1 # comment" >>$OBJ/sshd_config +echo "PermitOpen 127.0.0.1:1" >>$OBJ/sshd_config echo "Match Address 127.0.0.1" >>$OBJ/sshd_config echo "PermitOpen 127.0.0.1:2 127.0.0.1:3 127.0.0.1:$PORT" >>$OBJ/sshd_config grep -v AuthorizedKeysFile $OBJ/sshd_proxy_bak > $OBJ/sshd_proxy -echo "AuthorizedKeysFile /dev/null # comment" >>$OBJ/sshd_proxy +echo "AuthorizedKeysFile /dev/null" >>$OBJ/sshd_proxy echo "PermitOpen 127.0.0.1:1" >>$OBJ/sshd_proxy echo "Match user $USER" >>$OBJ/sshd_proxy echo "AuthorizedKeysFile /dev/null $OBJ/authorized_keys_%u" >>$OBJ/sshd_proxy -echo "Match Address 127.0.0.1 # comment" >>$OBJ/sshd_proxy +echo "Match Address 127.0.0.1" >>$OBJ/sshd_proxy echo "PermitOpen 127.0.0.1:2 127.0.0.1:3 127.0.0.1:$PORT" >>$OBJ/sshd_proxy ${SUDO} ${SSHD} -f $OBJ/sshd_config -T >/dev/null || \ diff -ruN openssh-9.4p1/regress/channel-timeout.sh openssh-9.4p1+x509-14.2.1/regress/channel-timeout.sh --- openssh-9.4p1/regress/channel-timeout.sh 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/channel-timeout.sh 2023-08-20 10:07:00.000000000 +0300 @@ -4,10 +4,21 @@ tid="channel timeout" # XXX not comprehensive. Still need -R -L agent X11 forwarding + interactive +SFTPSUBSYS=$OBJ/slow-sftp-server.sh -rm -f $OBJ/sshd_proxy.orig +rm -f $OBJ/sshd_proxy.orig cp $OBJ/sshd_proxy $OBJ/sshd_proxy.orig +# Set up a "slow sftp server" that sleeps before executing the real one. +cat > $SFTPSUBSYS << EOF +#! /bin/sh + +sleep 5 +$SFTPSERVER +EOF +chmod a+x $SFTPSUBSYS + + verbose "no timeout" ${SSH} -F $OBJ/ssh_proxy somehost "sleep 5 ; exit 23" r=$? @@ -42,21 +53,12 @@ fail "ssh failed" fi -# Set up a "slow sftp server" that sleeps before executing the real one. -cat > $OBJ/slow-sftp-server.sh << _EOF -#!/bin/sh - -sleep 5 -$SFTPSERVER -_EOF -chmod a+x $OBJ/slow-sftp-server.sh - verbose "sftp no timeout" (grep -vi subsystem.*sftp $OBJ/sshd_proxy.orig; - echo "Subsystem sftp $OBJ/slow-sftp-server.sh" ) > $OBJ/sshd_proxy + echo "Subsystem sftp $SFTPSUBSYS" ) > $OBJ/sshd_proxy rm -f ${COPY} -$SFTP -qS $SSH -F $OBJ/ssh_proxy somehost:$DATA $COPY +$SFTP -qS $SSH -F $OBJ/ssh_proxy somehost:$DATA $COPY >>$TEST_REGRESS_LOGFILE 2>&1 r=$? if [ $r -ne 0 ]; then fail "sftp failed" @@ -66,10 +68,10 @@ verbose "sftp timeout" (grep -vi subsystem.*sftp $OBJ/sshd_proxy.orig; echo "ChannelTimeout session:subsystem:sftp=1" ; - echo "Subsystem sftp $OBJ/slow-sftp-server.sh" ) > $OBJ/sshd_proxy + echo "Subsystem sftp $SFTPSUBSYS" ) > $OBJ/sshd_proxy rm -f ${COPY} -$SFTP -qS $SSH -F $OBJ/ssh_proxy somehost:$DATA $COPY +$SFTP -qS $SSH -F $OBJ/ssh_proxy somehost:$DATA $COPY >>$TEST_REGRESS_LOGFILE 2>&1 r=$? if [ $r -eq 0 ]; then fail "sftp succeeded unexpectedly" @@ -79,13 +81,14 @@ verbose "sftp irrelevant timeout" (grep -vi subsystem.*sftp $OBJ/sshd_proxy.orig; echo "ChannelTimeout session:subsystem:command=1" ; - echo "Subsystem sftp $OBJ/slow-sftp-server.sh" ) > $OBJ/sshd_proxy + echo "Subsystem sftp $SFTPSUBSYS" ) > $OBJ/sshd_proxy rm -f ${COPY} -$SFTP -qS $SSH -F $OBJ/ssh_proxy somehost:$DATA $COPY +$SFTP -qS $SSH -F $OBJ/ssh_proxy somehost:$DATA $COPY >>$TEST_REGRESS_LOGFILE 2>&1 r=$? if [ $r -ne 0 ]; then fail "sftp failed" fi cmp $DATA $COPY || fail "corrupted copy" +rm -f "$SFTPSUBSYS" diff -ruN openssh-9.4p1/regress/check-perm.c openssh-9.4p1+x509-14.2.1/regress/check-perm.c --- openssh-9.4p1/regress/check-perm.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/check-perm.c 2023-08-20 10:07:01.000000000 +0300 @@ -19,6 +19,9 @@ #include #endif +/* misc.c */ +int safe_path(const char *, struct stat *, const char *, uid_t, char *, size_t); + static void fatal(const char *fmt, ...) { @@ -58,7 +61,7 @@ /* debug3("%s: checking '%s'", __func__, component); */ - if (stat(component, &st) != 0) + if (stat(component, &st) == -1) fatal("%s: stat(\"%s\"): %s", __func__, component, strerror(errno)); if (st.st_uid != 0 || (st.st_mode & 022) != 0) @@ -89,65 +92,6 @@ return 0; } -/* from auth.c */ -int -auth_secure_path(const char *name, struct stat *stp, const char *pw_dir, - uid_t uid, char *err, size_t errlen) -{ - char buf[PATH_MAX], homedir[PATH_MAX]; - char *cp; - int comparehome = 0; - struct stat st; - - if (realpath(name, buf) == NULL) { - snprintf(err, errlen, "realpath %s failed: %s", name, - strerror(errno)); - return -1; - } - if (pw_dir != NULL && realpath(pw_dir, homedir) != NULL) - comparehome = 1; - - if (!S_ISREG(stp->st_mode)) { - snprintf(err, errlen, "%s is not a regular file", buf); - return -1; - } - if ((!platform_sys_dir_uid(stp->st_uid) && stp->st_uid != uid) || - (stp->st_mode & 022) != 0) { - snprintf(err, errlen, "bad ownership or modes for file %s", - buf); - return -1; - } - - /* for each component of the canonical path, walking upwards */ - for (;;) { - if ((cp = dirname(buf)) == NULL) { - snprintf(err, errlen, "dirname() failed"); - return -1; - } - strlcpy(buf, cp, sizeof(buf)); - - if (stat(buf, &st) < 0 || - (!platform_sys_dir_uid(st.st_uid) && st.st_uid != uid) || - (st.st_mode & 022) != 0) { - snprintf(err, errlen, - "bad ownership or modes for directory %s", buf); - return -1; - } - - /* If are past the homedir then we can stop */ - if (comparehome && strcmp(homedir, buf) == 0) - break; - - /* - * dirname should always complete with a "/" path, - * but we can be paranoid and check for "." too - */ - if ((strcmp("/", buf) == 0) || (strcmp(".", buf) == 0)) - break; - } - return 0; -} - static void usage(void) { @@ -192,9 +136,9 @@ if (mode == 1) safely_chroot(path, getuid()); else if (mode == 2) { - if (stat(path, &st) < 0) + if (stat(path, &st) == -1) fatal("Could not stat %s: %s", path, strerror(errno)); - if (auth_secure_path(path, &st, NULL, 0, + if (safe_path(path, &st, NULL, 0, errmsg, sizeof(errmsg)) != 0) fatal("Unsafe %s: %s", path, errmsg); } else { diff -ruN openssh-9.4p1/regress/cipher-speed.sh openssh-9.4p1+x509-14.2.1/regress/cipher-speed.sh --- openssh-9.4p1/regress/cipher-speed.sh 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/cipher-speed.sh 2023-08-20 10:07:00.000000000 +0300 @@ -3,13 +3,14 @@ tid="cipher speed" +ciphers=`$SSH -Q cipher` +macs=`$SSH -Q mac` + # Enable all supported ciphers and macs. -ciphers=`${SSH} -Q Ciphers | tr '\n' , | sed 's/,$//'` -macs=`${SSH} -Q MACs | tr '\n' , | sed 's/,$//'` -cat >>$OBJ/sshd_proxy <>$OBJ/sshd_proxy <&2 start_sshd @@ -14,15 +12,17 @@ cast128-cbc blowfish 3des-cbc ; do verbose "$tid: cipher $c" rm -f ${COPY} - # XXX the 2nd "cat" seems to be needed because of buggy FD handling - # in conch - ${CONCH} --identity $OBJ/ssh-rsa --port $PORT --user $USER -e none \ + ${CONCH} --identity $OBJ/ssh-rsa_pem --port $PORT --user $USER -e none \ --known-hosts $OBJ/known_hosts --notty --noagent --nox11 -n \ - 127.0.0.1 "cat ${DATA}" 2>/dev/null | cat > ${COPY} + 127.0.0.1 "cat ${DATA}" > ${COPY} if [ $? -ne 0 ]; then fail "ssh cat $DATA failed" + continue fi cmp ${DATA} ${COPY} || fail "corrupted copy" done + +stop_sshd + rm -f ${COPY} diff -ruN openssh-9.4p1/regress/connection-timeout.sh openssh-9.4p1+x509-14.2.1/regress/connection-timeout.sh --- openssh-9.4p1/regress/connection-timeout.sh 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/connection-timeout.sh 2023-08-20 10:07:00.000000000 +0300 @@ -2,20 +2,47 @@ # Placed in the Public Domain. tid="unused connection timeout" -if config_defined DISABLE_FD_PASSING ; then - skip "not supported on this platform" -fi -CTL=$OBJ/ctl-sock -cp $OBJ/sshd_proxy $OBJ/sshd_proxy.orig +WAIT_SECONDS=20 +make_tmpdir +CTL=$SSH_REGRESS_TMP/ctl-sock + +wait_for_process_to_exit() { + _pid=$1 + _n=0 + while kill -0 $_pid 2>/dev/null ; do + test $_n -eq 1 && trace "waiting for $_pid to exit" + _n=`expr $_n + 1` + test $_n -ge $WAIT_SECONDS && return 1 + sleep 1 + done + return 0 +} -check_ssh() { - test -S $CTL || return 1 - if ! ${REAL_SSH} -qF$OBJ/ssh_proxy -O check \ - -oControlPath=$CTL somehost >/dev/null 2>&1 ; then - return 1 +mux_cmd() { + $REAL_SSH -q -F $OBJ/ssh_proxy -S $CTL -O $1 somehost 2>&1 +} + +mux_exit() { + _sshpid=`mux_cmd check | cut -f 2 -d = | cut -f 1 -d ')'` + r=$? + test $r -ne 0 && return $r + test -z "$_sshpid" && return 0 + mux_cmd exit >/dev/null + r=$? + if test $r -ne 0 ; then + fatal "ssh process did not respond to close" fi - return 0 + wait_for_process_to_exit $_sshpid + r=$? + if test $r -ne 0 ; then + fatal "ssh process did not exit" + fi + return $r +} + +check_ssh() { + mux_cmd check >/dev/null } start_ssh() { @@ -24,33 +51,23 @@ -oControlMaster=yes -oControlPath=$CTL somehost r=$? test $r -eq 0 || fatal "failed to start ssh $r" - check_ssh || fatal "ssh process unresponsive" + check_ssh + r=$? + test $r -eq 0 || fatal "ssh process unresponsive" } stop_ssh() { - test -S $CTL || return - check_ssh || fatal "ssh process is unresponsive: cannot close" - if ! ${REAL_SSH} -qF$OBJ/ssh_proxy -O exit \ - -oControlPath=$CTL >/dev/null somehost >/dev/null ; then - fatal "ssh process did not respond to close" - fi - n=0 - while [ "$n" -lt 20 ] ; do - test -S $CTL || break - sleep 1 - n=`expr $n + 1` - done - if test -S $CTL ; then - fatal "ssh process did not exit" - fi + mux_exit } trap "stop_ssh" EXIT +cp $OBJ/sshd_proxy $OBJ/sshd_proxy.orig + verbose "no timeout" start_ssh sleep 5 -check_ssh || fatal "ssh unexpectedly missing" +check_ssh || fail "ssh unexpectedly missing" stop_ssh (cat $OBJ/sshd_proxy.orig ; echo "UnusedConnectionTimeout 2") > $OBJ/sshd_proxy @@ -62,13 +79,13 @@ stop_ssh verbose "session inhibits timeout" -rm -f $OBJ/copy.1 +rm -f $OBJ/copy2 start_ssh ${REAL_SSH} -qoControlPath=$CTL -oControlMaster=no -Fnone somehost \ - "sleep 8; touch $OBJ/copy.1" & + "sleep 8; touch $OBJ/copy2" & check_ssh || fail "ssh unexpectedly missing" wait -test -f $OBJ/copy.1 || fail "missing result file" +test -f $OBJ/copy2 || fail "missing result file" verbose "timeout after session" # Session should still be running from previous diff -ruN openssh-9.4p1/regress/connect-privsep.sh openssh-9.4p1+x509-14.2.1/regress/connect-privsep.sh --- openssh-9.4p1/regress/connect-privsep.sh 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/connect-privsep.sh 2023-08-20 10:07:00.000000000 +0300 @@ -6,6 +6,7 @@ cp $OBJ/sshd_proxy $OBJ/sshd_proxy.orig echo 'UsePrivilegeSeparation yes' >> $OBJ/sshd_proxy +echo "= UsePrivilegeSeparation yes" >> $TEST_SSH_LOGFILE ${SSH} -F $OBJ/ssh_proxy 999.999.999.999 true if [ $? -ne 0 ]; then fail "ssh privsep+proxyconnect failed" @@ -14,6 +15,7 @@ cp $OBJ/sshd_proxy.orig $OBJ/sshd_proxy echo 'UsePrivilegeSeparation sandbox' >> $OBJ/sshd_proxy +echo "= UsePrivilegeSeparation sandbox" >> $TEST_SSH_LOGFILE ${SSH} -F $OBJ/ssh_proxy 999.999.999.999 true if [ $? -ne 0 ]; then fail "ssh privsep/sandbox+proxyconnect failed" @@ -26,6 +28,8 @@ else mopts=`echo $TEST_MALLOC_OPTIONS | sed 's/./& /g'` fi +# Skip tests as tested malloc options are OpenBSD specific. +: || \ for m in '' $mopts ; do env MALLOC_OPTIONS="$m" ${SSH} -F $OBJ/ssh_proxy 999.999.999.999 true if [ $? -ne 0 ]; then diff -ruN openssh-9.4p1/regress/dhgex.sh openssh-9.4p1+x509-14.2.1/regress/dhgex.sh --- openssh-9.4p1/regress/dhgex.sh 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/dhgex.sh 2023-08-20 10:07:00.000000000 +0300 @@ -1,4 +1,4 @@ -# $OpenBSD: dhgex.sh,v 1.8 2023/03/02 08:14:52 dtucker Exp $ +# $OpenBSD: dhgex.sh,v 1.7 2020/12/21 22:48:41 dtucker Exp $ # Placed in the Public Domain. tid="dhgex" @@ -24,15 +24,15 @@ max=8192 groupsz="$min<$bits<$max" verbose "$tid bits $bits $kex $cipher" - ${SSH} ${opts} $@ -vvv -F ${OBJ}/ssh_proxy somehost true + $SSH $opts ${1+"$@"} -vvv -F $OBJ/ssh_proxy somehost true if [ $? -ne 0 ]; then fail "ssh failed ($@)" fi # check what we request - grep "SSH2_MSG_KEX_DH_GEX_REQUEST($groupsz) sent" ${LOG} >/dev/null + grep "SSH2_MSG_KEX_DH_GEX_REQUEST sent: $groupsz" ${LOG} >/dev/null if [ $? != 0 ]; then - got="`egrep 'SSH2_MSG_KEX_DH_GEX_REQUEST(.*) sent' ${LOG}`" - fail "$tid unexpected GEX sizes, expected $groupsz, got '$got'" + got=`egrep "SSH2_MSG_KEX_DH_GEX_REQUEST sent: (.*)" ${LOG}` + fail "$tid unexpected GEX sizes, expected $groupsz, got $got" fi # check what we got. gotbits="`awk 'BEGIN{FS="/"}/bits set:/{print $2}' ${LOG} | @@ -47,7 +47,7 @@ { bits="$1"; shift - for c in $@; do + for c in ${1+"$@"} ; do for k in $kexs; do ssh_test_dhgex $bits $c $k done diff -ruN openssh-9.4p1/regress/dynamic-forward.sh openssh-9.4p1+x509-14.2.1/regress/dynamic-forward.sh --- openssh-9.4p1/regress/dynamic-forward.sh 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/dynamic-forward.sh 2023-08-20 10:07:00.000000000 +0300 @@ -3,17 +3,56 @@ tid="dynamic forwarding" -# This is a reasonable proxy for IPv6 support. +FWDPORT=`expr $PORT + 1` + +cp $OBJ/ssh_config $OBJ/ssh_config.orig + +proxycmd="$OBJ/netcat -x 127.0.0.1:$FWDPORT -X" + +SKIP_IPV6=false if ! config_defined HAVE_STRUCT_IN6_ADDR ; then - SKIP_IPV6=yes + SKIP_IPV6=true fi -FWDPORT=`expr $PORT + 1` +WAIT_SECONDS=20 make_tmpdir CTL=${SSH_REGRESS_TMP}/ctl-sock -cp $OBJ/ssh_config $OBJ/ssh_config.orig -proxycmd="$OBJ/netcat -x 127.0.0.1:$FWDPORT -X" -trace "will use ProxyCommand $proxycmd" + +wait_for_process_to_exit() { + _pid=$1 + _n=0 + while kill -0 $_pid 2>/dev/null ; do + test $_n -eq 1 && trace "waiting for $_pid to exit" + _n=`expr $_n + 1` + test $_n -ge $WAIT_SECONDS && return 1 + sleep 1 + done + return 0 +} + +mux_cmd() { + $REAL_SSH -q -F $OBJ/ssh_proxy -S $CTL -O $1 somehost 2>&1 +} + +mux_exit() { + _sshpid=`mux_cmd check | cut -f 2 -d = | cut -f 1 -d ')'` + r=$? + test $r -ne 0 && return $r + test -z "$_sshpid" && return 0 + mux_cmd exit + r=$? + if test $r -ne 0 ; then + fatal "forwarding ssh process did not respond to close" + return $r + fi + wait_for_process_to_exit $_sshpid + r=$? + if test $r -ne 0 ; then + fatal "forwarding ssh process did not exit" + fi + return $r +} + start_ssh() { direction="$1" @@ -22,57 +61,54 @@ error="1" trace "start dynamic -$direction forwarding, fork to background" (cat $OBJ/ssh_config.orig ; echo "$arg") > $OBJ/ssh_config - ${REAL_SSH} -vvvnNfF $OBJ/ssh_config -E$TEST_SSH_LOGFILE \ + $REAL_SSH -nN -F $OBJ/ssh_config -f -vvvv -E$TEST_SSH_LOGFILE \ -$direction $FWDPORT -oExitOnForwardFailure=yes \ -oControlMaster=yes -oControlPath=$CTL somehost r=$? test $r -eq 0 || fatal "failed to start dynamic forwarding $r" - if ! ${REAL_SSH} -qF$OBJ/ssh_config -O check \ - -oControlPath=$CTL somehost >/dev/null 2>&1 ; then - fatal "forwarding ssh process unresponsive" - fi + mux_cmd check >/dev/null + r=$? + test $r -ne 0 && fatal "forwarding ssh process unresponsive" + return $r } stop_ssh() { - test -S $CTL || return - if ! ${REAL_SSH} -qF$OBJ/ssh_config -O exit \ - -oControlPath=$CTL >/dev/null somehost >/dev/null ; then - fatal "forwarding ssh process did not respond to close" - fi - n=0 - while [ "$n" -lt 20 ] ; do - test -S $CTL || break - sleep 1 - n=`expr $n + 1` - done - if test -S $CTL ; then - fatal "forwarding ssh process did not exit" - fi + mux_exit } check_socks() { - direction=$1 - expect_success=$2 + direction="$1" + expect_success="$2" for s in 4 5; do for h in 127.0.0.1 localhost; do trace "testing ssh socks version $s host $h (-$direction)" - ${REAL_SSH} -q -F $OBJ/ssh_config \ + $REAL_SSH -q -F $OBJ/ssh_config \ -o "ProxyCommand ${proxycmd}${s} $h $PORT 2>/dev/null" \ somehost cat ${DATA} > ${COPY} r=$? - if [ "x$expect_success" = "xY" ] ; then - if [ $r -ne 0 ] ; then - fail "ssh failed with exit status $r" + if test "x$expect_success" = "xN" ; then + if test $r -eq 0 ; then + fail "ssh unexpectedly succeeded" + r=33 fi - test -f ${COPY} || fail "failed copy ${DATA}" - cmp ${DATA} ${COPY} || fail "corrupted copy of ${DATA}" - elif [ $r -eq 0 ] ; then - fail "ssh unexpectedly succeeded" + return $r fi + if test $r -ne 0 ; then + fail "ssh failed with exit status $r" + return $r + fi + test -f ${COPY} || fail "failed copy ${DATA}" + cmp ${DATA} ${COPY} || fail "corrupted copy of ${DATA}" done done } +gen_permit_argument() { + permit="127.0.0.1:$1" + $SKIP_IPV6 || permit="$permit [::1]:$1" + permit="$permit localhost:$1" +} + start_sshd trap "stop_ssh" EXIT @@ -82,7 +118,7 @@ check_socks $d Y stop_ssh test "x$d" = "xR" || continue - + # Test PermitRemoteOpen verbose "PermitRemoteOpen=any" start_ssh $d PermitRemoteOpen=any @@ -95,15 +131,13 @@ stop_ssh verbose "PermitRemoteOpen=explicit" - permit="127.0.0.1:$PORT [::1]:$PORT localhost:$PORT" - test -z "$SKIP_IPV6" || permit="127.0.0.1:$PORT localhost:$PORT" + gen_permit_argument $PORT start_ssh $d PermitRemoteOpen="$permit" check_socks $d Y stop_ssh verbose "PermitRemoteOpen=disallowed" - permit="127.0.0.1:1 [::1]:1 localhost:1" - test -z "$SKIP_IPV6" || permit="127.0.0.1:1 localhost:1" + gen_permit_argument 1 start_ssh $d PermitRemoteOpen="$permit" check_socks $d N stop_ssh diff -ruN openssh-9.4p1/regress/envpass.sh openssh-9.4p1+x509-14.2.1/regress/envpass.sh --- openssh-9.4p1/regress/envpass.sh 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/envpass.sh 2023-08-20 10:07:00.000000000 +0300 @@ -5,9 +5,9 @@ # NB accepted env vars are in test-exec.sh (_XXX_TEST_* and _XXX_TEST) -# Prepare a custom config to test for a configuration parsing bug fixed in 4.0 +# Prepare a custom config to test configuration parsing in addition cat << EOF > $OBJ/ssh_proxy_envpass -Host test-sendenv-confparse-bug +Host test-sendenv-envpass SendEnv * EOF cat $OBJ/ssh_proxy >> $OBJ/ssh_proxy_envpass @@ -63,7 +63,7 @@ _XXX_TEST_A=1 _XXX_TEST_B=2 ${SSH} -oSendEnv="_XXX_TEST_*" \ -F $OBJ/ssh_proxy_envpass otherhost \ sh << 'EOF' - test X"$_XXX_TEST_A" = X"1" -a X"$_XXX_TEST_B" = X"2" + test X"$_XXX_TEST_A" = X"1" && test X"$_XXX_TEST_B" = X"2" EOF r=$? if [ $r -ne 0 ]; then @@ -75,7 +75,7 @@ ${SSH} -F $OBJ/ssh_proxy_envpass \ -oSetEnv="_XXX_TEST_A=1 _XXX_TEST_B=2" otherhost \ sh << 'EOF' - test X"$_XXX_TEST_A" = X"1" -a X"$_XXX_TEST_B" = X"2" + test X"$_XXX_TEST_A" = X"1" && test X"$_XXX_TEST_B" = X"2" EOF r=$? if [ $r -ne 0 ]; then @@ -84,9 +84,10 @@ trace "setenv, first match wins" verbose "test $tid: setenv, first match wins" ${SSH} -F $OBJ/ssh_proxy_envpass \ - -oSetEnv="_XXX_TEST_A=1 _XXX_TEST_A=11 _XXX_TEST_B=2" otherhost \ + -oSetEnv="_XXX_TEST_A=1 _XXX_TEST_A=11 _XXX_TEST_B=2" \ + -oSetEnv="_XXX_TEST_B=22" otherhost \ sh << 'EOF' - test X"$_XXX_TEST_A" = X"1" -a X"$_XXX_TEST_B" = X"2" + test X"$_XXX_TEST_A" = X"1" && test X"$_XXX_TEST_B" = X"2" EOF r=$? if [ $r -ne 0 ]; then @@ -100,7 +101,7 @@ ${SSH} -F $OBJ/ssh_proxy_envpass \ -oSetEnv="_XXX_TEST_A=1 _XXX_TEST_B=2" otherhost \ sh << 'EOF' - test X"$_XXX_TEST_A" = X"23" -a X"$_XXX_TEST_B" = X"2" + test X"$_XXX_TEST_A" = X"23" && test X"$_XXX_TEST_B" = X"2" EOF r=$? if [ $r -ne 0 ]; then @@ -111,10 +112,11 @@ verbose "test $tid: server setenv wins" cp $OBJ/sshd_proxy_bak $OBJ/sshd_proxy echo "SetEnv _XXX_TEST_A=23 _XXX_TEST_A=42" >> $OBJ/sshd_proxy +echo "SetEnv _XXX_TEST_B=43" >> $OBJ/sshd_proxy ${SSH} -F $OBJ/ssh_proxy_envpass \ -oSetEnv="_XXX_TEST_A=1 _XXX_TEST_B=2" otherhost \ sh << 'EOF' - test X"$_XXX_TEST_A" = X"23" -a X"$_XXX_TEST_B" = X"2" + test X"$_XXX_TEST_A" = X"23" && test X"$_XXX_TEST_B" = X"43" EOF r=$? if [ $r -ne 0 ]; then diff -ruN openssh-9.4p1/regress/exit-status-signal.sh openssh-9.4p1+x509-14.2.1/regress/exit-status-signal.sh --- openssh-9.4p1/regress/exit-status-signal.sh 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/exit-status-signal.sh 2023-08-20 10:07:00.000000000 +0300 @@ -2,23 +2,28 @@ tid="exit status on signal" +pidfile=$OBJ/remote_pid + # spawn client in background -rm -f $OBJ/remote_pid -${SSH} -F $OBJ/ssh_proxy somehost 'echo $$ >'$OBJ'/remote_pid; sleep 444' & -ssh_pid=$! +rm -f $pidfile +$SSH -F $OBJ/ssh_proxy somehost 'echo $$ >'$pidfile'; sleep 444' & +client_pid=$! # wait for it to start -n=20 -while [ ! -f $OBJ/remote_pid ] && [ $n -gt 0 ]; do - n=$(($n - 1)) +n=0 +while test ! -f $pidfile ; do sleep 1 + n=`expr $n + 1` + if test $n -gt 60; then + kill $client_pid + fatal "timeout waiting for background ssh" + fi done -kill $ssh_pid -wait $ssh_pid +kill $client_pid +wait $client_pid exit_code=$? -if [ $exit_code -eq 0 ]; then +if test $exit_code -eq 0 ; then fail "ssh client should fail on signal" fi - diff -ruN openssh-9.4p1/regress/fips-connect-privsep.sh openssh-9.4p1+x509-14.2.1/regress/fips-connect-privsep.sh --- openssh-9.4p1/regress/fips-connect-privsep.sh 1970-01-01 02:00:00.000000000 +0200 +++ openssh-9.4p1+x509-14.2.1/regress/fips-connect-privsep.sh 2023-08-20 10:07:00.000000000 +0300 @@ -0,0 +1,27 @@ +# Placed in the Public Domain. + +tid="proxy connect with privsep in FIPS mode" + +if test -z "$OPENSSL_FIPS" ; then + fail "test is not run in FIPS environment" +fi + + +verbose "privilege separation: enabled" +cp $OBJ/sshd_proxy $OBJ/sshd_proxy.orig +echo 'UsePrivilegeSeparation yes' >> $OBJ/sshd_proxy +echo "= UsePrivilegeSeparation yes" >> $TEST_SSH_LOGFILE +$SSH -F $OBJ/ssh_proxy 999.999.999.999 : +if test $? -ne 0; then + fail "ssh privsep+proxyconnect failed" +fi + + +verbose "privilege separation: sandbox" +cp $OBJ/sshd_proxy.orig $OBJ/sshd_proxy +echo 'UsePrivilegeSeparation sandbox' >> $OBJ/sshd_proxy +echo "= UsePrivilegeSeparation sandbox" >> $TEST_SSH_LOGFILE +$SSH -F $OBJ/ssh_proxy 999.999.999.999 : +if test $? -ne 0; then + fail "ssh sandbox+proxyconnect failed" +fi diff -ruN openssh-9.4p1/regress/fips-try-ciphers.sh openssh-9.4p1+x509-14.2.1/regress/fips-try-ciphers.sh --- openssh-9.4p1/regress/fips-try-ciphers.sh 1970-01-01 02:00:00.000000000 +0200 +++ openssh-9.4p1+x509-14.2.1/regress/fips-try-ciphers.sh 2023-08-20 10:07:00.000000000 +0300 @@ -0,0 +1,77 @@ +# Placed in the Public Domain. + +tid="try ciphers in FIPS mode" + +if test -z "$OPENSSL_FIPS" ; then + fail "test is not run in FIPS environment" +fi + + +fips_ciphers=`$SSH -Q cipher` +other_ciphers= +for v in `unset OPENSSL_FIPS; $SSH -Q cipher` ; do + for f in $fips_ciphers ''; do + test "x$v" = "x$f" && break + done + test -z "$f" && other_ciphers="$other_ciphers $v" +done + +fips_macs=`$SSH -Q mac` +other_macs= +for v in `unset OPENSSL_FIPS; $SSH -Q mac` ; do + for f in $fips_macs ''; do + test "x$v" = "x$f" && break + done + test -z "$f" && other_macs="$other_macs $v" +done + + +cp $OBJ/sshd_proxy $OBJ/sshd_proxy_bak + +update_sshd_proxy() { + cp $OBJ/sshd_proxy_bak $OBJ/sshd_proxy + echo "Ciphers=$1" >> $OBJ/sshd_proxy + echo "MACs=$2" >> $OBJ/sshd_proxy +} + + +for c in $fips_ciphers; do + for m in $fips_macs; do + msg="fips-cipher $c fips-mac $m" + trace "$msg" + verbose "test $tid: $msg" + update_sshd_proxy $c $m + $SSH -F $OBJ/ssh_proxy -m $m -c $c somehost : + if test 0 -ne $?; then + fail "ssh failed with mac $m cipher $c" + fi + done +done + +# non-fips mac should fail +for c in $fips_ciphers; do + for m in $other_macs; do + msg="fips-cipher $c mac $m" + trace "$msg" + verbose "negative test $tid: $msg" + update_sshd_proxy $c $m + $SSH -F $OBJ/ssh_proxy -m $m -c $c somehost : >>$TEST_SSH_LOGFILE 2>&1 + if test 0 -eq $?; then + fail "ssh succeeded with mac $m cipher $c - nok" + fi + done +done + +# non-fips cipher should fail +for c in $other_ciphers; do + for m in $fips_macs $other_macs; do + msg="cipher $c mac $m" + trace "$msg" + verbose "negative test $tid: $msg" + update_sshd_proxy $c $m + $SSH -F $OBJ/ssh_proxy -m $m -c $c somehost : >>$TEST_SSH_LOGFILE 2>&1 + if test 0 -eq $?; then + fail "ssh succeeded with mac $m cipher $c - nok" + fi + done +done diff -ruN openssh-9.4p1/regress/forward-control.sh openssh-9.4p1+x509-14.2.1/regress/forward-control.sh --- openssh-9.4p1/regress/forward-control.sh 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/forward-control.sh 2023-08-20 10:07:00.000000000 +0300 @@ -5,8 +5,9 @@ LFWD_PORT=3320 RFWD_PORT=3321 -CTL=$OBJ/ctl-sock WAIT_SECONDS=20 +make_tmpdir +CTL="$SSH_REGRESS_TMP"/ctl-sock wait_for_process_to_exit() { _pid=$1 @@ -21,11 +22,13 @@ } mux_cmd() { - ${SSH} -F $OBJ/ssh_proxy -S $CTL -O $1 host 2>&1 + $SSH -F $OBJ/ssh_proxy -S $CTL -O $1 host 2>&1 } -controlmaster_pid() { - mux_cmd check | cut -f2 -d= | cut -f1 -d')' +mux_exit() { + _sshpid=`mux_cmd check | cut -f 2 -d = | cut -f 1 -d ')'` + mux_cmd exit >/dev/null + wait_for_process_to_exit $_sshpid } # usage: check_lfwd Y|N message @@ -41,9 +44,7 @@ ${SSH} -F $OBJ/ssh_config -p $LFWD_PORT \ -oConnectionAttempts=10 host true >/dev/null 2>&1 _result=$? - _sshpid=`controlmaster_pid` - mux_cmd exit >/dev/null - wait_for_process_to_exit $_sshpid + mux_exit if test "x$_expected" = "xY" -a $_result -ne 0 ; then fail "check_lfwd failed (expecting success): $_message" elif test "x$_expected" = "xN" -a $_result -eq 0 ; then @@ -66,13 +67,11 @@ -Nf host mux_cmd check >/dev/null _result=$? - _sshpid=`controlmaster_pid` - if test $_result -eq 0; then + if test $_result -eq 0 ; then ${SSH} -F $OBJ/ssh_config -p $RFWD_PORT \ -oConnectionAttempts=10 host true >/dev/null 2>&1 _result=$? - mux_cmd exit >/dev/null - wait_for_process_to_exit $_sshpid + mux_exit fi if test "x$_expected" = "xY" -a $_result -ne 0 ; then fail "check_rfwd failed (expecting success): $_message" @@ -225,4 +224,3 @@ rperm_tests local Y N Y N Y N rperm_tests remote N Y N N N Y rperm_tests no N N N N N N - diff -ruN openssh-9.4p1/regress/forwarding.sh openssh-9.4p1+x509-14.2.1/regress/forwarding.sh --- openssh-9.4p1/regress/forwarding.sh 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/forwarding.sh 2023-08-20 10:07:00.000000000 +0300 @@ -11,7 +11,7 @@ last=$PORT fwd="" make_tmpdir -CTL=${SSH_REGRESS_TMP}/ctl-sock +CTL="$SSH_REGRESS_TMP"/ctl-sock for j in 0 1 2; do for i in 0 1 2; do @@ -29,7 +29,7 @@ ${SSH} -S $CTL -N -M -F $OBJ/ssh_config -f $fwd somehost trace "transfer over forwarded channels and check result" -${SSH} -F $OBJ/ssh_config -p$last -o 'ConnectionAttempts=10' \ +${SSH} -F $OBJ/ssh_config -p$last -oConnectionAttempts=10 \ somehost cat ${DATA} > ${COPY} test -s ${COPY} || fail "failed copy of ${DATA}" cmp ${DATA} ${COPY} || fail "corrupted copy of ${DATA}" @@ -75,8 +75,7 @@ fail "connection failed with cleared local forwarding" else # this one should fail - ${SSH} -F $OBJ/ssh_config -p ${base}01 somehost true \ - >>$TEST_REGRESS_LOGFILE 2>&1 && \ + $SSH -F $OBJ/ssh_config -p ${base}01 somehost true && \ fail "local forwarding not cleared" fi ${SSH} -F $OBJ/ssh_config -S $CTL -O exit somehost 2>/dev/null @@ -89,8 +88,7 @@ fail "connection failed with cleared remote forwarding" else # this one should fail - ${SSH} -F $OBJ/ssh_config -p ${base}01 somehost true \ - >>$TEST_REGRESS_LOGFILE 2>&1 && \ + $SSH -F $OBJ/ssh_config -p ${base}01 somehost true && \ fail "remote forwarding not cleared" fi ${SSH} -F $OBJ/ssh_config -S $CTL -O exit somehost 2>/dev/null @@ -110,7 +108,7 @@ ${SSH} -S $CTL -N -M -F $OBJ/ssh_config -f somehost trace "config file: transfer over forwarded channels and check result" -${SSH} -F $OBJ/ssh_config -p${base}02 -o 'ConnectionAttempts=10' \ +${SSH} -F $OBJ/ssh_config -p${base}02 -oConnectionAttempts=10 \ somehost cat ${DATA} > ${COPY} test -s ${COPY} || fail "failed copy of ${DATA}" cmp ${DATA} ${COPY} || fail "corrupted copy of ${DATA}" @@ -124,7 +122,7 @@ ${SSH} -S $CTL.1 -N -M -f -F $OBJ/ssh_config -L[$OBJ/unix-1.fwd]:[$OBJ/unix-2.fwd] somehost ${SSH} -S $CTL.2 -N -M -f -F $OBJ/ssh_config -R[$OBJ/unix-2.fwd]:[$OBJ/unix-3.fwd] somehost ${SSH} -S $CTL.3 -N -M -f -F $OBJ/ssh_config -L[$OBJ/unix-3.fwd]:127.0.0.1:$PORT somehost -${SSH} -F $OBJ/ssh_config -p${base}01 -o 'ConnectionAttempts=10' \ +${SSH} -F $OBJ/ssh_config -p${base}01 -oConnectionAttempts=10 \ somehost cat ${DATA} > ${COPY} test -s ${COPY} || fail "failed copy ${DATA}" cmp ${DATA} ${COPY} || fail "corrupted copy of ${DATA}" diff -ruN openssh-9.4p1/regress/hostbased.sh openssh-9.4p1+x509-14.2.1/regress/hostbased.sh --- openssh-9.4p1/regress/hostbased.sh 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/hostbased.sh 2023-08-20 10:07:00.000000000 +0300 @@ -1,66 +1,67 @@ -# $OpenBSD: hostbased.sh,v 1.4 2022/12/07 11:45:43 dtucker Exp $ +# $OpenBSD: hostbased.sh,v 1.3 2022/01/08 07:55:26 dtucker Exp $ # Placed in the Public Domain. -# This test requires external setup and thus is skipped unless -# TEST_SSH_HOSTBASED_AUTH and SUDO are set to "yes". -# Since ssh-keysign has key paths hard coded, unlike the other tests it -# needs to use the real host keys. It requires: -# - ssh-keysign must be installed and setuid. -# - "EnableSSHKeysign yes" must be in the system ssh_config. -# - the system's own real FQDN the system-wide shosts.equiv. -# - the system's real public key fingerprints must be in global ssh_known_hosts. -# +# Since helper for host-based authentication uses keys with hard coded +# paths, unlike the other tests it needs to use the real host keys. +# In addition host-based requires: +# - helper(ssh-keysign) must be installed and setuid root. +# - "EnableSSHKeysign yes" must be in the system client configuration. +# - host and user accepted by system-wide shosts.equiv. +# - host public key listed in known hosts files. + tid="hostbased" -if [ -z "${TEST_SSH_HOSTBASED_AUTH}" ]; then - skip "TEST_SSH_HOSTBASED_AUTH not set." -elif [ -z "${SUDO}" ]; then +if test -z "$SUDO" ; then skip "SUDO not set" fi -# Enable all supported hostkey algos (but no others) -hostkeyalgos=`${SSH} -Q HostKeyAlgorithms | tr '\n' , | sed 's/,$//'` - +cp $OBJ/sshd_proxy $OBJ/sshd_proxy_orig +grep -vi hostkey $OBJ/sshd_proxy_orig > $OBJ/sshd_proxy cat >>$OBJ/sshd_proxy < $OBJ/ssh_proxy cat >>$OBJ/ssh_proxy </dev/null`" in 256*ECDSA*) algos="$algos ecdsa-sha2-nistp256" ;; 384*ECDSA*) algos="$algos ecdsa-sha2-nistp384" ;; 521*ECDSA*) algos="$algos ecdsa-sha2-nistp521" ;; *RSA*) algos="$algos ssh-rsa rsa-sha2-256 rsa-sha2-512" ;; *ED25519*) algos="$algos ssh-ed25519" ;; *DSA*) algos="$algos ssh-dss" ;; - *) verbose "unknown host key type $key" ;; + *) verbose "unknown host key $key" + continue;; esac + echo "HostKey $key" >> $OBJ/sshd_proxy done +test -z "$algos" && fail "no default host-keys" for algo in $algos; do trace "hostbased algo $algo" opts="-F $OBJ/ssh_proxy" - if [ "x$algo" != "xdefault" ]; then - opts="$opts -oHostbasedAcceptedAlgorithms=$algo" - fi - SSH_CONNECTION=`${SSH} $opts localhost 'echo $SSH_CONNECTION'` - if [ $? -ne 0 ]; then + opts="$opts -oHostbasedAcceptedAlgorithms=$algo" + SSH_CONNECTION=`$SSH $opts localhost 'echo $SSH_CONNECTION'` + if test $? -ne 0 ; then fail "connect failed, hostbased algo $algo" - elif [ "$SSH_CONNECTION" != "UNKNOWN 65535 UNKNOWN 65535" ]; then + elif test "x$SSH_CONNECTION" != "xUNKNOWN 65535 UNKNOWN 65535" ; then fail "hostbased algo $algo bad SSH_CONNECTION" \ "$SSH_CONNECTION" else - verbose "ok hostbased algo $algo" + verbose "ok hostbased $algo" fi done diff -ruN openssh-9.4p1/regress/hostkey-agent.sh openssh-9.4p1+x509-14.2.1/regress/hostkey-agent.sh --- openssh-9.4p1/regress/hostkey-agent.sh 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/hostkey-agent.sh 2023-08-20 10:07:00.000000000 +0300 @@ -2,8 +2,9 @@ # Placed in the Public Domain. tid="hostkey agent" +PLAIN_TYPES=`echo "$SSH_HOSTKEY_TYPES" | sed 's/ssh-xmss@openssh.com//'` # TODO -rm -f $OBJ/agent-key.* $OBJ/ssh_proxy.orig $OBJ/known_hosts.orig $OBJ/agent-ca* +rm -f $OBJ/agent-key.* $OBJ/ssh_proxy.orig $OBJ/agent-ca $OBJ/agent-ca.pub trace "start agent" eval `${SSHAGENT} ${EXTRA_AGENT_ARGS} -s` > /dev/null @@ -18,7 +19,7 @@ ${SSHKEYGEN} -qt ed25519 -f $OBJ/agent-ca -N '' || fatal "ssh-keygen CA" trace "load hostkeys" -for k in $SSH_KEYTYPES ; do +for k in $PLAIN_TYPES ; do ${SSHKEYGEN} -qt $k -f $OBJ/agent-key.$k -N '' || fatal "ssh-keygen $k" ${SSHKEYGEN} -s $OBJ/agent-ca -qh -n localhost-with-alias \ -I localhost-with-alias $OBJ/agent-key.$k.pub || \ @@ -32,9 +33,11 @@ unset SSH_AUTH_SOCK -for k in $SSH_KEYTYPES ; do - verbose "key type $k" +for ps in $SSHD_PRIVSEP ; do +for k in $PLAIN_TYPES ; do + verbose "key type $k privsep=$ps" cp $OBJ/sshd_proxy.orig $OBJ/sshd_proxy + echo "UsePrivilegeSeparation $ps" >> $OBJ/sshd_proxy echo "HostKeyAlgorithms $k" >> $OBJ/sshd_proxy echo "Hostkey $OBJ/agent-key.${k}" >> $OBJ/sshd_proxy opts="-oHostKeyAlgorithms=$k -F $OBJ/ssh_proxy" @@ -42,46 +45,57 @@ cat $OBJ/agent-key.$k.pub) > $OBJ/known_hosts SSH_CONNECTION=`${SSH} $opts host 'echo $SSH_CONNECTION'` if [ $? -ne 0 ]; then - fail "keytype $k failed" + fail "key type $k privsep=$ps failed" fi if [ "$SSH_CONNECTION" != "UNKNOWN 65535 UNKNOWN 65535" ]; then - fail "bad SSH_CONNECTION key type $k" + fail "bad SSH_CONNECTION key type $k privsep=$ps" fi done +done -SSH_CERTTYPES=`ssh -Q key-sig | grep 'cert-v01@openssh.com'` +SSH_CERTTYPES=`$SSH -Q key | grep 'cert-v01@openssh.com'` +SSH_CERTTYPES=`echo "$SSH_CERTTYPES" | sed 's/ssh-xmss-cert-v01@openssh.com//'` # TODO # Prepare sshd_proxy for certificates. cp $OBJ/sshd_proxy.orig $OBJ/sshd_proxy HOSTKEYALGS="" for k in $SSH_CERTTYPES ; do - test -z "$HOSTKEYALGS" || HOSTKEYALGS="${HOSTKEYALGS}," - HOSTKEYALGS="${HOSTKEYALGS}${k}" + if test -z "$HOSTKEYALGS" ; then + HOSTKEYALGS="$k" + else + HOSTKEYALGS="$HOSTKEYALGS,$k" + fi done -for k in $SSH_KEYTYPES ; do - echo "Hostkey $OBJ/agent-key.${k}.pub" >> $OBJ/sshd_proxy +for k in $PLAIN_TYPES ; do + echo "Hostkey $OBJ/agent-key.${k}" >> $OBJ/sshd_proxy echo "HostCertificate $OBJ/agent-key.${k}-cert.pub" >> $OBJ/sshd_proxy test -f $OBJ/agent-key.${k}.pub || fatal "no $k key" test -f $OBJ/agent-key.${k}-cert.pub || fatal "no $k cert" done echo "HostKeyAlgorithms $HOSTKEYALGS" >> $OBJ/sshd_proxy +cp $OBJ/sshd_proxy $OBJ/sshd_proxy.orig # Add only CA trust anchor to known_hosts. ( printf '@cert-authority localhost-with-alias ' ; cat $OBJ/agent-ca.pub) > $OBJ/known_hosts +for ps in $SSHD_PRIVSEP ; do for k in $SSH_CERTTYPES ; do - verbose "cert type $k" + verbose "cert type $k privsep=$ps" + cp $OBJ/sshd_proxy.orig $OBJ/sshd_proxy + echo "UsePrivilegeSeparation $ps" >> $OBJ/sshd_proxy opts="-oHostKeyAlgorithms=$k -F $OBJ/ssh_proxy" SSH_CONNECTION=`${SSH} $opts host 'echo $SSH_CONNECTION'` - if [ $? -ne 0 ]; then - fail "cert type $k failed" + if test $? -ne 0 ; then + fail "cert type $k privsep=$ps failed" fi - if [ "$SSH_CONNECTION" != "UNKNOWN 65535 UNKNOWN 65535" ]; then - fail "bad SSH_CONNECTION key type $k" + if test "$SSH_CONNECTION" != "UNKNOWN 65535 UNKNOWN 65535" ; then + fail "bad SSH_CONNECTION key type $k privsep=$ps" fi done +done trace "kill agent" ${SSHAGENT} -k > /dev/null +rm $OBJ/agent-ca.pub diff -ruN openssh-9.4p1/regress/hostkey-rotate.sh openssh-9.4p1+x509-14.2.1/regress/hostkey-rotate.sh --- openssh-9.4p1/regress/hostkey-rotate.sh 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/hostkey-rotate.sh 2023-08-20 10:07:00.000000000 +0300 @@ -26,9 +26,11 @@ grep -vi 'hostkey' $OBJ/sshd_proxy > $OBJ/sshd_proxy.orig mv $OBJ/ssh_proxy $OBJ/ssh_proxy.orig -grep -vi 'globalknownhostsfile' $OBJ/ssh_proxy.orig > $OBJ/ssh_proxy -echo "UpdateHostkeys=yes" >> $OBJ/ssh_proxy -echo "GlobalKnownHostsFile=none" >> $OBJ/ssh_proxy +( +grep -vi 'globalknownhostsfile' $OBJ/ssh_proxy.orig +echo "GlobalKnownHostsFile /dev/null" +echo "UpdateHostkeys yes" +) > $OBJ/ssh_proxy rm $OBJ/known_hosts # The "primary" key type is ed25519 since it's supported even when built @@ -39,25 +41,26 @@ trace "prepare hostkeys" nkeys=0 all_algs="" -for k in $SSH_HOSTKEY_TYPES; do - ${SSHKEYGEN} -qt $k -f $OBJ/hkr.$k -N '' || fatal "ssh-keygen $k" +for k in $SSH_HOSTKEY_TYPES ; do + keytype_compat $k + $SSHKEYGEN -q -N '' $keytype_val -f $OBJ/hkr.$k || fatal "ssh-keygen $k" echo "Hostkey $OBJ/hkr.${k}" >> $OBJ/sshd_proxy.orig nkeys=`expr $nkeys + 1` test "x$all_algs" = "x" || all_algs="${all_algs}," case "$k" in ssh-rsa) secondary="ssh-rsa" - all_algs="${all_algs}rsa-sha2-256,rsa-sha2-512,$k" - ;; - *) - all_algs="${all_algs}$k" + if config_defined HAVE_EVP_SHA256 ; then + all_algs="${all_algs}rsa-sha2-256,rsa-sha2-512," + fi ;; esac + all_algs="$all_algs$k" done dossh() { # All ssh should succeed in this test - ${SSH} -F $OBJ/ssh_proxy "$@" x true || fail "ssh $@ failed" + $SSH -F $OBJ/ssh_proxy ${1+"$@"} x true || fail "ssh $@ failed" } expect_nkeys() { @@ -91,16 +94,21 @@ dossh -oStrictHostKeyChecking=yes -oHostKeyAlgorithms=$all_algs # Check that other keys learned expect_nkeys $nkeys "learn hostkeys" -for k in $SSH_HOSTKEY_TYPES; do +for k in $SSH_HOSTKEY_TYPES ; do check_key_present $k || fail "didn't learn keytype $k" done # Check each key type -for k in $SSH_HOSTKEY_TYPES; do +for k in $SSH_HOSTKEY_TYPES ; do + alg= case "$k" in - ssh-rsa) alg="rsa-sha2-256,rsa-sha2-512,ssh-rsa" ;; - *) alg="$k" ;; + ssh-rsa) + if config_defined HAVE_EVP_SHA256 ; then + alg="rsa-sha2-256,rsa-sha2-512," + fi + ;; esac + alg="$alg$k" verbose "learn additional hostkeys, type=$k" dossh -oStrictHostKeyChecking=yes -oHostKeyAlgorithms=$alg,$all_algs expect_nkeys $nkeys "learn hostkeys $k" @@ -112,7 +120,8 @@ verbose "learn changed non-primary hostkey type=${secondary}" mv $OBJ/hkr.${secondary}.pub $OBJ/hkr.${secondary}.pub.old rm -f $OBJ/hkr.${secondary} - ${SSHKEYGEN} -qt ${secondary} -f $OBJ/hkr.${secondary} -N '' || \ + keytype_compat $secondary + $SSHKEYGEN -q -N '' $keytype_val -f $OBJ/hkr.$secondary || \ fatal "ssh-keygen $secondary" dossh -oStrictHostKeyChecking=yes -oHostKeyAlgorithms=$all_algs # Check that the key was replaced @@ -124,7 +133,8 @@ # Add new hostkey (primary type) to sshd and connect verbose "learn new primary hostkey" -${SSHKEYGEN} -qt ${primary} -f $OBJ/hkr.${primary}-new -N '' || fatal "ssh-keygen ed25519" +keytype_compat $primary +$SSHKEYGEN -q -N '' $keytype_val -f $OBJ/hkr.${primary}-new || fatal "ssh-keygen ed25519" ( cat $OBJ/sshd_proxy.orig ; echo HostKey $OBJ/hkr.${primary}-new ) \ > $OBJ/sshd_proxy # Check new hostkey added @@ -150,3 +160,5 @@ dossh -oStrictHostKeyChecking=yes -oHostKeyAlgorithms=${primary} expect_nkeys 1 "learn hostkeys" check_key_present ${primary} || fail "didn't learn changed key" + +rm -f $OBJ/known_hosts.old diff -ruN openssh-9.4p1/regress/integrity.sh openssh-9.4p1+x509-14.2.1/regress/integrity.sh --- openssh-9.4p1/regress/integrity.sh 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/integrity.sh 2023-08-20 10:07:00.000000000 +0300 @@ -1,4 +1,4 @@ -# $OpenBSD: integrity.sh,v 1.25 2023/03/01 09:29:32 dtucker Exp $ +# $OpenBSD: integrity.sh,v 1.24 2020/01/21 08:06:27 djm Exp $ # Placed in the Public Domain. tid="integrity" @@ -17,8 +17,10 @@ #echo "KexAlgorithms -diffie-hellman-group*" \ # >> $OBJ/ssh_proxy +SH=${TEST_SHELL-sh} + # sshd-command for proxy (see test-exec.sh) -cmd="$SUDO env SSH_SK_HELPER="$SSH_SK_HELPER" sh ${OBJ}/sshd-log-wrapper.sh -i -f $OBJ/sshd_proxy" +cmd="$SUDO $SH ${SRC}/sshd-log-wrapper.sh ${TEST_SSHD_LOGFILE} ${SSHD} -i -f $OBJ/sshd_proxy" for m in $macs; do trace "test $tid: mac $m" diff -ruN openssh-9.4p1/regress/keygen-comment.sh openssh-9.4p1+x509-14.2.1/regress/keygen-comment.sh --- openssh-9.4p1/regress/keygen-comment.sh 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/keygen-comment.sh 2023-08-20 10:07:00.000000000 +0300 @@ -4,49 +4,58 @@ S1="secret1" +if config_defined HAVE_EVP_SHA256 ; then +keygen_hash_opt=sha256 +keygen_hash_res="SHA256:(.){43}" +else +keygen_hash_opt=md5 +keygen_hash_res="MD5:(.){47}" +fi + check_fingerprint () { file="$1" comment="$2" trace "fingerprinting $file" - if ! ${SSHKEYGEN} -l -E sha256 -f $file > $OBJ/$t-fgp ; then + if ! $SSHKEYGEN -l -E $keygen_hash_opt -f $file > $OBJ/$t-fgp ; then fail "ssh-keygen -l failed for $t-key" fi - if ! egrep "^([0-9]+) SHA256:(.){43} ${comment} \(.*\)\$" \ + if ! egrep "^([0-9]+) "$keygen_hash_res" $comment \(.*\)\$" \ $OBJ/$t-fgp >/dev/null 2>&1 ; then fail "comment is not correctly recovered for $t-key" fi rm -f $OBJ/$t-fgp } -for fmt in '' RFC4716 PKCS8 PEM; do - for t in $SSH_KEYTYPES; do +for fmt in RFC4716 PKCS8 PEM OpenSSH ; do + for t in $SSH_KEYTYPES ; do trace "generating $t key in '$fmt' format" rm -f $OBJ/$t-key* - oldfmt="" + customfmt=: case "$fmt" in - PKCS8|PEM) oldfmt=1 ;; + RFC4716|PKCS8|PEM) customfmt=false ;; esac - # Some key types like ssh-ed25519 and *@openssh.com are never - # stored in old formats. + # ssh-ed25519 and *@openssh.com keys are stored only + # in custom format case "$t" in - ssh-ed25519|*openssh.com) test -z "$oldfmt" || continue ;; + ssh-ed25519|*openssh.com) $customfmt || continue ;; esac comment="foo bar" - fmtarg="" - test -z "$fmt" || fmtarg="-m $fmt" - ${SSHKEYGEN} $fmtarg -N '' -C "${comment}" \ - -t $t -f $OBJ/$t-key >/dev/null 2>&1 || \ + $SSHKEYGEN -m $fmt -N '' -C "$comment" \ + -t $t -f $OBJ/$t-key >/dev/null || \ fatal "keygen of $t in format $fmt failed" - check_fingerprint $OBJ/$t-key "${comment}" - check_fingerprint $OBJ/$t-key.pub "${comment}" + check_fingerprint $OBJ/$t-key "$comment" + check_fingerprint $OBJ/$t-key.pub "$comment" # Output fingerprint using only private file trace "fingerprinting $t key using private key file" rm -f $OBJ/$t-key.pub - if [ ! -z "$oldfmt" ] ; then - # Comment cannot be recovered from old format keys. + if $customfmt ; then + # as well comment can be extracted from + # private stored in custom format + : + else comment="no comment" fi - check_fingerprint $OBJ/$t-key "${comment}" + check_fingerprint $OBJ/$t-key "$comment" rm -f $OBJ/$t-key* done done diff -ruN openssh-9.4p1/regress/keygen-convert.sh openssh-9.4p1+x509-14.2.1/regress/keygen-convert.sh --- openssh-9.4p1/regress/keygen-convert.sh 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/keygen-convert.sh 2023-08-20 10:07:00.000000000 +0300 @@ -4,41 +4,54 @@ tid="convert keys" cat > $OBJ/askpass <&1 | grep "ssh-keygen -e" >/dev/null; then - test_import_export=1 -fi - -for t in ${SSH_KEYTYPES}; do - # generate user key for agent - trace "generating $t key" - rm -f $OBJ/$t-key - ${SSHKEYGEN} -q -N "" -t $t -f $OBJ/$t-key - - if test "x$test_import_export" = "x1"; then - trace "export $t private to rfc4716 public" - ${SSHKEYGEN} -q -e -f $OBJ/$t-key >$OBJ/$t-key-rfc || \ - fail "export $t private to rfc4716 public" - - trace "export $t public to rfc4716 public" - ${SSHKEYGEN} -q -e -f $OBJ/$t-key.pub >$OBJ/$t-key-rfc.pub || \ - fail "$t public to rfc4716 public" - - cmp $OBJ/$t-key-rfc $OBJ/$t-key-rfc.pub || \ - fail "$t rfc4716 exports differ between public and private" - - trace "import $t rfc4716 public" - ${SSHKEYGEN} -q -i -f $OBJ/$t-key-rfc >$OBJ/$t-rfc-imported || \ - fail "$t import rfc4716 public" - - cut -f1,2 -d " " $OBJ/$t-key.pub >$OBJ/$t-key-nocomment.pub - cmp $OBJ/$t-key-nocomment.pub $OBJ/$t-rfc-imported || \ - fail "$t imported differs from original" - fi +do_test() { + fmt=$1 + msg=$2 + sfx=$3 + + case $fmt in + PKCS8) + case $t in + ed25519) + config_defined OPENSSL_HAS_ED25519 || + return;; + esac + ;; + esac + + trace "export $t private to $msg public" + ${SSHKEYGEN} -q -e -m $fmt -f $OBJ/$t-key >$OBJ/$t-key-$sfx || \ + fail "export $t private to rfc4716 public" + + trace "export $t public to $msg public" + ${SSHKEYGEN} -q -e -m $fmt -f $OBJ/$t-key.only-pub >$OBJ/$t-key-$sfx.pub || \ + fail "$t public to $msg public" + + cmp $OBJ/$t-key-$sfx $OBJ/$t-key-$sfx.pub > /dev/null || \ + fail "$t $msg exports differ between public and private" + + trace "import $t $msg public" + ${SSHKEYGEN} -q -i -m $fmt -f $OBJ/$t-key-$sfx >$OBJ/$t-$sfx-imported || \ + fail "$t import $msg public" + + cmp $OBJ/$t-key-nocomment.pub $OBJ/$t-$sfx-imported > /dev/null || \ + fail "$t $msg imported differs from original" + + rm -f $OBJ/$t-key-$sfx $OBJ/$t-key-$sfx.pub $OBJ/$t-$sfx-imported +} + +do_test_askpass() { + e=$t-key-nocomment.pub + case $t in + ed25519) + config_defined OPENSSL_HAS_ED25519 || + e=$t-key.only-pub;; + esac trace "set passphrase $t" ${SSHKEYGEN} -q -p -P '' -N 'hunter2' -f $OBJ/$t-key >/dev/null || \ @@ -46,10 +59,34 @@ trace "export $t to public with passphrase" SSH_ASKPASS=$OBJ/askpass SSH_ASKPASS_REQUIRE=force \ - ${SSHKEYGEN} -y -f $OBJ/$t-key >$OBJ/$t-key-nocomment.pub - cmp $OBJ/$t-key.pub $OBJ/$t-key-nocomment.pub || \ + ${SSHKEYGEN} -y -f $OBJ/$t-key >$OBJ/$t-key-askpass.pub + cmp $OBJ/$t-key-askpass.pub $OBJ/$e || \ fail "$t exported pubkey differs from generated" +} + +for i in ${SSH_KEYTYPES}; do + case "$i" in + ssh-rsa) t=rsa; type="-t rsa" ;; + ecdsa-sha2-nistp256) t=ec_p256; type="-t ecdsa -b 256" ;; + ecdsa-sha2-nistp384) t=ec_p384; type="-t ecdsa -b 384" ;; + ecdsa-sha2-nistp521) t=ec_p521; type="-t ecdsa -b 521" ;; + ssh-ed25519) t=ed25519; type="-t ed25519" ;; + ssh-dss) t=dsa; type="-t dsa" ;; + *) continue ;; + esac + + # generate user key for import/export + trace "generating $t key" + rm -f $OBJ/$t-key + ${SSHKEYGEN} -q -N "" $type -f $OBJ/$t-key + mv $OBJ/$t-key.pub $OBJ/$t-key.only-pub + cut -f1,2 -d " " $OBJ/$t-key.only-pub >$OBJ/$t-key-nocomment.pub + + do_test RFC4716 "rfc4716" rfc + do_test PKCS8 "pkcs#8" pk8 + + do_test_askpass - rm -f $OBJ/$t-key $OBJ/$t-key.pub $OBJ/$t-key-rfc $OBJ/$t-key-rfc.pub \ - $OBJ/$t-rfc-imported $OBJ/$t-key-nocomment.pub + rm -f $OBJ/$t-key $OBJ/$t-key.only-pub \ + $OBJ/$t-key-askpass.pub $OBJ/$t-key-nocomment.pub done diff -ruN openssh-9.4p1/regress/keygen-knownhosts.sh openssh-9.4p1+x509-14.2.1/regress/keygen-knownhosts.sh --- openssh-9.4p1/regress/keygen-knownhosts.sh 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/keygen-knownhosts.sh 2023-08-20 10:07:00.000000000 +0300 @@ -56,7 +56,7 @@ _host=$1 _name=$2 shift; shift - ${SSHKEYGEN} "$@" -f $OBJ/kh.invalid -F $_host > $OBJ/kh.result + $SSHKEYGEN ${1+"$@"} -f $OBJ/kh.invalid -F $_host > $OBJ/kh.result if ! diff -w $OBJ/kh.expect $OBJ/kh.result ; then fail "didn't find $_name" fi diff -ruN openssh-9.4p1/regress/keygen-moduli.sh openssh-9.4p1+x509-14.2.1/regress/keygen-moduli.sh --- openssh-9.4p1/regress/keygen-moduli.sh 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/keygen-moduli.sh 2023-08-20 10:07:00.000000000 +0300 @@ -3,17 +3,17 @@ tid="keygen moduli" -dhgex=0 +dhgex=false for kex in `${SSH} -Q kex`; do case $kex in - diffie-hellman-group*) dhgex=1 ;; + diffie-hellman-group*) dhgex=: ;; esac done # Try "start at the beginning and stop after 1", "skip 1 then stop after 1" # and "skip 2 and run to the end with checkpointing". Since our test data # file has 3 lines, these should always result in 1 line of output. -if [ "x$dhgex" = "x1" ]; then +if $dhgex ; then for i in "-O lines=1" "-O start-line=1 -O lines=1" "-O start-line=2 -O checkpoint=$OBJ/moduli.ckpt"; do trace "keygen $i" rm -f $OBJ/moduli.out $OBJ/moduli.ckpt diff -ruN openssh-9.4p1/regress/keygen-sshfp.sh openssh-9.4p1+x509-14.2.1/regress/keygen-sshfp.sh --- openssh-9.4p1/regress/keygen-sshfp.sh 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/keygen-sshfp.sh 2023-08-20 10:07:00.000000000 +0300 @@ -4,46 +4,57 @@ tid="keygen-sshfp" trace "keygen fingerprints" -fp=`${SSHKEYGEN} -r test -f ${SRC}/ed25519_openssh.pub | \ - awk '$5=="1"{print $6}'` -if [ "$fp" != "8a8647a7567e202ce317e62606c799c53d4c121f" ]; then - fail "keygen fingerprint sha1" -fi -fp=`${SSHKEYGEN} -r test -f ${SRC}/ed25519_openssh.pub | \ - awk '$5=="2"{print $6}'` -if [ "$fp" != \ - "54a506fb849aafb9f229cf78a94436c281efcb4ae67c8a430e8c06afcb5ee18f" ]; then - fail "keygen fingerprint sha256" -fi -# Expect two lines of output without an explicit algorithm +# Expect N lines of output without an explicit algorithm +if config_defined HAVE_EVP_SHA256 ; then + N=2 +else + N=1 +fi fp=`${SSHKEYGEN} -r test -f ${SRC}/ed25519_openssh.pub | wc -l` -if [ $(($fp + 0)) -ne 2 ] ; then +if test "x$fp" != "x$N" ; then fail "incorrect number of SSHFP records $fp (expected 2)" fi # Test explicit algorithm selection exp="test IN SSHFP 4 1 8a8647a7567e202ce317e62606c799c53d4c121f" fp=`${SSHKEYGEN} -Ohashalg=sha1 -r test -f ${SRC}/ed25519_openssh.pub` -if [ "x$exp" != "x$fp" ] ; then +if test "x$exp" != "x$fp" ; then fail "incorrect SHA1 SSHFP output" fi +if config_defined HAVE_EVP_SHA256 ; then exp="test IN SSHFP 4 2 54a506fb849aafb9f229cf78a94436c281efcb4ae67c8a430e8c06afcb5ee18f" fp=`${SSHKEYGEN} -Ohashalg=sha256 -r test -f ${SRC}/ed25519_openssh.pub` -if [ "x$exp" != "x$fp" ] ; then +if test "x$exp" != "x$fp" ; then fail "incorrect SHA256 SSHFP output" fi +fi -if ${SSH} -Q key-plain | grep ssh-rsa >/dev/null; then - fp=`${SSHKEYGEN} -r test -f ${SRC}/rsa_openssh.pub | awk '$5=="1"{print $6}'` - if [ "$fp" != "99c79cc09f5f81069cc017cdf9552cfc94b3b929" ]; then - fail "keygen fingerprint sha1" +for k in $SSH_KEYTYPES ; do + case $k in + ssh-ed25519) + N=ed25519; + fp1='8a8647a7567e202ce317e62606c799c53d4c121f'; + fp2='54a506fb849aafb9f229cf78a94436c281efcb4ae67c8a430e8c06afcb5ee18f'; + ;; + ssh-rsa) + N=rsa; + fp1='99c79cc09f5f81069cc017cdf9552cfc94b3b929'; + fp2='e30d6b9eb7a4de495324e4d5870b8220577993ea6af417e8e4a4f1c5bf01a9b6'; + ;; + *) + continue + ;; + esac + res=`${SSHKEYGEN} -r test -f ${SRC}/${N}_openssh.pub` + fp=`echo "$res" | awk '$5=="1" { print $6 }'` + if test "x$fp" != "x$fp1" ; then + fail "keygen fingerprint sha1 for keytype $k" fi - fp=`${SSHKEYGEN} -r test -f ${SRC}/rsa_openssh.pub | awk '$5=="2"{print $6}'` - if [ "$fp" != \ - "e30d6b9eb7a4de495324e4d5870b8220577993ea6af417e8e4a4f1c5bf01a9b6" ]; then - fail "keygen fingerprint sha256" + config_defined HAVE_EVP_SHA256 || continue + fp=`echo "$res" | awk '$5=="2" { print $6 }'` + if test "x$fp" != "x$fp2" ; then + fail "keygen fingerprint sha256 for keytype $k" fi -fi - +done diff -ruN openssh-9.4p1/regress/key-options.sh openssh-9.4p1+x509-14.2.1/regress/key-options.sh --- openssh-9.4p1/regress/key-options.sh 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/key-options.sh 2023-08-20 10:07:00.000000000 +0300 @@ -7,12 +7,6 @@ authkeys="$OBJ/authorized_keys_${USER}" cp $authkeys $origkeys -# Allocating ptys can require privileges on some platforms. -skip_pty="" -if ! config_defined HAVE_OPENPTY && [ "x$SUDO" = "x" ]; then - skip_pty="no openpty(3) and SUDO not set" -fi - # Test command= forced command for c in 'command="echo bar"' 'no-pty,command="echo bar"'; do sed "s/.*/$c &/" $origkeys >$authkeys @@ -33,7 +27,6 @@ rm -f $OBJ/data sed "s/.*/$opts &/" $origkeys >$authkeys verbose "key option pty $which" - [ "x$skip_pty" != "x" ] && verbose "skipped because $skip_pty" && return ${SSH} -ttq -F $OBJ/ssh_proxy somehost "tty > $OBJ/data; exit 0" if [ $? -ne 0 ] ; then fail "key option failed $which" @@ -51,7 +44,6 @@ rm -f $OBJ/data sed "s/.*/$opts &/" $origkeys >$authkeys verbose "key option pty $which" - [ "x$skip_pty" != "x" ] && verbose "skipped because $skip_pty" && return ${SSH} -ttq -F $OBJ/ssh_proxy somehost "tty > $OBJ/data; exit 0" if [ $? -eq 0 ]; then r=`cat $OBJ/data` diff -ruN openssh-9.4p1/regress/keyscan.sh openssh-9.4p1+x509-14.2.1/regress/keyscan.sh --- openssh-9.4p1/regress/keyscan.sh 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/keyscan.sh 2023-08-20 10:07:00.000000000 +0300 @@ -3,7 +3,8 @@ tid="keyscan" -for i in $SSH_KEYTYPES; do +algs= +for i in $SSH_HOSTKEY_TYPES ; do if [ -z "$algs" ]; then algs="$i" else @@ -14,7 +15,7 @@ start_sshd -for t in $SSH_KEYTYPES; do +for t in $SSH_HOSTKEY_TYPES ; do trace "keyscan type $t" ${SSHKEYSCAN} -t $t -T 15 -p $PORT 127.0.0.1 127.0.0.1 127.0.0.1 \ > /dev/null 2>&1 diff -ruN openssh-9.4p1/regress/keys-command.sh openssh-9.4p1+x509-14.2.1/regress/keys-command.sh --- openssh-9.4p1/regress/keys-command.sh 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/keys-command.sh 2023-08-20 10:07:00.000000000 +0300 @@ -1,4 +1,4 @@ -# $OpenBSD: keys-command.sh,v 1.8 2021/09/30 04:22:50 dtucker Exp $ +# $OpenBSD: keys-command.sh,v 1.7 2021/09/01 00:50:27 dtucker Exp $ # Placed in the Public Domain. tid="authorized keys from command" @@ -20,8 +20,8 @@ KEY_COMMAND="/var/run/keycommand_${LOGNAME}.$$" trap "${SUDO} rm -f ${KEY_COMMAND}" 0 cat << _EOF | $SUDO sh -c "rm -f '$KEY_COMMAND' ; cat > '$KEY_COMMAND'" -#!/bin/sh -echo args: "\$@" >> $OBJ/keys-command-args +#! $TEST_SHELL +echo args: \${1+"\$@"} >> $OBJ/keys-command-args echo "$PATH" | grep -q mekmitasdigoat && exit 7 test "x\$1" != "x${LOGNAME}" && exit 1 if test $# -eq 6 ; then @@ -36,9 +36,8 @@ $SUDO chmod 0755 "$KEY_COMMAND" if ! $OBJ/check-perm -m keys-command $KEY_COMMAND ; then - echo "skipping: $KEY_COMMAND is unsuitable as AuthorizedKeysCommand" $SUDO rm -f $KEY_COMMAND - exit 0 + skip "$KEY_COMMAND is unsuitable as AuthorizedKeysCommand" fi if [ -x $KEY_COMMAND ]; then diff -ruN openssh-9.4p1/regress/keytype.sh openssh-9.4p1+x509-14.2.1/regress/keytype.sh --- openssh-9.4p1/regress/keytype.sh 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/keytype.sh 2023-08-20 10:07:00.000000000 +0300 @@ -6,6 +6,8 @@ cp $OBJ/sshd_proxy $OBJ/sshd_proxy_bak cp $OBJ/ssh_proxy $OBJ/ssh_proxy_bak +config_defined HAVE_EVP_SHA256 && extra_algs=",rsa-sha2-*" + # Construct list of key types based on what the built binaries support. ktypes="" for i in ${SSH_KEYTYPES}; do @@ -16,21 +18,16 @@ ecdsa-sha2-nistp256) ktypes="$ktypes ecdsa-256" ;; ecdsa-sha2-nistp384) ktypes="$ktypes ecdsa-384" ;; ecdsa-sha2-nistp521) ktypes="$ktypes ecdsa-521" ;; - sk-ssh-ed25519*) ktypes="$ktypes ed25519-sk" ;; - sk-ecdsa-sha2-nistp256*) ktypes="$ktypes ecdsa-sk" ;; esac done for kt in $ktypes; do rm -f $OBJ/key.$kt - xbits=`echo ${kt} | awk -F- '{print $2}'` - xtype=`echo ${kt} | awk -F- '{print $1}'` - case "$kt" in - *sk) type="$kt"; bits="n/a"; bits_arg="";; - *) type=$xtype; bits=$xbits; bits_arg="-b $bits";; - esac + bits=`echo ${kt} | awk -F- '{print $2}'` + type=`echo ${kt} | awk -F- '{print $1}'` verbose "keygen $type, $bits bits" - ${SSHKEYGEN} $bits_arg -q -N '' -t $type -f $OBJ/key.$kt || \ + keytype_compat $type + $SSHKEYGEN -b $bits -q -N '' $keytype_val -f $OBJ/key.$kt || \ fail "ssh-keygen for type $type, $bits bits failed" done @@ -41,16 +38,14 @@ ecdsa-384) echo ecdsa-sha2-nistp384;; ecdsa-521) echo ecdsa-sha2-nistp521;; ed25519-512) echo ssh-ed25519;; - rsa-*) echo rsa-sha2-512,rsa-sha2-256,ssh-rsa;; - ed25519-sk) echo sk-ssh-ed25519@openssh.com;; - ecdsa-sk) echo sk-ecdsa-sha2-nistp256@openssh.com;; + rsa-*) echo ssh-rsa$extra_algs;; esac } tries="1 2 3" for ut in $ktypes; do user_type=`kname_to_ktype "$ut"` - htypes="$ut" + htypes=$ut #htypes=$ktypes for ht in $htypes; do host_type=`kname_to_ktype "$ht"` diff -ruN openssh-9.4p1/regress/knownhosts-command.sh openssh-9.4p1+x509-14.2.1/regress/knownhosts-command.sh --- openssh-9.4p1/regress/knownhosts-command.sh 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/knownhosts-command.sh 2023-08-20 10:07:00.000000000 +0300 @@ -1,8 +1,18 @@ -# $OpenBSD: knownhosts-command.sh,v 1.3 2021/08/30 01:15:45 djm Exp $ +# $OpenBSD: knownhosts-command.sh,v 1.2 2020/12/22 06:47:24 djm Exp $ # Placed in the Public Domain. tid="known hosts command " +# cross-project configuration +if test "$sshd_type" != "pkix" ; then +mv $OBJ/sshd_proxy $OBJ/sshd_proxy.orig +( + grep -v "HostkeyAlgorithms" $OBJ/sshd_proxy.orig + echo "HostkeyAlgorithms *,ssh-dss*" +) > $OBJ/sshd_proxy +fi + + rm -f $OBJ/knownhosts_command $OBJ/ssh_proxy_khc cp $OBJ/ssh_proxy $OBJ/ssh_proxy_orig @@ -13,43 +23,50 @@ echo "KnownHostsCommand $OBJ/knownhosts_command '%t' '%K' '%u'" ; ) > $OBJ/ssh_proxy +> $OBJ/knownhosts_command +chmod a+x $OBJ/knownhosts_command + verbose "simple connection" cat > $OBJ/knownhosts_command << _EOF -#!/bin/sh +#! $TEST_SHELL cat $OBJ/known_hosts _EOF -chmod a+x $OBJ/knownhosts_command -${SSH} -F $OBJ/ssh_proxy x true || fail "ssh connect failed" +$SSH -F $OBJ/ssh_proxy x true || fail "ssh connect failed" verbose "no keys" cat > $OBJ/knownhosts_command << _EOF -#!/bin/sh +#! $TEST_SHELL exit 0 _EOF -chmod a+x $OBJ/knownhosts_command -${SSH} -F $OBJ/ssh_proxy x true && fail "ssh connect succeeded with no keys" +$SSH -F $OBJ/ssh_proxy x true && fail "ssh connect succeeded with no keys" verbose "bad exit status" cat > $OBJ/knownhosts_command << _EOF -#!/bin/sh +#! $TEST_SHELL cat $OBJ/known_hosts exit 1 _EOF -chmod a+x $OBJ/knownhosts_command -${SSH} -F $OBJ/ssh_proxy x true && fail "ssh connect succeeded with bad exit" +$SSH -F $OBJ/ssh_proxy x true && fail "ssh connect succeeded with bad exit" -for keytype in ${SSH_HOSTKEY_TYPES} ; do - algs=$keytype - test "x$keytype" = "xssh-dss" && continue - test "x$keytype" = "xssh-rsa" && algs=ssh-rsa,rsa-sha2-256,rsa-sha2-512 +for keytype in $SSH_HOSTKEY_TYPES ; do +case $keytype in +ssh-xmss@openssh.com) continue;; # TODO +esac verbose "keytype $keytype" cat > $OBJ/knownhosts_command << _EOF -#!/bin/sh -die() { echo "\$@" 1>&2 ; exit 1; } +#! $TEST_SHELL +if test "x\$1" = "xNONE" ; then + grep " $keytype " $OBJ/known_hosts + exit 0 +fi +die() { echo \${1+"\$@"} >&2 ; exit 1; } test "x\$1" = "x$keytype" || die "wrong keytype \$1 (expected $keytype)" test "x\$3" = "x$LOGNAME" || die "wrong username \$3 (expected $LOGNAME)" -grep -- "\$1.*\$2" $OBJ/known_hosts +grep "\$1.*\$2" $OBJ/known_hosts _EOF - ${SSH} -F $OBJ/ssh_proxy -oHostKeyAlgorithms=$algs x true || - fail "ssh connect failed for keytype $x" + $SSH -F $OBJ/ssh_proxy -oHostKeyAlgorithms=$keytype x true || + fail "ssh connect failed for keytype $keytype" done + +# cleanup +rm -f knownhosts_command diff -ruN openssh-9.4p1/regress/krl.sh openssh-9.4p1+x509-14.2.1/regress/krl.sh --- openssh-9.4p1/regress/krl.sh 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/krl.sh 2023-08-20 10:07:00.000000000 +0300 @@ -3,17 +3,20 @@ tid="key revocation lists" +if config_defined HAVE_EVP_SHA256 ; then + skip_sha256=false +else + skip_sha256=: +fi + # Use ed25519 by default since it's fast and it's supported when building # w/out OpenSSL. Populate ktype[2-4] with the other types if supported. -ktype1=ed25519; ktype2=ed25519; ktype3=ed25519; -ktype4=ed25519; ktype5=ed25519; ktype6=ed25519; +ktype1=ed25519; ktype2=ed25519; ktype3=ed25519; ktype4=ed25519 for t in $SSH_KEYTYPES; do case "$t" in ecdsa*) ktype2=ecdsa ;; ssh-rsa) ktype3=rsa ;; ssh-dss) ktype4=dsa ;; - sk-ssh-ed25519@openssh.com) ktype5=ed25519-sk ;; - sk-ecdsa-sha2-nistp256@openssh.com) ktype6=ecdsa-sk ;; esac done @@ -37,7 +40,6 @@ serial: 15 serial: 30 serial: 50 -serial: 90 serial: 999 # The following sum to 500-799 serial: 500 @@ -55,7 +57,7 @@ # A specification that revokes some certificated by key ID. touch $OBJ/revoked-keyid -for n in 1 2 3 4 10 15 30 50 90 `jot 500 300` 999 1000 1001 1002; do +for n in 1 2 3 4 10 15 30 50 `jot 500 300` 999 1000 1001 1002; do test "x$n" = "x499" && continue # Fill in by-ID revocation spec. echo "id: revoked $n" >> $OBJ/revoked-keyid @@ -68,11 +70,9 @@ # supported. keytype=$ktype1 case $N in - 2 | 10 | 510 | 1001) keytype=$ktype2 ;; - 4 | 30 | 520 | 1002) keytype=$ktype3 ;; - 8 | 50 | 530 | 1003) keytype=$ktype4 ;; - 16 | 70 | 540 | 1004) keytype=$ktype5 ;; - 32 | 90 | 550 | 1005) keytype=$ktype6 ;; + 2 | 10 | 510 | 1001) keytype=$ktype2 ;; + 4 | 30 | 520 | 1002) keytype=$ktype3 ;; + 8 | 50 | 530 | 1003) keytype=$ktype4 ;; esac $SSHKEYGEN -t $keytype -f $f -C "" -N "" > /dev/null \ || fatal "$SSHKEYGEN failed" @@ -84,7 +84,7 @@ # Generate some keys. verbose "$tid: generating test keys" -REVOKED_SERIALS="1 4 10 50 90 500 510 520 550 799 999" +REVOKED_SERIALS="1 4 10 50 500 510 520 799 999" for n in $REVOKED_SERIALS ; do f=`keygen $n` RKEYS="$RKEYS ${f}.pub" @@ -102,6 +102,7 @@ touch $OBJ/revoked-sha1 $OBJ/revoked-sha256 $OBJ/revoked-hash for rkey in $RKEYS; do (printf "sha1: "; cat $rkey) >> $OBJ/revoked-sha1 + $skip_sha256 || \ (printf "sha256: "; cat $rkey) >> $OBJ/revoked-sha256 (printf "hash: "; $SSHKEYGEN -lf $rkey | \ awk '{ print $2 }') >> $OBJ/revoked-hash @@ -121,6 +122,7 @@ >/dev/null || fatal "$SSHKEYGEN KRL failed" $SSHKEYGEN $OPTS -kf $OBJ/krl-sha1 $OBJ/revoked-sha1 \ >/dev/null 2>&1 || fatal "$SSHKEYGEN KRL failed" +$skip_sha256 || \ $SSHKEYGEN $OPTS -kf $OBJ/krl-sha256 $OBJ/revoked-sha256 \ >/dev/null 2>&1 || fatal "$SSHKEYGEN KRL failed" $SSHKEYGEN $OPTS -kf $OBJ/krl-hash $OBJ/revoked-hash \ @@ -183,6 +185,7 @@ check_krl $f $OBJ/krl-keys $KEYS_RESULT "$TAG" check_krl $f $OBJ/krl-all $ALL_RESULT "$TAG" check_krl $f $OBJ/krl-sha1 $HASH_RESULT "$TAG" + $skip_sha256 || \ check_krl $f $OBJ/krl-sha256 $HASH_RESULT "$TAG" check_krl $f $OBJ/krl-hash $HASH_RESULT "$TAG" check_krl $f $OBJ/krl-serial $SERIAL_RESULT "$TAG" diff -ruN openssh-9.4p1/regress/limit-keytype.sh openssh-9.4p1+x509-14.2.1/regress/limit-keytype.sh --- openssh-9.4p1/regress/limit-keytype.sh 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/limit-keytype.sh 2023-08-20 10:07:00.000000000 +0300 @@ -3,23 +3,18 @@ tid="restrict pubkey type" -# XXX sk-* keys aren't actually tested ATM. - rm -f $OBJ/authorized_keys_$USER $OBJ/user_ca_key* $OBJ/user_key* rm -f $OBJ/authorized_principals_$USER $OBJ/cert_user_key* mv $OBJ/sshd_proxy $OBJ/sshd_proxy.orig mv $OBJ/ssh_proxy $OBJ/ssh_proxy.orig -ktype1=ed25519; ktype2=ed25519; ktype3=ed25519; -ktype4=ed25519; ktype5=ed25519; ktype6=ed25519; -for t in $SSH_KEYTYPES ; do +ktype1=ed25519; ktype2=$ktype1; ktype3=$ktype1; ktype4=$ktype1 +for t in $SSH_KEYTYPES ; do case "$t" in ssh-rsa) ktype2=rsa ;; ecdsa*) ktype3=ecdsa ;; # unused ssh-dss) ktype4=dsa ;; - sk-ssh-ed25519@openssh.com) ktype5=ed25519-sk ;; - sk-ecdsa-sha2-nistp256@openssh.com) ktype6=ecdsa-sk ;; esac done @@ -36,10 +31,6 @@ fatal "ssh-keygen failed" ${SSHKEYGEN} -q -N '' -t $ktype4 -f $OBJ/user_key4 || \ fatal "ssh-keygen failed" -${SSHKEYGEN} -q -N '' -t $ktype5 -f $OBJ/user_key5 || \ - fatal "ssh-keygen failed" -${SSHKEYGEN} -q -N '' -t $ktype6 -f $OBJ/user_key6 || \ - fatal "ssh-keygen failed" ${SSHKEYGEN} -q -s $OBJ/user_ca_key -I "regress user key for $USER" \ -z $$ -n ${USER},mekmitasdigoat $OBJ/user_key3 || fatal "couldn't sign user_key1" @@ -52,6 +43,8 @@ opts="-oProtocol=2 -F $OBJ/ssh_proxy -oIdentitiesOnly=yes" certopts="$opts -i $OBJ/user_key3 -oCertificateFile=$OBJ/cert_user_key3.pub" +config_defined HAVE_EVP_SHA256 && extra_algs=",rsa-sha2-256,rsa-sha2-512" + echo mekmitasdigoat > $OBJ/authorized_principals_$USER cat $OBJ/user_key1.pub > $OBJ/authorized_keys_$USER cat $OBJ/user_key2.pub >> $OBJ/authorized_keys_$USER @@ -63,10 +56,10 @@ echo "AuthenticationMethods publickey" echo "TrustedUserCAKeys $OBJ/user_ca_key.pub" echo "AuthorizedPrincipalsFile $OBJ/authorized_principals_%u" - for x in "$@" ; do + for x in ${1+"$@"} ; do echo "$x" done - ) > $OBJ/sshd_proxy + ) > $OBJ/sshd_proxy } # Return the required parameter for PubkeyAcceptedAlgorithms corresponding to @@ -76,9 +69,7 @@ ecdsa) printf "ecdsa-sha2-*" ;; ed25519) printf "ssh-ed25519" ;; dsa) printf "ssh-dss" ;; - rsa) printf "rsa-sha2-256,rsa-sha2-512,ssh-rsa" ;; - sk-ecdsa) printf "sk-ecdsa-*" ;; - sk-ssh-ed25519) printf "sk-ssh-ed25519-*" ;; + rsa) printf "ssh-rsa$extra_algs" ;; esac } @@ -116,7 +107,7 @@ # Allow RSA in main config, Ed25519 for non-existent user. verbose "match w/ no match" prepare_config "PubkeyAcceptedAlgorithms `keytype $ktype2`" \ - "Match user x$USER" "PubkeyAcceptedAlgorithms +`keytype $ktype1`" + "Match user x$USER" "PubkeyAcceptedAlgorithms `keytype $ktype1`" ${SSH} $certopts proxy true && fatal "cert succeeded" if [ "$ktype1" != "$ktype2" ]; then ${SSH} $opts -i $OBJ/user_key1 proxy true && fatal "key1 succeeded" @@ -126,8 +117,7 @@ # Allow only DSA in main config, Ed25519 for user. verbose "match w/ matching" prepare_config "PubkeyAcceptedAlgorithms `keytype $ktype4`" \ - "Match user $USER" "PubkeyAcceptedAlgorithms +`keytype $ktype1`" + "Match user $USER" "PubkeyAcceptedAlgorithms *$ktype2*-cert-v01@openssh.com,`keytype $ktype1`" ${SSH} $certopts proxy true || fatal "cert failed" ${SSH} $opts -i $OBJ/user_key1 proxy true || fatal "key1 failed" ${SSH} $opts -i $OBJ/user_key4 proxy true && fatal "key4 succeeded" - diff -ruN openssh-9.4p1/regress/login-timeout.sh openssh-9.4p1+x509-14.2.1/regress/login-timeout.sh --- openssh-9.4p1/regress/login-timeout.sh 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/login-timeout.sh 2023-08-20 10:07:00.000000000 +0300 @@ -1,9 +1,9 @@ -# $OpenBSD: login-timeout.sh,v 1.10 2021/09/30 05:20:08 dtucker Exp $ +# $OpenBSD: login-timeout.sh,v 1.9 2017/08/07 00:53:51 dtucker Exp $ # Placed in the Public Domain. tid="connect after login grace timeout" -trace "test login grace time" +trace "test login grace with privsep" cp $OBJ/sshd_config $OBJ/sshd_config.orig grep -vi LoginGraceTime $OBJ/sshd_config.orig > $OBJ/sshd_config echo "LoginGraceTime 10s" >> $OBJ/sshd_config @@ -14,5 +14,19 @@ sleep 15 ${SSH} -F $OBJ/ssh_config somehost true if [ $? -ne 0 ]; then - fail "ssh connect after login grace timeout failed" + fail "ssh connect after login grace timeout failed with privsep" +fi + +stop_sshd + +trace "test login grace without privsep" +echo "UsePrivilegeSeparation no" >> $OBJ/sshd_config +start_sshd +sleep 1 + +(echo SSH-2.0-fake; sleep 60) | telnet 127.0.0.1 ${PORT} >/dev/null 2>&1 & +sleep 15 +${SSH} -F $OBJ/ssh_config somehost true +if [ $? -ne 0 ]; then + fail "ssh connect after login grace timeout failed without privsep" fi diff -ruN openssh-9.4p1/regress/Makefile openssh-9.4p1+x509-14.2.1/regress/Makefile --- openssh-9.4p1/regress/Makefile 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/Makefile 2023-08-20 10:07:00.000000000 +0300 @@ -1,6 +1,7 @@ # $OpenBSD: Makefile,v 1.125 2023/05/17 05:52:01 djm Exp $ -tests: prep file-tests t-exec unit +tests: unit file-tests t-exec +check-core: tests REGRESS_TARGETS= t1 t2 t3 t4 t5 t6 t7 t8 t9 t10 t11 t12 @@ -10,18 +11,15 @@ # Interop tests are not run by default interop interop-tests: t-exec-interop -prep: - test "x${USE_VALGRIND}" = "x" || mkdir -p $(OBJ)/valgrind-out - clean: for F in $(CLEANFILES); do rm -f $(OBJ)$$F; done + rm -rf $(OBJ)copy.dd $(OBJ)copy.dd2 $(OBJ)copy.dd.glob[456] rm -rf $(OBJ).putty distclean: clean -LTESTS= connect \ +LTESTS= connect \ proxy-connect \ - sshfp-connect \ connect-privsep \ connect-uri \ proto-version \ @@ -73,7 +71,6 @@ cfgparse \ cfgmatch \ cfgmatchlisten \ - percent \ addrmatch \ localcommand \ forcecommand \ @@ -97,54 +94,71 @@ servcfginclude \ allow-deny-users \ authinfo \ - sshsig \ knownhosts \ knownhosts-command \ - agent-restrict \ - hostbased \ channel-timeout \ connection-timeout +# portability: +# percent \ +# extra setup: +# hostbased - see comment in regression test + +FIPS_LTESTS=\ + fips-connect-privsep \ + fips-try-ciphers + INTEROP_TESTS= putty-transfer putty-ciphers putty-kex conch-ciphers #INTEROP_TESTS+=ssh-com ssh-com-client ssh-com-keygen ssh-com-sftp EXTRA_TESTS= agent-pkcs11 -#EXTRA_TESTS+= cipher-speed +#EXTRA_TESTS+= cipher-speed -USERNAME= ${LOGNAME} -CLEANFILES= *.core actual agent-key.* authorized_keys_${USERNAME} \ - authorized_keys_${USERNAME}.* \ - authorized_principals_${USERNAME} \ +CLEAN_KEYGEN_CONVERT= *-key *-key.only-pub *-key-nocomment.pub \ + *-key-rfc *-key-rfc.pub *-rfc-imported \ + *-key-pk8 *-key-pk8.pub *-pk8-imported +CLEANFILES= *.core actual agent-ca agent-ca.pub agent-key.* authkeys_orig \ + $(CLEAN_KEYGEN_CONVERT) \ + authorized_keys_* \ + authorized_principals_* \ banner.in banner.out cert_host_key* cert_user_key* \ - copy.1 copy.2 data ed25519-agent ed25519-agent* \ - ed25519-agent.pub ed25519 ed25519.pub empty.in \ + batch copy2 data \ + ssh-dss-agent* ssh-dss ssh-dss.pub \ + ssh-ed25519-agent* ssh-ed25519 ssh-ed25519.pub empty.in \ + ecdsa-sha2-nistp256-agent* ecdsa-sha2-nistp256 ecdsa-sha2-nistp256.pub \ + ecdsa-sha2-nistp384-agent* ecdsa-sha2-nistp384 ecdsa-sha2-nistp384.pub \ + ecdsa-sha2-nistp521-agent* ecdsa-sha2-nistp521 ecdsa-sha2-nistp521.pub \ expect failed-regress.log failed-ssh.log failed-sshd.log \ hkr.* host.ecdsa-sha2-nistp256 host.ecdsa-sha2-nistp384 \ host.ecdsa-sha2-nistp521 host.ssh-dss host.ssh-ed25519 \ - host.ssh-rsa host_ca_key* host_krl_* host_revoked_* key.* \ + host.ssh-rsa host.ssh-xmss@openssh.com \ + host_ca_key* host_krl_* host_revoked_* key.* \ key.dsa-* key.ecdsa-* key.ed25519-512 \ key.ed25519-512.pub key.rsa-* keys-command-args kh.* askpass \ - known_hosts known_hosts-cert known_hosts.* krl-* ls.copy \ - modpipe netcat no_identity_config \ + known_hosts known_hosts.old known_hosts-cert knownhosts_command \ + krl-* ls.copy no_identity_config \ pidfile putty.rsa2 ready regress.log remote_pid \ - revoked-* rsa rsa-agent rsa-agent.pub rsa.pub rsa_ssh2_cr.prv \ - rsa_ssh2_crnl.prv scp-ssh-wrapper.exe \ - scp-ssh-wrapper.scp setuid-allowed sftp-server.log \ + revoked-* ssh-rsa-agent* ssh-rsa ssh-rsa.pub ssh-rsa_pem ssh-rsa_pem.pub \ + ssh-xmss@openssh.com ssh-xmss@openssh.com.pub \ + rsa_ssh2_cr.prv rsa_ssh2_crnl.prv scp-ssh-wrapper.exe \ + scp-ssh-wrapper.scp sftp-server.log \ sftp-server.sh sftp.log ssh-log-wrapper.sh ssh.log \ ssh-agent.log ssh-add.log slow-sftp-server.sh \ ssh-rsa_oldfmt knownhosts_command \ - ssh_config ssh_config.* ssh_proxy ssh_proxy_bak \ - ssh_proxy_* sshd.log sshd_config sshd_config.* \ + ssh_config ssh_config.* ssh_proxy ssh_proxy.orig ssh_proxy_* \ + sshd.log sshd_config sshd_config_minimal \ sshd_config.* sshd_proxy sshd_proxy.* sshd_proxy_bak \ sshd_proxy_orig t10.out t10.out.pub t12.out t12.out.pub \ t2.out t3.out t6.out1 t6.out2 t7.out t7.out.pub \ - t8.out t8.out.pub t9.out t9.out.pub \ - timestamp testdata user_*key* user_ca* user_key* + t8.out t8.out.pub t9.out t9.out.pub testdata \ + user_*key* user_ca* user_key* # Enable all malloc(3) randomisations and checks TEST_ENV= "MALLOC_OPTIONS=CFGJRSUX" TEST_SSH_SSHKEYGEN?=ssh-keygen +TEST_SHELL?=sh +SHELL=$(TEST_SHELL) CPPFLAGS=-I.. @@ -165,6 +179,7 @@ ${TEST_SSH_SSHKEYGEN} -if $(OBJ)/t3.out | diff - ${.CURDIR}/rsa_openssh.pub t4: + OPENSSL_FIPS=; unset OPENSSL_FIPS || :; \ ${TEST_SSH_SSHKEYGEN} -E md5 -lf ${.CURDIR}/rsa_openssh.pub |\ awk '{print $$2}' | diff - ${.CURDIR}/t4.ok @@ -193,13 +208,13 @@ ${TEST_SSH_SSHKEYGEN} -Bf $(OBJ)/t8.out > /dev/null $(OBJ)/t9.out: - ! ${TEST_SSH_SSH} -Q key-plain | grep ecdsa >/dev/null || \ + (! ${TEST_SSH_SSH} -Q key-plain | grep ecdsa >/dev/null) || \ ${TEST_SSH_SSHKEYGEN} -q -t ecdsa -N '' -f $@ t9: $(OBJ)/t9.out - ! ${TEST_SSH_SSH} -Q key-plain | grep ecdsa >/dev/null || \ + (! ${TEST_SSH_SSH} -Q key-plain | grep ecdsa >/dev/null) || \ ${TEST_SSH_SSHKEYGEN} -lf $(OBJ)/t9.out > /dev/null - ! ${TEST_SSH_SSH} -Q key-plain | grep ecdsa >/dev/null || \ + (! ${TEST_SSH_SSH} -Q key-plain | grep ecdsa >/dev/null) || \ ${TEST_SSH_SSHKEYGEN} -Bf $(OBJ)/t9.out > /dev/null @@ -211,8 +226,10 @@ ${TEST_SSH_SSHKEYGEN} -Bf $(OBJ)/t10.out > /dev/null t11: + if egrep "^#define.*HAVE_EVP_SHA256" ${BUILDDIR}/config.h >/dev/null 2>&1 ; then \ ${TEST_SSH_SSHKEYGEN} -E sha256 -lf ${.CURDIR}/rsa_openssh.pub |\ - awk '{print $$2}' | diff - ${.CURDIR}/t11.ok + awk '{print $$2}' | diff - ${.CURDIR}/t11.ok \ + ; fi $(OBJ)/t12.out: ${TEST_SSH_SSHKEYGEN} -q -t ed25519 -N '' -C 'test-comment-1234' -f $@ @@ -222,38 +239,42 @@ t-exec: ${LTESTS:=.sh} @if [ "x$?" = "x" ]; then exit 0; fi; \ - _started=""; test -z "${LTESTS_FROM}" && _started=1 ;\ + start_from=false; test -n "$$LTESTS_FROM" && start_from=:; \ for TEST in ""$?; do \ - if [ -z "$$_started" ] ; then \ - if [ "x$$TEST" = "x${LTESTS_FROM}.sh" ]; then \ - _started=1; \ - else \ - continue; \ - fi ; \ + if $$start_from ; then \ + test "x$$TEST" != "x$$LTESTS_FROM.sh" && continue; \ + start_from=false; \ fi ; \ - skip=no; \ - for t in ""$${SKIP_LTESTS}; do \ - if [ "x$${t}.sh" = "x$${TEST}" ]; then skip=yes; fi; \ + do_test=:; \ + for t in ""$$SKIP_LTESTS; do \ + if test "$$t.sh" = "$$TEST" ; then do_test=false; break; fi; \ done; \ - if [ "x$${skip}" = "xno" ]; then \ - echo "run test $${TEST}" ... 1>&2; \ + if $$do_test ; then \ + echo "=== run test $$TEST" ... >&2; \ (env SUDO="${SUDO}" TEST_ENV=${TEST_ENV} ${TEST_SHELL} ${.CURDIR}/test-exec.sh ${.OBJDIR} ${.CURDIR}/$${TEST}) || exit $$?; \ else \ - echo skip test $${TEST} 1>&2; \ + echo "=== test $$TEST skipped!" >&2; \ fi; \ done +f-exec: ${FIPS_LTESTS:=.sh} + @if [ "x$?" = "x" ]; then exit 0; fi; \ + for TEST in ""$?; do \ + echo "=== run test $$TEST" ... >&2; \ + (env SUDO="${SUDO}" TEST_ENV=${TEST_ENV} ${TEST_SHELL} ${.CURDIR}/test-exec.sh ${.OBJDIR} ${.CURDIR}/$${TEST}) || exit $$?; \ + done + t-exec-interop: ${INTEROP_TESTS:=.sh} @if [ "x$?" = "x" ]; then exit 0; fi; \ for TEST in ""$?; do \ - echo "run test $${TEST}" ... 1>&2; \ + echo "=== run test $$TEST" ... >&2; \ (env SUDO="${SUDO}" TEST_ENV=${TEST_ENV} ${TEST_SHELL} ${.CURDIR}/test-exec.sh ${.OBJDIR} ${.CURDIR}/$${TEST}) || exit $$?; \ done t-extra: ${EXTRA_TESTS:=.sh} @if [ "x$?" = "x" ]; then exit 0; fi; \ for TEST in ""$?; do \ - echo "run test $${TEST}" ... 1>&2; \ + echo "=== run test $$TEST" ... >&2; \ (env SUDO="${SUDO}" TEST_ENV=${TEST_ENV} ${TEST_SHELL} ${.CURDIR}/test-exec.sh ${.OBJDIR} ${.CURDIR}/$${TEST}) || exit $$?; \ done @@ -266,21 +287,29 @@ V="" ; \ test "x${USE_VALGRIND}" = "x" || \ V=${.CURDIR}/valgrind-unit.sh ; \ - $$V ${.OBJDIR}/unittests/sshbuf/test_sshbuf ; \ - $$V ${.OBJDIR}/unittests/sshkey/test_sshkey \ + test "x$$UNITTEST_SSHBUF" = "xskip" || \ + $$V ${.OBJDIR}/unittests/sshbuf/test_sshbuf ; \ + test "x$$UNITTEST_SSHKEY" = "xskip" || \ + $$V ${.OBJDIR}/unittests/sshkey/test_sshkey \ -d ${.CURDIR}/unittests/sshkey/testdata ; \ - $$V ${.OBJDIR}/unittests/sshsig/test_sshsig \ - -d ${.CURDIR}/unittests/sshsig/testdata ; \ + test "x$$UNITTEST_AUTHOPT" = "xskip" || \ $$V ${.OBJDIR}/unittests/authopt/test_authopt \ -d ${.CURDIR}/unittests/authopt/testdata ; \ + test "x$$UNITTEST_BITMAP" = "xskip" || \ $$V ${.OBJDIR}/unittests/bitmap/test_bitmap ; \ + test "x$$UNITTEST_CONVERSION" = "xskip" || \ $$V ${.OBJDIR}/unittests/conversion/test_conversion ; \ + test "x$$UNITTEST_KEX" = "xskip" || \ $$V ${.OBJDIR}/unittests/kex/test_kex ; \ + test "x$$UNITTEST_HOSTKEYS" = "xskip" || \ $$V ${.OBJDIR}/unittests/hostkeys/test_hostkeys \ -d ${.CURDIR}/unittests/hostkeys/testdata ; \ + test "x$$UNITTEST_MATCH" = "xskip" || \ $$V ${.OBJDIR}/unittests/match/test_match ; \ + test "x$$UNITTEST_MISC" = "xskip" || \ $$V ${.OBJDIR}/unittests/misc/test_misc ; \ + test "x$$UNITTEST_UTF8" = "xskip" || \ if test "x${TEST_SSH_UTF8}" = "xyes" ; then \ $$V ${.OBJDIR}/unittests/utf8/test_utf8 ; \ - fi \ + fi ; \ fi diff -ruN openssh-9.4p1/regress/misc/fuzz-harness/agent_fuzz.cc openssh-9.4p1+x509-14.2.1/regress/misc/fuzz-harness/agent_fuzz.cc --- openssh-9.4p1/regress/misc/fuzz-harness/agent_fuzz.cc 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/misc/fuzz-harness/agent_fuzz.cc 1970-01-01 02:00:00.000000000 +0200 @@ -1,15 +0,0 @@ -// cc_fuzz_target test for ssh-agent. -extern "C" { - -#include -#include - -extern void test_one(const uint8_t* s, size_t slen); - -int LLVMFuzzerTestOneInput(const uint8_t* s, size_t slen) -{ - test_one(s, slen); - return 0; -} - -} // extern diff -ruN openssh-9.4p1/regress/misc/fuzz-harness/agent_fuzz_helper.c openssh-9.4p1+x509-14.2.1/regress/misc/fuzz-harness/agent_fuzz_helper.c --- openssh-9.4p1/regress/misc/fuzz-harness/agent_fuzz_helper.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/misc/fuzz-harness/agent_fuzz_helper.c 1970-01-01 02:00:00.000000000 +0200 @@ -1,177 +0,0 @@ -#include "fixed-keys.h" -#include - -#define main(ac, av) xxxmain(ac, av) -#include "../../../ssh-agent.c" - -void test_one(const uint8_t* s, size_t slen); - -static int -devnull_or_die(void) -{ - int fd; - - if ((fd = open("/dev/null", O_RDWR)) == -1) { - error_f("open /dev/null: %s", strerror(errno)); - abort(); - } - return fd; -} - -static struct sshkey * -pubkey_or_die(const char *s) -{ - char *tmp, *cp; - struct sshkey *pubkey; - int r; - - tmp = cp = xstrdup(s); - if ((pubkey = sshkey_new(KEY_UNSPEC)) == NULL) - abort(); - if ((r = sshkey_read(pubkey, &cp)) != 0) { - error_fr(r, "parse"); - abort(); - } - free(tmp); - return pubkey; -} - -static struct sshkey * -privkey_or_die(const char *s) -{ - int r; - struct sshbuf *b; - struct sshkey *privkey; - - if ((b = sshbuf_from(s, strlen(s))) == NULL) { - error_f("sshbuf_from failed"); - abort(); - } - if ((r = sshkey_parse_private_fileblob(b, "", &privkey, NULL)) != 0) { - error_fr(r, "parse"); - abort(); - } - sshbuf_free(b); - return privkey; -} - -static void -add_key(const char *privkey, const char *certpath) -{ - Identity *id; - int r; - struct sshkey *cert; - - id = xcalloc(1, sizeof(Identity)); - TAILQ_INSERT_TAIL(&idtab->idlist, id, next); - idtab->nentries++; - id->key = privkey_or_die(privkey); - id->comment = xstrdup("rhododaktulos Eos"); - if (sshkey_is_sk(id->key)) - id->sk_provider = xstrdup("internal"); - - /* Now the cert too */ - id = xcalloc(1, sizeof(Identity)); - TAILQ_INSERT_TAIL(&idtab->idlist, id, next); - idtab->nentries++; - id->key = privkey_or_die(privkey); - cert = pubkey_or_die(certpath); - if ((r = sshkey_to_certified(id->key)) != 0) { - error_fr(r, "sshkey_to_certified"); - abort(); - } - if ((r = sshkey_cert_copy(cert, id->key)) != 0) { - error_fr(r, "sshkey_cert_copy"); - abort(); - } - sshkey_free(cert); - id->comment = xstrdup("outis"); - if (sshkey_is_sk(id->key)) - id->sk_provider = xstrdup("internal"); -} - -static void -cleanup_idtab(void) -{ - Identity *id; - - if (idtab == NULL) return; - for (id = TAILQ_FIRST(&idtab->idlist); id; - id = TAILQ_FIRST(&idtab->idlist)) { - TAILQ_REMOVE(&idtab->idlist, id, next); - free_identity(id); - } - free(idtab); - idtab = NULL; -} - -static void -reset_idtab(void) -{ - cleanup_idtab(); - idtab_init(); - // Load keys. - add_key(PRIV_RSA, CERT_RSA); - add_key(PRIV_DSA, CERT_DSA); - add_key(PRIV_ECDSA, CERT_ECDSA); - add_key(PRIV_ED25519, CERT_ED25519); - add_key(PRIV_ECDSA_SK, CERT_ECDSA_SK); - add_key(PRIV_ED25519_SK, CERT_ED25519_SK); -} - -static void -cleanup_sockettab(void) -{ - u_int i; - for (i = 0; i < sockets_alloc; i++) { - if (sockets[i].type != AUTH_UNUSED) - close_socket(sockets + i); - } - free(sockets); - sockets = NULL; - sockets_alloc = 0; -} - -static void -reset_sockettab(int devnull) -{ - int fd; - - cleanup_sockettab(); - if ((fd = dup(devnull)) == -1) { - error_f("dup: %s", strerror(errno)); - abort(); - } - new_socket(AUTH_CONNECTION, fd); - assert(sockets[0].type == AUTH_CONNECTION); - assert(sockets[0].fd == fd); -} - -#define MAX_MESSAGES 256 -void -test_one(const uint8_t* s, size_t slen) -{ - static int devnull = -1; - size_t i, olen, nlen; - - if (devnull == -1) { - log_init(__progname, SYSLOG_LEVEL_DEBUG3, - SYSLOG_FACILITY_AUTH, 1); - devnull = devnull_or_die(); - allowed_providers = xstrdup(""); - setenv("DISPLAY", "", 1); /* ban askpass */ - } - - reset_idtab(); - reset_sockettab(devnull); - (void)sshbuf_put(sockets[0].input, s, slen); - for (i = 0; i < MAX_MESSAGES; i++) { - olen = sshbuf_len(sockets[0].input); - process_message(0); - nlen = sshbuf_len(sockets[0].input); - if (nlen == 0 || nlen == olen) - break; - } - cleanup_idtab(); - cleanup_sockettab(); -} diff -ruN openssh-9.4p1/regress/misc/fuzz-harness/authkeys_fuzz.cc openssh-9.4p1+x509-14.2.1/regress/misc/fuzz-harness/authkeys_fuzz.cc --- openssh-9.4p1/regress/misc/fuzz-harness/authkeys_fuzz.cc 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/misc/fuzz-harness/authkeys_fuzz.cc 1970-01-01 02:00:00.000000000 +0200 @@ -1,81 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -extern "C" { - -#include "hostfile.h" -#include "auth.h" -#include "auth-options.h" -#include "sshkey.h" - -// testdata/id_ed25519.pub and testdata/id_ed25519-cert.pub -const char *pubkey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDPQXmEVMVLmeFRyafKMVWgPDkv8/uRBTwmcEDatZzMD"; -const char *certtext = "ssh-ed25519-cert-v01@openssh.com AAAAIHNzaC1lZDI1NTE5LWNlcnQtdjAxQG9wZW5zc2guY29tAAAAIMDQjYH6XRzH3j3MW1DdjCoAfvrHfgjnVGF+sLK0pBfqAAAAIDPQXmEVMVLmeFRyafKMVWgPDkv8/uRBTwmcEDatZzMDAAAAAAAAA+sAAAABAAAAB3VseXNzZXMAAAAXAAAAB3VseXNzZXMAAAAIb2R5c3NldXMAAAAAAAAAAP//////////AAAAAAAAAIIAAAAVcGVybWl0LVgxMS1mb3J3YXJkaW5nAAAAAAAAABdwZXJtaXQtYWdlbnQtZm9yd2FyZGluZwAAAAAAAAAWcGVybWl0LXBvcnQtZm9yd2FyZGluZwAAAAAAAAAKcGVybWl0LXB0eQAAAAAAAAAOcGVybWl0LXVzZXItcmMAAAAAAAAAAAAAADMAAAALc3NoLWVkMjU1MTkAAAAgM9BeYRUxUuZ4VHJp8oxVaA8OS/z+5EFPCZwQNq1nMwMAAABTAAAAC3NzaC1lZDI1NTE5AAAAQBj0og+s09/HpwdHZbzN0twooKPDWWrxGfnP1Joy6cDnY2BCSQ7zg9vbq11kLF8H/sKOTZWAQrUZ7LlChOu9Ogw= id_ed25519.pub"; - -// stubs -void auth_debug_add(const char *fmt,...) -{ -} - -void -auth_log_authopts(const char *loc, const struct sshauthopt *opts, int do_remote) -{ -} - -int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) -{ - char *tmp, *o, *cp = (char *)malloc(size + 1 + strlen(pubkey) + 1); - struct sshauthopt *opts = NULL; - struct passwd *pw = getpwuid(getuid()); - static struct sshkey *key, *cert; - - if (key == NULL) { - if ((key = sshkey_new(KEY_UNSPEC)) == NULL || - (cert = sshkey_new(KEY_UNSPEC)) == NULL) - abort(); - if ((o = tmp = strdup(pubkey)) == NULL || - sshkey_read(key, &tmp) != 0) - abort(); - free(o); - if ((o = tmp = strdup(certtext)) == NULL || - sshkey_read(cert, &tmp) != 0) - abort(); - free(o); - } - if (cp == NULL || pw == NULL || key == NULL || cert == NULL) - abort(); - - // Cleanup whitespace at input EOL. - for (; size > 0 && strchr(" \t\r\n", data[size - 1]) != NULL; size--) ; - - // Append a pubkey that will match. - memcpy(cp, data, size); - cp[size] = ' '; - memcpy(cp + size + 1, pubkey, strlen(pubkey) + 1); - - // Try key. - if ((tmp = strdup(cp)) == NULL) - abort(); - (void) auth_check_authkey_line(pw, key, tmp, "127.0.0.1", "localhost", - "fuzz", &opts); - free(tmp); - sshauthopt_free(opts); - - // Try cert. - if ((tmp = strdup(cp)) == NULL) - abort(); - (void) auth_check_authkey_line(pw, cert, tmp, "127.0.0.1", "localhost", - "fuzz", &opts); - free(tmp); - sshauthopt_free(opts); - - free(cp); - return 0; -} - -} // extern "C" diff -ruN openssh-9.4p1/regress/misc/fuzz-harness/fixed-keys.h openssh-9.4p1+x509-14.2.1/regress/misc/fuzz-harness/fixed-keys.h --- openssh-9.4p1/regress/misc/fuzz-harness/fixed-keys.h 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/misc/fuzz-harness/fixed-keys.h 1970-01-01 02:00:00.000000000 +0200 @@ -1,119 +0,0 @@ -/* - * Some keys used by fuzzers - */ - -#define PRIV_RSA \ -"-----BEGIN OPENSSH PRIVATE KEY-----\n"\ -"b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABFwAAAAdzc2gtcn\n"\ -"NhAAAAAwEAAQAAAQEA3+epf+VGKoGPaAZXrf6S0cyumQnddkGBnVFX0A5eh37RtLug0qY5\n"\ -"thxsBUbGGVr9mTd2QXwLujBwYg5l1MP/Fmg+5312Zgx9pHmS+qKULbar0hlNgptNEb+aNU\n"\ -"d3o9qg3aXqXm7+ZnjAV05ef/mxNRN2ZvuEkw7cRppTJcbBI+vF3lXuCXnX2klDI95Gl2AW\n"\ -"3WHRtanqLHZXuBkjjRBDKc7MUq/GP1hmLiAd95dvU7fZjRlIEsP84zGEI1Fb0L/kmPHcOt\n"\ -"iVfHft8CtmC9v6+94JrOiPBBNScV+dyrgAGPsdKdr/1vIpQmCNiI8s3PCiD8J7ZiBaYm0I\n"\ -"8fq5G/qnUwAAA7ggw2dXIMNnVwAAAAdzc2gtcnNhAAABAQDf56l/5UYqgY9oBlet/pLRzK\n"\ -"6ZCd12QYGdUVfQDl6HftG0u6DSpjm2HGwFRsYZWv2ZN3ZBfAu6MHBiDmXUw/8WaD7nfXZm\n"\ -"DH2keZL6opQttqvSGU2Cm00Rv5o1R3ej2qDdpepebv5meMBXTl5/+bE1E3Zm+4STDtxGml\n"\ -"MlxsEj68XeVe4JedfaSUMj3kaXYBbdYdG1qeosdle4GSONEEMpzsxSr8Y/WGYuIB33l29T\n"\ -"t9mNGUgSw/zjMYQjUVvQv+SY8dw62JV8d+3wK2YL2/r73gms6I8EE1JxX53KuAAY+x0p2v\n"\ -"/W8ilCYI2Ijyzc8KIPwntmIFpibQjx+rkb+qdTAAAAAwEAAQAAAQEArWm5B4tFasppjUHM\n"\ -"SsAuajtCxtizI1Hc10EW59cZM4vvUzE2f6+qZvdgWj3UU/L7Et23w0QVuSCnCerox379ZB\n"\ -"ddEOFFAAiQjwBx65hbd4RRUymxtIQfjq18++LcMJW1nbVQ7c69ThQbtALIggmbS+ZE/8Gx\n"\ -"jkwmIrCH0Ww8TlpsPe+mNHuyNk7UEZoXLm22lNLqq5qkIL5JgT6M2iNJpMOJy9/CKi6kO4\n"\ -"JPuVwjdG4C5pBPaMN3KJ1IvAlSlLGNaXnfXcn85gWfsCjsZmH3liey2NJamqp/w83BrKUg\n"\ -"YZvMR2qeWZaKkFTahpzN5KRK1BFeB37O0P84Dzh1biDX8QAAAIEAiWXW8ePYFwLpa2mFIh\n"\ -"VvRTdcrN70rVK5eWVaL3pyS4vGA56Jixq86dHveOnbSY+iNb1jQidtXc8SWUt2wtHqZ32h\n"\ -"Lji9/hMSKqe9SEP3xvDRDmUJqsVw0ySyrFrzm4160QY6RKU3CIQCVFslMZ9fxmrfZ/hxoU\n"\ -"0X3FVsxmC4+kwAAACBAPOc1YERpV6PjANBrGR+1o1RCdACbm5myc42QzSNIaOZmgrYs+Gt\n"\ -"7+EcoqSdbJzHJNCNQfF+A+vjbIkFiuZqq/5wwr59qXx5OAlijLB/ywwKmTWq6lp//Zxny+\n"\ -"ka3sIGNO14eQvmxNDnlLL+RIZleCTEKBXSW6CZhr+uHMZFKKMtAAAAgQDrSkm+LbILB7H9\n"\ -"jxEBZLhv53aAn4u81kFKQOJ7PzzpBGSoD12i7oIJu5siSD5EKDNVEr+SvCf0ISU3BuMpzl\n"\ -"t3YrPrHRheOFhn5e3j0e//zB8rBC0DGB4CtTDdeh7rOXUL4K0pz+8wEpNkV62SWxhC6NRW\n"\ -"I79JhtGkh+GtcnkEfwAAAAAB\n"\ -"-----END OPENSSH PRIVATE KEY-----\n" -#define PUB_RSA \ -"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDf56l/5UYqgY9oBlet/pLRzK6ZCd12QYGdUVfQDl6HftG0u6DSpjm2HGwFRsYZWv2ZN3ZBfAu6MHBiDmXUw/8WaD7nfXZmDH2keZL6opQttqvSGU2Cm00Rv5o1R3ej2qDdpepebv5meMBXTl5/+bE1E3Zm+4STDtxGmlMlxsEj68XeVe4JedfaSUMj3kaXYBbdYdG1qeosdle4GSONEEMpzsxSr8Y/WGYuIB33l29Tt9mNGUgSw/zjMYQjUVvQv+SY8dw62JV8d+3wK2YL2/r73gms6I8EE1JxX53KuAAY+x0p2v/W8ilCYI2Ijyzc8KIPwntmIFpibQjx+rkb+qdT" -#define CERT_RSA \ -"ssh-rsa-cert-v01@openssh.com AAAAHHNzaC1yc2EtY2VydC12MDFAb3BlbnNzaC5jb20AAAAg89JX6OBMYDSxER8fnU5y8xxeMCHR/hI0uVqdEhNyCpcAAAADAQABAAABAQDf56l/5UYqgY9oBlet/pLRzK6ZCd12QYGdUVfQDl6HftG0u6DSpjm2HGwFRsYZWv2ZN3ZBfAu6MHBiDmXUw/8WaD7nfXZmDH2keZL6opQttqvSGU2Cm00Rv5o1R3ej2qDdpepebv5meMBXTl5/+bE1E3Zm+4STDtxGmlMlxsEj68XeVe4JedfaSUMj3kaXYBbdYdG1qeosdle4GSONEEMpzsxSr8Y/WGYuIB33l29Tt9mNGUgSw/zjMYQjUVvQv+SY8dw62JV8d+3wK2YL2/r73gms6I8EE1JxX53KuAAY+x0p2v/W8ilCYI2Ijyzc8KIPwntmIFpibQjx+rkb+qdTAAAAAAAAA+0AAAABAAAAB3VseXNzZXMAAAAXAAAAB3VseXNzZXMAAAAIb2R5c3NldXMAAAAAAAAAAP//////////AAAAAAAAAIIAAAAVcGVybWl0LVgxMS1mb3J3YXJkaW5nAAAAAAAAABdwZXJtaXQtYWdlbnQtZm9yd2FyZGluZwAAAAAAAAAWcGVybWl0LXBvcnQtZm9yd2FyZGluZwAAAAAAAAAKcGVybWl0LXB0eQAAAAAAAAAOcGVybWl0LXVzZXItcmMAAAAAAAAAAAAAADMAAAALc3NoLWVkMjU1MTkAAAAgM9BeYRUxUuZ4VHJp8oxVaA8OS/z+5EFPCZwQNq1nMwMAAABTAAAAC3NzaC1lZDI1NTE5AAAAQGCDA6PWw4x9bHQl0w7NqifHepumqD3dmyMx+hZGuPRon+TsyCjfytu7hWmV7l9XUF0fPQNFQ7FGat5e+7YUNgE= id_rsa.pub" -#define PRIV_DSA \ -"-----BEGIN OPENSSH PRIVATE KEY-----\n"\ -"b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABsgAAAAdzc2gtZH\n"\ -"NzAAAAgQCsGTfjpQ465EOkfQXJM9BOvfRQE0fqlykAls+ncz+T7hrbeScRu8xpwzsznJNm\n"\ -"xlW8o6cUDiHmBJ5OHgamUC9N7YJeU/6fnOAZifgN8mqK6k8pKHuje8ANOiYgHLl0yiASQA\n"\ -"3//qMyzZ+W/hemoLSmLAbEqlfWVeyYx+wta1Vm+QAAABUAvWyehvUvdHvQxavYgS5p0t5Q\n"\ -"d7UAAACBAIRA9Yy+f4Kzqpv/qICPO3zk42UuP7WAhSW2nCbQdLlCiSTxcjKgcvXNRckwJP\n"\ -"44JjSHOtJy/AMtJrPIbLYG6KuWTdBlEHFiG6DafvLG+qPMSL2bPjXTOhuOMbCHIZ+5WBkW\n"\ -"THeG/Nv11iI01Of9V6tXkig23K370flkRkXFi9MdAAAAgCt6YUcQkNwG7B/e5M1FZsLP9O\n"\ -"kVB3BwLAOjmWdHpyhu3HpwSJa3XLEvhXN0i6IVI2KgPo/2GtYA6rHt14L+6u1pmhh8sAvQ\n"\ -"ksp3qZB+xh/NP+hBqf0sbHX0yYbzKOvI5SCc/kKK6yagcBZOsubM/KC8TxyVgmD5c6WzYs\n"\ -"h5TEpvAAAB2PHjRbbx40W2AAAAB3NzaC1kc3MAAACBAKwZN+OlDjrkQ6R9Bckz0E699FAT\n"\ -"R+qXKQCWz6dzP5PuGtt5JxG7zGnDOzOck2bGVbyjpxQOIeYEnk4eBqZQL03tgl5T/p+c4B\n"\ -"mJ+A3yaorqTykoe6N7wA06JiAcuXTKIBJADf/+ozLNn5b+F6agtKYsBsSqV9ZV7JjH7C1r\n"\ -"VWb5AAAAFQC9bJ6G9S90e9DFq9iBLmnS3lB3tQAAAIEAhED1jL5/grOqm/+ogI87fOTjZS\n"\ -"4/tYCFJbacJtB0uUKJJPFyMqBy9c1FyTAk/jgmNIc60nL8Ay0ms8hstgboq5ZN0GUQcWIb\n"\ -"oNp+8sb6o8xIvZs+NdM6G44xsIchn7lYGRZMd4b82/XWIjTU5/1Xq1eSKDbcrfvR+WRGRc\n"\ -"WL0x0AAACAK3phRxCQ3AbsH97kzUVmws/06RUHcHAsA6OZZ0enKG7cenBIlrdcsS+Fc3SL\n"\ -"ohUjYqA+j/Ya1gDqse3Xgv7q7WmaGHywC9CSynepkH7GH80/6EGp/SxsdfTJhvMo68jlIJ\n"\ -"z+QorrJqBwFk6y5sz8oLxPHJWCYPlzpbNiyHlMSm8AAAAUUA+OGldMi76ClO/sstpdbBUE\n"\ -"lq8AAAAAAQI=\n"\ -"-----END OPENSSH PRIVATE KEY-----\n" -#define PUB_DSA \ -"ssh-dss AAAAB3NzaC1kc3MAAACBAKwZN+OlDjrkQ6R9Bckz0E699FATR+qXKQCWz6dzP5PuGtt5JxG7zGnDOzOck2bGVbyjpxQOIeYEnk4eBqZQL03tgl5T/p+c4BmJ+A3yaorqTykoe6N7wA06JiAcuXTKIBJADf/+ozLNn5b+F6agtKYsBsSqV9ZV7JjH7C1rVWb5AAAAFQC9bJ6G9S90e9DFq9iBLmnS3lB3tQAAAIEAhED1jL5/grOqm/+ogI87fOTjZS4/tYCFJbacJtB0uUKJJPFyMqBy9c1FyTAk/jgmNIc60nL8Ay0ms8hstgboq5ZN0GUQcWIboNp+8sb6o8xIvZs+NdM6G44xsIchn7lYGRZMd4b82/XWIjTU5/1Xq1eSKDbcrfvR+WRGRcWL0x0AAACAK3phRxCQ3AbsH97kzUVmws/06RUHcHAsA6OZZ0enKG7cenBIlrdcsS+Fc3SLohUjYqA+j/Ya1gDqse3Xgv7q7WmaGHywC9CSynepkH7GH80/6EGp/SxsdfTJhvMo68jlIJz+QorrJqBwFk6y5sz8oLxPHJWCYPlzpbNiyHlMSm8=" -#define CERT_DSA \ -"ssh-dss-cert-v01@openssh.com AAAAHHNzaC1kc3MtY2VydC12MDFAb3BlbnNzaC5jb20AAAAguF716Yub+vVKNlONKLsfxGYWkRe/PyjfYdGRTsFaDvAAAACBAKwZN+OlDjrkQ6R9Bckz0E699FATR+qXKQCWz6dzP5PuGtt5JxG7zGnDOzOck2bGVbyjpxQOIeYEnk4eBqZQL03tgl5T/p+c4BmJ+A3yaorqTykoe6N7wA06JiAcuXTKIBJADf/+ozLNn5b+F6agtKYsBsSqV9ZV7JjH7C1rVWb5AAAAFQC9bJ6G9S90e9DFq9iBLmnS3lB3tQAAAIEAhED1jL5/grOqm/+ogI87fOTjZS4/tYCFJbacJtB0uUKJJPFyMqBy9c1FyTAk/jgmNIc60nL8Ay0ms8hstgboq5ZN0GUQcWIboNp+8sb6o8xIvZs+NdM6G44xsIchn7lYGRZMd4b82/XWIjTU5/1Xq1eSKDbcrfvR+WRGRcWL0x0AAACAK3phRxCQ3AbsH97kzUVmws/06RUHcHAsA6OZZ0enKG7cenBIlrdcsS+Fc3SLohUjYqA+j/Ya1gDqse3Xgv7q7WmaGHywC9CSynepkH7GH80/6EGp/SxsdfTJhvMo68jlIJz+QorrJqBwFk6y5sz8oLxPHJWCYPlzpbNiyHlMSm8AAAAAAAAD6AAAAAEAAAAHdWx5c3NlcwAAABcAAAAHdWx5c3NlcwAAAAhvZHlzc2V1cwAAAAAAAAAA//////////8AAAAAAAAAggAAABVwZXJtaXQtWDExLWZvcndhcmRpbmcAAAAAAAAAF3Blcm1pdC1hZ2VudC1mb3J3YXJkaW5nAAAAAAAAABZwZXJtaXQtcG9ydC1mb3J3YXJkaW5nAAAAAAAAAApwZXJtaXQtcHR5AAAAAAAAAA5wZXJtaXQtdXNlci1yYwAAAAAAAAAAAAAAMwAAAAtzc2gtZWQyNTUxOQAAACAz0F5hFTFS5nhUcmnyjFVoDw5L/P7kQU8JnBA2rWczAwAAAFMAAAALc3NoLWVkMjU1MTkAAABAjMQEZcbdUYJBjIC4GxByFDOb8tv71vDZdx7irHwaqIjx5rzpJUuOV1r8ZO4kY+Yaiun1yrWj2QYkfJrHBvD1DA== id_dsa.pub" -#define PRIV_ECDSA \ -"-----BEGIN OPENSSH PRIVATE KEY-----\n"\ -"b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAaAAAABNlY2RzYS\n"\ -"1zaGEyLW5pc3RwMjU2AAAACG5pc3RwMjU2AAAAQQTDJ0VlMv+0rguNzaJ1DF2KueHaxRSQ\n"\ -"6LpIxGbulrg1a8RPbnMXwag5GcDiDllD2lDUJUuBEWyjXA0rZoZX35ELAAAAoE/Bbr5PwW\n"\ -"6+AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBMMnRWUy/7SuC43N\n"\ -"onUMXYq54drFFJDoukjEZu6WuDVrxE9ucxfBqDkZwOIOWUPaUNQlS4ERbKNcDStmhlffkQ\n"\ -"sAAAAhAIhE6hCID5oOm1TDktc++KFKyScjLifcZ6Cgv5xSSyLOAAAAAAECAwQFBgc=\n"\ -"-----END OPENSSH PRIVATE KEY-----\n" -#define PUB_ECDSA \ -"ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBMMnRWUy/7SuC43NonUMXYq54drFFJDoukjEZu6WuDVrxE9ucxfBqDkZwOIOWUPaUNQlS4ERbKNcDStmhlffkQs=" -#define CERT_ECDSA \ -"ecdsa-sha2-nistp256-cert-v01@openssh.com AAAAKGVjZHNhLXNoYTItbmlzdHAyNTYtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgVJZuM/1AOe6n++qRWMyUuAThYqLvvQxj5CGflLODp60AAAAIbmlzdHAyNTYAAABBBMMnRWUy/7SuC43NonUMXYq54drFFJDoukjEZu6WuDVrxE9ucxfBqDkZwOIOWUPaUNQlS4ERbKNcDStmhlffkQsAAAAAAAAD6QAAAAEAAAAHdWx5c3NlcwAAABcAAAAHdWx5c3NlcwAAAAhvZHlzc2V1cwAAAAAAAAAA//////////8AAAAAAAAAggAAABVwZXJtaXQtWDExLWZvcndhcmRpbmcAAAAAAAAAF3Blcm1pdC1hZ2VudC1mb3J3YXJkaW5nAAAAAAAAABZwZXJtaXQtcG9ydC1mb3J3YXJkaW5nAAAAAAAAAApwZXJtaXQtcHR5AAAAAAAAAA5wZXJtaXQtdXNlci1yYwAAAAAAAAAAAAAAMwAAAAtzc2gtZWQyNTUxOQAAACAz0F5hFTFS5nhUcmnyjFVoDw5L/P7kQU8JnBA2rWczAwAAAFMAAAALc3NoLWVkMjU1MTkAAABAtdJpcF6ZmQL+ueices4QZeL7AK8Xuo08jyLgiolhjKy2jj4LSUki4aX/ZeZeJuby1ovGrfaeFAgx3itPLR7IAQ== id_ecdsa.pub" -#define PRIV_ED25519 \ -"-----BEGIN OPENSSH PRIVATE KEY-----\n"\ -"b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW\n"\ -"QyNTUxOQAAACAz0F5hFTFS5nhUcmnyjFVoDw5L/P7kQU8JnBA2rWczAwAAAIhWlP99VpT/\n"\ -"fQAAAAtzc2gtZWQyNTUxOQAAACAz0F5hFTFS5nhUcmnyjFVoDw5L/P7kQU8JnBA2rWczAw\n"\ -"AAAEDE1rlcMC0s0X3TKVZAOVavZOywwkXw8tO5dLObxaCMEDPQXmEVMVLmeFRyafKMVWgP\n"\ -"Dkv8/uRBTwmcEDatZzMDAAAAAAECAwQF\n"\ -"-----END OPENSSH PRIVATE KEY-----\n" -#define PUB_ED25519 \ -"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDPQXmEVMVLmeFRyafKMVWgPDkv8/uRBTwmcEDatZzMD" -#define CERT_ED25519 \ -"ssh-ed25519-cert-v01@openssh.com AAAAIHNzaC1lZDI1NTE5LWNlcnQtdjAxQG9wZW5zc2guY29tAAAAIMDQjYH6XRzH3j3MW1DdjCoAfvrHfgjnVGF+sLK0pBfqAAAAIDPQXmEVMVLmeFRyafKMVWgPDkv8/uRBTwmcEDatZzMDAAAAAAAAA+sAAAABAAAAB3VseXNzZXMAAAAXAAAAB3VseXNzZXMAAAAIb2R5c3NldXMAAAAAAAAAAP//////////AAAAAAAAAIIAAAAVcGVybWl0LVgxMS1mb3J3YXJkaW5nAAAAAAAAABdwZXJtaXQtYWdlbnQtZm9yd2FyZGluZwAAAAAAAAAWcGVybWl0LXBvcnQtZm9yd2FyZGluZwAAAAAAAAAKcGVybWl0LXB0eQAAAAAAAAAOcGVybWl0LXVzZXItcmMAAAAAAAAAAAAAADMAAAALc3NoLWVkMjU1MTkAAAAgM9BeYRUxUuZ4VHJp8oxVaA8OS/z+5EFPCZwQNq1nMwMAAABTAAAAC3NzaC1lZDI1NTE5AAAAQBj0og+s09/HpwdHZbzN0twooKPDWWrxGfnP1Joy6cDnY2BCSQ7zg9vbq11kLF8H/sKOTZWAQrUZ7LlChOu9Ogw= id_ed25519.pub" -#define PRIV_ECDSA_SK \ -"-----BEGIN OPENSSH PRIVATE KEY-----\n"\ -"b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAfwAAACJzay1lY2\n"\ -"RzYS1zaGEyLW5pc3RwMjU2QG9wZW5zc2guY29tAAAACG5pc3RwMjU2AAAAQQTYyU76zop1\n"\ -"VOb4DfKWYnR5b0TOC3zw8DzObAfHWB5o6xls+tOYiEleXvIEi00Da2iCK47habZTOhLyeB\n"\ -"X2Avu5AAAABHNzaDoAAAGYqUAQSKlAEEgAAAAic2stZWNkc2Etc2hhMi1uaXN0cDI1NkBv\n"\ -"cGVuc3NoLmNvbQAAAAhuaXN0cDI1NgAAAEEE2MlO+s6KdVTm+A3ylmJ0eW9Ezgt88PA8zm\n"\ -"wHx1geaOsZbPrTmIhJXl7yBItNA2togiuO4Wm2UzoS8ngV9gL7uQAAAARzc2g6AQAAAOMt\n"\ -"LS0tLUJFR0lOIEVDIFBSSVZBVEUgS0VZLS0tLS0KTUhjQ0FRRUVJSHFsZjNsWTkxZFhwUn\n"\ -"dYZDBrS0lYWmNpeDRRcDBNSU15Ny9JMUxXSTFuWG9Bb0dDQ3FHU000OQpBd0VIb1VRRFFn\n"\ -"QUUyTWxPK3M2S2RWVG0rQTN5bG1KMGVXOUV6Z3Q4OFBBOHptd0h4MWdlYU9zWmJQclRtSW\n"\ -"hKClhsN3lCSXROQTJ0b2dpdU80V20yVXpvUzhuZ1Y5Z0w3dVE9PQotLS0tLUVORCBFQyBQ\n"\ -"UklWQVRFIEtFWS0tLS0tCgAAAAAAAAAbZGptQGRqbS5zeWQuY29ycC5nb29nbGUuY29tAQ\n"\ -"IDBAUG\n"\ -"-----END OPENSSH PRIVATE KEY-----\n" -#define PUB_ECDSA_SK \ -"sk-ecdsa-sha2-nistp256@openssh.com AAAAInNrLWVjZHNhLXNoYTItbmlzdHAyNTZAb3BlbnNzaC5jb20AAAAIbmlzdHAyNTYAAABBBNjJTvrOinVU5vgN8pZidHlvRM4LfPDwPM5sB8dYHmjrGWz605iISV5e8gSLTQNraIIrjuFptlM6EvJ4FfYC+7kAAAAEc3NoOg==" -#define CERT_ECDSA_SK \ -"sk-ecdsa-sha2-nistp256-cert-v01@openssh.com AAAAK3NrLWVjZHNhLXNoYTItbmlzdHAyNTYtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgKLHtIca++5VoDrUAXU/KqGJZ7jZEnuJSTvt7VrYY9foAAAAIbmlzdHAyNTYAAABBBNjJTvrOinVU5vgN8pZidHlvRM4LfPDwPM5sB8dYHmjrGWz605iISV5e8gSLTQNraIIrjuFptlM6EvJ4FfYC+7kAAAAEc3NoOgAAAAAAAAPqAAAAAQAAAAd1bHlzc2VzAAAAFwAAAAd1bHlzc2VzAAAACG9keXNzZXVzAAAAAAAAAAD//////////wAAAAAAAACCAAAAFXBlcm1pdC1YMTEtZm9yd2FyZGluZwAAAAAAAAAXcGVybWl0LWFnZW50LWZvcndhcmRpbmcAAAAAAAAAFnBlcm1pdC1wb3J0LWZvcndhcmRpbmcAAAAAAAAACnBlcm1pdC1wdHkAAAAAAAAADnBlcm1pdC11c2VyLXJjAAAAAAAAAAAAAAAzAAAAC3NzaC1lZDI1NTE5AAAAIDPQXmEVMVLmeFRyafKMVWgPDkv8/uRBTwmcEDatZzMDAAAAUwAAAAtzc2gtZWQyNTUxOQAAAEB1naZOQDLaDr+fwn6E9x8/8HeiaUubDzPexfNQMz+m/7RD0gd5uJhHYUfDb5+/sIx1I7bUEeRIDkBbmZ2foo0E" -#define PRIV_ED25519_SK \ -"-----BEGIN OPENSSH PRIVATE KEY-----\n"\ -"b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAASgAAABpzay1zc2\n"\ -"gtZWQyNTUxOUBvcGVuc3NoLmNvbQAAACCTJtH10vWhIDxd62edvMLg9u2cwYKyqa7332je\n"\ -"RArHjAAAAARzc2g6AAAAwN7vvE3e77xNAAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY2\n"\ -"9tAAAAIJMm0fXS9aEgPF3rZ528wuD27ZzBgrKprvffaN5ECseMAAAABHNzaDoBAAAAQEsS\n"\ -"xLFiVzfpH2mt9xh8i/zmHV646Hud4QruNBAGNl8gkybR9dL1oSA8XetnnbzC4PbtnMGCsq\n"\ -"mu999o3kQKx4wAAAAAAAAAG2RqbUBkam0uc3lkLmNvcnAuZ29vZ2xlLmNvbQECAwQFBg==\n"\ -"-----END OPENSSH PRIVATE KEY-----\n" -#define PUB_ED25519_SK \ -"sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIJMm0fXS9aEgPF3rZ528wuD27ZzBgrKprvffaN5ECseMAAAABHNzaDo=" -#define CERT_ED25519_SK \ -"sk-ssh-ed25519-cert-v01@openssh.com AAAAI3NrLXNzaC1lZDI1NTE5LWNlcnQtdjAxQG9wZW5zc2guY29tAAAAIJiT+C/VLMWholFZ4xhOyJr0nSLZSFRIM3I07wUNTRPaAAAAIJMm0fXS9aEgPF3rZ528wuD27ZzBgrKprvffaN5ECseMAAAABHNzaDoAAAAAAAAD7AAAAAEAAAAHdWx5c3NlcwAAABcAAAAHdWx5c3NlcwAAAAhvZHlzc2V1cwAAAAAAAAAA//////////8AAAAAAAAAggAAABVwZXJtaXQtWDExLWZvcndhcmRpbmcAAAAAAAAAF3Blcm1pdC1hZ2VudC1mb3J3YXJkaW5nAAAAAAAAABZwZXJtaXQtcG9ydC1mb3J3YXJkaW5nAAAAAAAAAApwZXJtaXQtcHR5AAAAAAAAAA5wZXJtaXQtdXNlci1yYwAAAAAAAAAAAAAAMwAAAAtzc2gtZWQyNTUxOQAAACAz0F5hFTFS5nhUcmnyjFVoDw5L/P7kQU8JnBA2rWczAwAAAFMAAAALc3NoLWVkMjU1MTkAAABAX0Pu13B94pVR3qq8MJQGkOS1Cd7AAM1k6O2VSwyDPM/LfsWIQ4ywgxDmk3hjXWOY7BqljuMxo5VO4JymEIhQBA==" diff -ruN openssh-9.4p1/regress/misc/fuzz-harness/kex_fuzz.cc openssh-9.4p1+x509-14.2.1/regress/misc/fuzz-harness/kex_fuzz.cc --- openssh-9.4p1/regress/misc/fuzz-harness/kex_fuzz.cc 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/misc/fuzz-harness/kex_fuzz.cc 1970-01-01 02:00:00.000000000 +0200 @@ -1,460 +0,0 @@ -// libfuzzer driver for key exchange fuzzing. - - -#include -#include -#include -#include -#include - -extern "C" { - -#include "includes.h" -#include "ssherr.h" -#include "ssh_api.h" -#include "sshbuf.h" -#include "packet.h" -#include "myproposal.h" -#include "xmalloc.h" -#include "authfile.h" -#include "log.h" - -#include "fixed-keys.h" - -// Define if you want to generate traces. -/* #define STANDALONE 1 */ - -static int prepare_key(struct shared_state *st, int keytype, int bits); - -struct shared_state { - size_t nkeys; - struct sshkey **privkeys, **pubkeys; -}; - -struct test_state { - struct sshbuf *smsgs, *cmsgs; /* output, for standalone mode */ - struct sshbuf *sin, *cin; /* input; setup per-test in do_kex_with_key */ - struct sshbuf *s_template, *c_template; /* main copy of input */ -}; - -static int -do_send_and_receive(struct ssh *from, struct ssh *to, - struct sshbuf *store, int clobber, size_t *n) -{ - u_char type; - size_t len; - const u_char *buf; - int r; - - for (*n = 0;; (*n)++) { - if ((r = ssh_packet_next(from, &type)) != 0) { - debug_fr(r, "ssh_packet_next"); - return r; - } - if (type != 0) - return 0; - buf = ssh_output_ptr(from, &len); - debug_f("%zu%s", len, clobber ? " ignore" : ""); - if (len == 0) - return 0; - if ((r = ssh_output_consume(from, len)) != 0) { - debug_fr(r, "ssh_output_consume"); - return r; - } - if (store != NULL && (r = sshbuf_put(store, buf, len)) != 0) { - debug_fr(r, "sshbuf_put"); - return r; - } - if (!clobber && (r = ssh_input_append(to, buf, len)) != 0) { - debug_fr(r, "ssh_input_append"); - return r; - } - } -} - -static int -run_kex(struct test_state *ts, struct ssh *client, struct ssh *server) -{ - int r = 0; - size_t cn, sn; - - /* If fuzzing, replace server/client input */ - if (ts->sin != NULL) { - if ((r = ssh_input_append(server, sshbuf_ptr(ts->sin), - sshbuf_len(ts->sin))) != 0) { - error_fr(r, "ssh_input_append"); - return r; - } - sshbuf_reset(ts->sin); - } - if (ts->cin != NULL) { - if ((r = ssh_input_append(client, sshbuf_ptr(ts->cin), - sshbuf_len(ts->cin))) != 0) { - error_fr(r, "ssh_input_append"); - return r; - } - sshbuf_reset(ts->cin); - } - while (!server->kex->done || !client->kex->done) { - cn = sn = 0; - debug_f("S:"); - if ((r = do_send_and_receive(server, client, - ts->smsgs, ts->cin != NULL, &sn)) != 0) { - debug_fr(r, "S->C"); - break; - } - debug_f("C:"); - if ((r = do_send_and_receive(client, server, - ts->cmsgs, ts->sin != NULL, &cn)) != 0) { - debug_fr(r, "C->S"); - break; - } - if (cn == 0 && sn == 0) { - debug_f("kex stalled"); - r = SSH_ERR_PROTOCOL_ERROR; - break; - } - } - debug_fr(r, "done"); - return r; -} - -static void -store_key(struct shared_state *st, struct sshkey *pubkey, - struct sshkey *privkey) -{ - if (st == NULL || pubkey->type < 0 || pubkey->type > INT_MAX || - privkey->type != pubkey->type || - ((size_t)pubkey->type < st->nkeys && - st->pubkeys[pubkey->type] != NULL)) - abort(); - if ((size_t)pubkey->type >= st->nkeys) { - st->pubkeys = (struct sshkey **)xrecallocarray(st->pubkeys, - st->nkeys, pubkey->type + 1, sizeof(*st->pubkeys)); - st->privkeys = (struct sshkey **)xrecallocarray(st->privkeys, - st->nkeys, privkey->type + 1, sizeof(*st->privkeys)); - st->nkeys = privkey->type + 1; - } - debug_f("store %s at %d", sshkey_ssh_name(pubkey), pubkey->type); - st->pubkeys[pubkey->type] = pubkey; - st->privkeys[privkey->type] = privkey; -} - -static int -prepare_keys(struct shared_state *st) -{ - if (prepare_key(st, KEY_RSA, 2048) != 0 || - prepare_key(st, KEY_DSA, 1024) != 0 || - prepare_key(st, KEY_ECDSA, 256) != 0 || - prepare_key(st, KEY_ED25519, 256) != 0) { - error_f("key prepare failed"); - return -1; - } - return 0; -} - -static struct sshkey * -get_pubkey(struct shared_state *st, int keytype) -{ - if (st == NULL || keytype < 0 || (size_t)keytype >= st->nkeys || - st->pubkeys == NULL || st->pubkeys[keytype] == NULL) - abort(); - return st->pubkeys[keytype]; -} - -static struct sshkey * -get_privkey(struct shared_state *st, int keytype) -{ - if (st == NULL || keytype < 0 || (size_t)keytype >= st->nkeys || - st->privkeys == NULL || st->privkeys[keytype] == NULL) - abort(); - return st->privkeys[keytype]; -} - -static int -do_kex_with_key(struct shared_state *st, struct test_state *ts, - const char *kex, int keytype) -{ - struct ssh *client = NULL, *server = NULL; - struct sshkey *privkey = NULL, *pubkey = NULL; - struct sshbuf *state = NULL; - struct kex_params kex_params; - const char *ccp, *proposal[PROPOSAL_MAX] = { KEX_CLIENT }; - char *myproposal[PROPOSAL_MAX] = {0}, *keyname = NULL; - int i, r; - - ts->cin = ts->sin = NULL; - if (ts->c_template != NULL && - (ts->cin = sshbuf_fromb(ts->c_template)) == NULL) - abort(); - if (ts->s_template != NULL && - (ts->sin = sshbuf_fromb(ts->s_template)) == NULL) - abort(); - - pubkey = get_pubkey(st, keytype); - privkey = get_privkey(st, keytype); - keyname = xstrdup(sshkey_ssh_name(privkey)); - if (ts->cin != NULL) { - debug_f("%s %s clobber client %zu", kex, keyname, - sshbuf_len(ts->cin)); - } else if (ts->sin != NULL) { - debug_f("%s %s clobber server %zu", kex, keyname, - sshbuf_len(ts->sin)); - } else - debug_f("%s %s noclobber", kex, keyname); - - for (i = 0; i < PROPOSAL_MAX; i++) { - ccp = proposal[i]; -#ifdef CIPHER_NONE_AVAIL - if (i == PROPOSAL_ENC_ALGS_CTOS || i == PROPOSAL_ENC_ALGS_STOC) - ccp = "none"; -#endif - if (i == PROPOSAL_SERVER_HOST_KEY_ALGS) - ccp = keyname; - else if (i == PROPOSAL_KEX_ALGS && kex != NULL) - ccp = kex; - if ((myproposal[i] = strdup(ccp)) == NULL) { - error_f("strdup prop %d", i); - goto fail; - } - } - memcpy(kex_params.proposal, myproposal, sizeof(myproposal)); - if ((r = ssh_init(&client, 0, &kex_params)) != 0) { - error_fr(r, "init client"); - goto fail; - } - if ((r = ssh_init(&server, 1, &kex_params)) != 0) { - error_fr(r, "init server"); - goto fail; - } - if ((r = ssh_add_hostkey(server, privkey)) != 0 || - (r = ssh_add_hostkey(client, pubkey)) != 0) { - error_fr(r, "add hostkeys"); - goto fail; - } - if ((r = run_kex(ts, client, server)) != 0) { - error_fr(r, "kex"); - goto fail; - } - /* XXX rekex, set_state, etc */ - fail: - for (i = 0; i < PROPOSAL_MAX; i++) - free(myproposal[i]); - sshbuf_free(ts->sin); - sshbuf_free(ts->cin); - sshbuf_free(state); - ssh_free(client); - ssh_free(server); - free(keyname); - return r; -} - -static int -prepare_key(struct shared_state *st, int kt, int bits) -{ - const char *pubstr = NULL; - const char *privstr = NULL; - char *tmp, *cp; - struct sshkey *privkey = NULL, *pubkey = NULL; - struct sshbuf *b = NULL; - int r; - - switch (kt) { - case KEY_RSA: - pubstr = PUB_RSA; - privstr = PRIV_RSA; - break; - case KEY_DSA: - pubstr = PUB_DSA; - privstr = PRIV_DSA; - break; - case KEY_ECDSA: - pubstr = PUB_ECDSA; - privstr = PRIV_ECDSA; - break; - case KEY_ED25519: - pubstr = PUB_ED25519; - privstr = PRIV_ED25519; - break; - default: - abort(); - } - if ((b = sshbuf_from(privstr, strlen(privstr))) == NULL) - abort(); - if ((r = sshkey_parse_private_fileblob(b, "", &privkey, NULL)) != 0) { - error_fr(r, "priv %d", kt); - abort(); - } - sshbuf_free(b); - tmp = cp = xstrdup(pubstr); - if ((pubkey = sshkey_new(KEY_UNSPEC)) == NULL) - abort(); - if ((r = sshkey_read(pubkey, &cp)) != 0) { - error_fr(r, "pub %d", kt); - abort(); - } - free(tmp); - - store_key(st, pubkey, privkey); - return 0; -} - -#if defined(STANDALONE) - -#if 0 /* use this if generating new keys to embed above */ -static int -prepare_key(struct shared_state *st, int keytype, int bits) -{ - struct sshkey *privkey = NULL, *pubkey = NULL; - int r; - - if ((r = sshkey_generate(keytype, bits, &privkey)) != 0) { - error_fr(r, "generate"); - abort(); - } - if ((r = sshkey_from_private(privkey, &pubkey)) != 0) { - error_fr(r, "make pubkey"); - abort(); - } - store_key(st, pubkey, privkey); - return 0; -} -#endif - -int main(void) -{ - static struct shared_state *st; - struct test_state *ts; - const int keytypes[] = { KEY_RSA, KEY_DSA, KEY_ECDSA, KEY_ED25519, -1 }; - static const char * const kextypes[] = { - "sntrup761x25519-sha512@openssh.com", - "curve25519-sha256@libssh.org", - "ecdh-sha2-nistp256", - "diffie-hellman-group1-sha1", - "diffie-hellman-group-exchange-sha1", - NULL, - }; - int i, j; - char *path; - FILE *f; - - log_init("kex_fuzz", SYSLOG_LEVEL_DEBUG3, SYSLOG_FACILITY_AUTH, 1); - - if (st == NULL) { - st = (struct shared_state *)xcalloc(1, sizeof(*st)); - prepare_keys(st); - } - /* Run each kex method for each key and save client/server packets */ - for (i = 0; keytypes[i] != -1; i++) { - for (j = 0; kextypes[j] != NULL; j++) { - ts = (struct test_state *)xcalloc(1, sizeof(*ts)); - ts->smsgs = sshbuf_new(); - ts->cmsgs = sshbuf_new(); - do_kex_with_key(st, ts, kextypes[j], keytypes[i]); - xasprintf(&path, "S2C-%s-%s", - kextypes[j], sshkey_type(st->pubkeys[keytypes[i]])); - debug_f("%s", path); - if ((f = fopen(path, "wb+")) == NULL) - abort(); - if (fwrite(sshbuf_ptr(ts->smsgs), 1, - sshbuf_len(ts->smsgs), f) != sshbuf_len(ts->smsgs)) - abort(); - fclose(f); - free(path); - //sshbuf_dump(ts->smsgs, stderr); - xasprintf(&path, "C2S-%s-%s", - kextypes[j], sshkey_type(st->pubkeys[keytypes[i]])); - debug_f("%s", path); - if ((f = fopen(path, "wb+")) == NULL) - abort(); - if (fwrite(sshbuf_ptr(ts->cmsgs), 1, - sshbuf_len(ts->cmsgs), f) != sshbuf_len(ts->cmsgs)) - abort(); - fclose(f); - free(path); - //sshbuf_dump(ts->cmsgs, stderr); - sshbuf_free(ts->smsgs); - sshbuf_free(ts->cmsgs); - free(ts); - } - } - for (i = 0; keytypes[i] != -1; i++) { - xasprintf(&path, "%s.priv", - sshkey_type(st->privkeys[keytypes[i]])); - debug_f("%s", path); - if (sshkey_save_private(st->privkeys[keytypes[i]], path, - "", "", SSHKEY_PRIVATE_OPENSSH, NULL, 0) != 0) - abort(); - free(path); - xasprintf(&path, "%s.pub", - sshkey_type(st->pubkeys[keytypes[i]])); - debug_f("%s", path); - if (sshkey_save_public(st->pubkeys[keytypes[i]], path, "") != 0) - abort(); - free(path); - } -} -#else /* !STANDALONE */ -static void -do_kex(struct shared_state *st, struct test_state *ts, const char *kex) -{ - do_kex_with_key(st, ts, kex, KEY_RSA); - do_kex_with_key(st, ts, kex, KEY_DSA); - do_kex_with_key(st, ts, kex, KEY_ECDSA); - do_kex_with_key(st, ts, kex, KEY_ED25519); -} - -static void -kex_tests(struct shared_state *st, struct test_state *ts) -{ - do_kex(st, ts, "sntrup761x25519-sha512@openssh.com"); - do_kex(st, ts, "curve25519-sha256@libssh.org"); - do_kex(st, ts, "ecdh-sha2-nistp256"); - do_kex(st, ts, "diffie-hellman-group1-sha1"); - do_kex(st, ts, "diffie-hellman-group-exchange-sha1"); -} - -int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) -{ - static struct shared_state *st; - struct test_state *ts; - u_char crbuf[SSH_MAX_PRE_BANNER_LINES * 4]; - u_char zbuf[4096] = {0}; - static LogLevel loglevel = SYSLOG_LEVEL_INFO; - - if (st == NULL) { - if (getenv("DEBUG") != NULL || getenv("KEX_FUZZ_DEBUG") != NULL) - loglevel = SYSLOG_LEVEL_DEBUG3; - log_init("kex_fuzz", - loglevel, SYSLOG_FACILITY_AUTH, 1); - st = (struct shared_state *)xcalloc(1, sizeof(*st)); - prepare_keys(st); - } - - /* Ensure that we can complete (fail) banner exchange at least */ - memset(crbuf, '\n', sizeof(crbuf)); - - ts = (struct test_state *)xcalloc(1, sizeof(*ts)); - if ((ts->s_template = sshbuf_new()) == NULL || - sshbuf_put(ts->s_template, data, size) != 0 || - sshbuf_put(ts->s_template, crbuf, sizeof(crbuf)) != 0 || - sshbuf_put(ts->s_template, zbuf, sizeof(zbuf)) != 0) - abort(); - kex_tests(st, ts); - sshbuf_free(ts->s_template); - free(ts); - - ts = (struct test_state *)xcalloc(1, sizeof(*ts)); - if ((ts->c_template = sshbuf_new()) == NULL || - sshbuf_put(ts->c_template, data, size) != 0 || - sshbuf_put(ts->c_template, crbuf, sizeof(crbuf)) != 0 || - sshbuf_put(ts->c_template, zbuf, sizeof(zbuf)) != 0) - abort(); - kex_tests(st, ts); - sshbuf_free(ts->c_template); - free(ts); - - return 0; -} -#endif /* STANDALONE */ -} /* extern "C" */ diff -ruN openssh-9.4p1/regress/misc/fuzz-harness/Makefile openssh-9.4p1+x509-14.2.1/regress/misc/fuzz-harness/Makefile --- openssh-9.4p1/regress/misc/fuzz-harness/Makefile 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/misc/fuzz-harness/Makefile 2023-08-20 10:07:00.000000000 +0300 @@ -1,55 +1,30 @@ # NB. libssh and libopenbsd-compat should be built with the same sanitizer opts. -CC=clang-11 -CXX=clang++-11 -FUZZ_FLAGS=-fsanitize=address,fuzzer -fno-omit-frame-pointer +CXX=clang++-3.9 +FUZZ_FLAGS=-fsanitize=address,undefined -fsanitize-coverage=edge FUZZ_LIBS=-lFuzzer -CXXFLAGS=-O2 -g -Wall -Wextra -Wno-unused-parameter -I ../../.. $(FUZZ_FLAGS) -CFLAGS=$(CXXFLAGS) +CXXFLAGS=-O2 -g -Wall -Wextra -I ../../.. $(FUZZ_FLAGS) LDFLAGS=-L ../../.. -L ../../../openbsd-compat -g $(FUZZ_FLAGS) -LIBS=-lssh -lopenbsd-compat -lmd -lcrypto -lfido2 -lcbor $(FUZZ_LIBS) -SK_NULL_OBJS=ssh-sk-null.o -COMMON_DEPS=../../../libssh.a +LIBS=-lssh -lopenbsd-compat -lcrypto $(FUZZ_LIBS) -TARGETS=pubkey_fuzz sig_fuzz authopt_fuzz authkeys_fuzz sshsig_fuzz \ - sshsigopt_fuzz privkey_fuzz kex_fuzz agent_fuzz +TARGETS=pubkey_fuzz sig_fuzz authopt_fuzz privkey_fuzz all: $(TARGETS) .cc.o: $(CXX) $(CXXFLAGS) -c $< -o $@ -pubkey_fuzz: pubkey_fuzz.o $(SK_NULL_OBJS) $(COMMON_DEPS) - $(CXX) -o $@ pubkey_fuzz.o $(SK_NULL_OBJS) $(LDFLAGS) $(LIBS) +pubkey_fuzz: pubkey_fuzz.o + $(CXX) -o $@ pubkey_fuzz.o $(LDFLAGS) $(LIBS) -sig_fuzz: sig_fuzz.o $(SK_NULL_OBJS) $(COMMON_DEPS) - $(CXX) -o $@ sig_fuzz.o $(SK_NULL_OBJS) $(LDFLAGS) $(LIBS) +sig_fuzz: sig_fuzz.o + $(CXX) -o $@ sig_fuzz.o $(LDFLAGS) $(LIBS) -authopt_fuzz: authopt_fuzz.o $(SK_NULL_OBJS) $(COMMON_DEPS) - $(CXX) -o $@ authopt_fuzz.o $(SK_NULL_OBJS) ../../../auth-options.o $(LDFLAGS) $(LIBS) +authopt_fuzz: authopt_fuzz.o + $(CXX) -o $@ authopt_fuzz.o ../../../auth-options.o $(LDFLAGS) $(LIBS) -authkeys_fuzz: authkeys_fuzz.o $(SK_NULL_OBJS) $(COMMON_DEPS) - $(CXX) -o $@ authkeys_fuzz.o $(SK_NULL_OBJS) ../../../auth-options.o ../../../auth2-pubkeyfile.o $(LDFLAGS) $(LIBS) - -sshsig_fuzz: sshsig_fuzz.o $(SK_NULL_OBJS) $(COMMON_DEPS) - $(CXX) -o $@ sshsig_fuzz.o $(SK_NULL_OBJS) ../../../sshsig.o $(LDFLAGS) $(LIBS) - -sshsigopt_fuzz: sshsigopt_fuzz.o $(SK_NULL_OBJS) $(COMMON_DEPS) - $(CXX) -o $@ sshsigopt_fuzz.o $(SK_NULL_OBJS) ../../../sshsig.o $(LDFLAGS) $(LIBS) - -privkey_fuzz: privkey_fuzz.o $(SK_NULL_OBJS) $(COMMON_DEPS) - $(CXX) -o $@ privkey_fuzz.o $(SK_NULL_OBJS) $(LDFLAGS) $(LIBS) - -kex_fuzz: kex_fuzz.o $(SK_NULL_OBJS) $(COMMON_DEPS) - $(CXX) -o $@ kex_fuzz.o $(SK_NULL_OBJS) $(LDFLAGS) $(LIBS) -lz - -agent_fuzz: agent_fuzz.o agent_fuzz_helper.o sk-dummy.o ../../../ssh-sk.o $(COMMON_DEPS) - $(CXX) -o $@ agent_fuzz.o agent_fuzz_helper.o sk-dummy.o ../../../ssh-sk.o $(LDFLAGS) $(LIBS) -lz - -agent_fuzz_helper.o: agent_fuzz_helper.c ../../../ssh-agent.c - -sk-dummy.o: ../sk-dummy/sk-dummy.c - $(CC) $(CFLAGS) -c -o $@ ../sk-dummy/sk-dummy.c -DSK_DUMMY_INTEGRATE=1 $(LDFLAGS) +privkey_fuzz: privkey_fuzz.o + $(CXX) -o $@ privkey_fuzz.o $(LDFLAGS) $(LIBS) clean: - -rm -f *.o $(TARGETS) + -rm -f *.o pubkey_fuzz sig_fuzz authopt_fuzz privkey_fuzz diff -ruN openssh-9.4p1/regress/misc/fuzz-harness/privkey_fuzz.cc openssh-9.4p1+x509-14.2.1/regress/misc/fuzz-harness/privkey_fuzz.cc --- openssh-9.4p1/regress/misc/fuzz-harness/privkey_fuzz.cc 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/misc/fuzz-harness/privkey_fuzz.cc 2023-08-20 10:07:00.000000000 +0300 @@ -18,4 +18,3 @@ } } // extern - diff -ruN openssh-9.4p1/regress/misc/fuzz-harness/sig_fuzz.cc openssh-9.4p1+x509-14.2.1/regress/misc/fuzz-harness/sig_fuzz.cc --- openssh-9.4p1/regress/misc/fuzz-harness/sig_fuzz.cc 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/misc/fuzz-harness/sig_fuzz.cc 2023-08-20 10:07:00.000000000 +0300 @@ -31,31 +31,19 @@ static struct sshkey *ecdsa384 = generate_or_die(KEY_ECDSA, 384); static struct sshkey *ecdsa521 = generate_or_die(KEY_ECDSA, 521); #endif - struct sshkey_sig_details *details = NULL; static struct sshkey *ed25519 = generate_or_die(KEY_ED25519, 0); static const char *data = "If everyone started announcing his nose had " "run away, I don’t know how it would all end"; static const size_t dlen = strlen(data); #ifdef WITH_OPENSSL - sshkey_verify(rsa, sig, slen, (const u_char *)data, dlen, NULL, 0, &details); - sshkey_sig_details_free(details); - details = NULL; - sshkey_verify(dsa, sig, slen, (const u_char *)data, dlen, NULL, 0, &details); - sshkey_sig_details_free(details); - details = NULL; - sshkey_verify(ecdsa256, sig, slen, (const u_char *)data, dlen, NULL, 0, &details); - sshkey_sig_details_free(details); - details = NULL; - sshkey_verify(ecdsa384, sig, slen, (const u_char *)data, dlen, NULL, 0, &details); - sshkey_sig_details_free(details); - details = NULL; - sshkey_verify(ecdsa521, sig, slen, (const u_char *)data, dlen, NULL, 0, &details); - sshkey_sig_details_free(details); - details = NULL; + sshkey_verify(rsa, sig, slen, (const u_char *)data, dlen, NULL, 0); + sshkey_verify(dsa, sig, slen, (const u_char *)data, dlen, NULL, 0); + sshkey_verify(ecdsa256, sig, slen, (const u_char *)data, dlen, NULL, 0); + sshkey_verify(ecdsa384, sig, slen, (const u_char *)data, dlen, NULL, 0); + sshkey_verify(ecdsa521, sig, slen, (const u_char *)data, dlen, NULL, 0); #endif - sshkey_verify(ed25519, sig, slen, (const u_char *)data, dlen, NULL, 0, &details); - sshkey_sig_details_free(details); + sshkey_verify(ed25519, sig, slen, (const u_char *)data, dlen, NULL, 0); return 0; } diff -ruN openssh-9.4p1/regress/misc/fuzz-harness/sshsig_fuzz.cc openssh-9.4p1+x509-14.2.1/regress/misc/fuzz-harness/sshsig_fuzz.cc --- openssh-9.4p1/regress/misc/fuzz-harness/sshsig_fuzz.cc 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/misc/fuzz-harness/sshsig_fuzz.cc 1970-01-01 02:00:00.000000000 +0200 @@ -1,37 +0,0 @@ -// cc_fuzz_target test for sshsig verification. - -#include -#include -#include -#include -#include - -extern "C" { - -#include "includes.h" -#include "sshkey.h" -#include "ssherr.h" -#include "sshbuf.h" -#include "sshsig.h" -#include "log.h" - -int LLVMFuzzerTestOneInput(const uint8_t* sig, size_t slen) -{ - static const char *data = "If everyone started announcing his nose had " - "run away, I don’t know how it would all end"; - struct sshbuf *signature = sshbuf_from(sig, slen); - struct sshbuf *message = sshbuf_from(data, strlen(data)); - struct sshkey *k = NULL; - struct sshkey_sig_details *details = NULL; - extern char *__progname; - - log_init(__progname, SYSLOG_LEVEL_QUIET, SYSLOG_FACILITY_USER, 1); - sshsig_verifyb(signature, message, "castle", &k, &details); - sshkey_sig_details_free(details); - sshkey_free(k); - sshbuf_free(signature); - sshbuf_free(message); - return 0; -} - -} // extern diff -ruN openssh-9.4p1/regress/misc/fuzz-harness/sshsigopt_fuzz.cc openssh-9.4p1+x509-14.2.1/regress/misc/fuzz-harness/sshsigopt_fuzz.cc --- openssh-9.4p1/regress/misc/fuzz-harness/sshsigopt_fuzz.cc 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/misc/fuzz-harness/sshsigopt_fuzz.cc 1970-01-01 02:00:00.000000000 +0200 @@ -1,29 +0,0 @@ -#include -#include -#include -#include -#include - -extern "C" { - -#include "sshsig.h" - -int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) -{ - char *cp = (char *)malloc(size + 1); - struct sshsigopt *opts = NULL; - - if (cp == NULL) - goto out; - memcpy(cp, data, size); - cp[size] = '\0'; - if ((opts = sshsigopt_parse(cp, "libfuzzer", 0, NULL)) == NULL) - goto out; - - out: - free(cp); - sshsigopt_free(opts); - return 0; -} - -} // extern "C" diff -ruN openssh-9.4p1/regress/misc/fuzz-harness/ssh-sk-null.cc openssh-9.4p1+x509-14.2.1/regress/misc/fuzz-harness/ssh-sk-null.cc --- openssh-9.4p1/regress/misc/fuzz-harness/ssh-sk-null.cc 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/misc/fuzz-harness/ssh-sk-null.cc 1970-01-01 02:00:00.000000000 +0200 @@ -1,52 +0,0 @@ -/* $OpenBSD$ */ -/* - * Copyright (c) 2019 Google LLC - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -extern "C" { - -#include "includes.h" - -#include - -#include "ssherr.h" -#include "ssh-sk.h" - -int -sshsk_enroll(int type, const char *provider_path, const char *device, - const char *application, const char *userid, uint8_t flags, - const char *pin, struct sshbuf *challenge_buf, - struct sshkey **keyp, struct sshbuf *attest) -{ - return SSH_ERR_FEATURE_UNSUPPORTED; -} - -int -sshsk_sign(const char *provider_path, struct sshkey *key, - u_char **sigp, size_t *lenp, const u_char *data, size_t datalen, - u_int compat, const char *pin) -{ - return SSH_ERR_FEATURE_UNSUPPORTED; -} - -int -sshsk_load_resident(const char *provider_path, const char *device, - const char *pin, u_int flags, struct sshsk_resident_key ***srksp, - size_t *nsrksp) -{ - return SSH_ERR_FEATURE_UNSUPPORTED; -} - -}; diff -ruN openssh-9.4p1/regress/misc/fuzz-harness/testdata/create-agent-corpus.sh openssh-9.4p1+x509-14.2.1/regress/misc/fuzz-harness/testdata/create-agent-corpus.sh --- openssh-9.4p1/regress/misc/fuzz-harness/testdata/create-agent-corpus.sh 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/misc/fuzz-harness/testdata/create-agent-corpus.sh 1970-01-01 02:00:00.000000000 +0200 @@ -1,44 +0,0 @@ -#!/bin/sh - -# Exercise ssh-agent to generate fuzzing corpus - -# XXX assumes agent hacked up with sk-dummy.o and ssh-sk.o linked directly -# and dumping of e->request for each message. - -set -xe -SSH_AUTH_SOCK=$PWD/sock -rm -f agent-[0-9]* $SSH_AUTH_SOCK -export SSH_AUTH_SOCK -../../../../ssh-agent -D -a $SSH_AUTH_SOCK & -sleep 1 -AGENT_PID=$! -trap "kill $AGENT_PID" EXIT - -PRIV="id_dsa id_ecdsa id_ecdsa_sk id_ed25519 id_ed25519_sk id_rsa" - -# add keys -ssh-add $PRIV - -# sign -ssh-add -T *.pub - -# list -ssh-add -l - -# remove individually -ssh-add -d $PRIV - -# re-add with constraints -ssh-add -c -t 3h $PRIV - -# delete all -ssh-add -D - -# attempt to add a PKCS#11 token -ssh-add -s /fake || : - -# attempt to delete PKCS#11 -ssh-add -e /fake || : - -ssh-add -L - diff -ruN openssh-9.4p1/regress/misc/fuzz-harness/testdata/id_dsa openssh-9.4p1+x509-14.2.1/regress/misc/fuzz-harness/testdata/id_dsa --- openssh-9.4p1/regress/misc/fuzz-harness/testdata/id_dsa 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/misc/fuzz-harness/testdata/id_dsa 1970-01-01 02:00:00.000000000 +0200 @@ -1,21 +0,0 @@ ------BEGIN OPENSSH PRIVATE KEY----- -b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABsgAAAAdzc2gtZH -NzAAAAgQCsGTfjpQ465EOkfQXJM9BOvfRQE0fqlykAls+ncz+T7hrbeScRu8xpwzsznJNm -xlW8o6cUDiHmBJ5OHgamUC9N7YJeU/6fnOAZifgN8mqK6k8pKHuje8ANOiYgHLl0yiASQA -3//qMyzZ+W/hemoLSmLAbEqlfWVeyYx+wta1Vm+QAAABUAvWyehvUvdHvQxavYgS5p0t5Q -d7UAAACBAIRA9Yy+f4Kzqpv/qICPO3zk42UuP7WAhSW2nCbQdLlCiSTxcjKgcvXNRckwJP -44JjSHOtJy/AMtJrPIbLYG6KuWTdBlEHFiG6DafvLG+qPMSL2bPjXTOhuOMbCHIZ+5WBkW -THeG/Nv11iI01Of9V6tXkig23K370flkRkXFi9MdAAAAgCt6YUcQkNwG7B/e5M1FZsLP9O -kVB3BwLAOjmWdHpyhu3HpwSJa3XLEvhXN0i6IVI2KgPo/2GtYA6rHt14L+6u1pmhh8sAvQ -ksp3qZB+xh/NP+hBqf0sbHX0yYbzKOvI5SCc/kKK6yagcBZOsubM/KC8TxyVgmD5c6WzYs -h5TEpvAAAB2PHjRbbx40W2AAAAB3NzaC1kc3MAAACBAKwZN+OlDjrkQ6R9Bckz0E699FAT -R+qXKQCWz6dzP5PuGtt5JxG7zGnDOzOck2bGVbyjpxQOIeYEnk4eBqZQL03tgl5T/p+c4B -mJ+A3yaorqTykoe6N7wA06JiAcuXTKIBJADf/+ozLNn5b+F6agtKYsBsSqV9ZV7JjH7C1r -VWb5AAAAFQC9bJ6G9S90e9DFq9iBLmnS3lB3tQAAAIEAhED1jL5/grOqm/+ogI87fOTjZS -4/tYCFJbacJtB0uUKJJPFyMqBy9c1FyTAk/jgmNIc60nL8Ay0ms8hstgboq5ZN0GUQcWIb -oNp+8sb6o8xIvZs+NdM6G44xsIchn7lYGRZMd4b82/XWIjTU5/1Xq1eSKDbcrfvR+WRGRc -WL0x0AAACAK3phRxCQ3AbsH97kzUVmws/06RUHcHAsA6OZZ0enKG7cenBIlrdcsS+Fc3SL -ohUjYqA+j/Ya1gDqse3Xgv7q7WmaGHywC9CSynepkH7GH80/6EGp/SxsdfTJhvMo68jlIJ -z+QorrJqBwFk6y5sz8oLxPHJWCYPlzpbNiyHlMSm8AAAAUUA+OGldMi76ClO/sstpdbBUE -lq8AAAAAAQI= ------END OPENSSH PRIVATE KEY----- diff -ruN openssh-9.4p1/regress/misc/fuzz-harness/testdata/id_dsa-cert.pub openssh-9.4p1+x509-14.2.1/regress/misc/fuzz-harness/testdata/id_dsa-cert.pub --- openssh-9.4p1/regress/misc/fuzz-harness/testdata/id_dsa-cert.pub 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/misc/fuzz-harness/testdata/id_dsa-cert.pub 1970-01-01 02:00:00.000000000 +0200 @@ -1 +0,0 @@ -ssh-dss-cert-v01@openssh.com AAAAHHNzaC1kc3MtY2VydC12MDFAb3BlbnNzaC5jb20AAAAguF716Yub+vVKNlONKLsfxGYWkRe/PyjfYdGRTsFaDvAAAACBAKwZN+OlDjrkQ6R9Bckz0E699FATR+qXKQCWz6dzP5PuGtt5JxG7zGnDOzOck2bGVbyjpxQOIeYEnk4eBqZQL03tgl5T/p+c4BmJ+A3yaorqTykoe6N7wA06JiAcuXTKIBJADf/+ozLNn5b+F6agtKYsBsSqV9ZV7JjH7C1rVWb5AAAAFQC9bJ6G9S90e9DFq9iBLmnS3lB3tQAAAIEAhED1jL5/grOqm/+ogI87fOTjZS4/tYCFJbacJtB0uUKJJPFyMqBy9c1FyTAk/jgmNIc60nL8Ay0ms8hstgboq5ZN0GUQcWIboNp+8sb6o8xIvZs+NdM6G44xsIchn7lYGRZMd4b82/XWIjTU5/1Xq1eSKDbcrfvR+WRGRcWL0x0AAACAK3phRxCQ3AbsH97kzUVmws/06RUHcHAsA6OZZ0enKG7cenBIlrdcsS+Fc3SLohUjYqA+j/Ya1gDqse3Xgv7q7WmaGHywC9CSynepkH7GH80/6EGp/SxsdfTJhvMo68jlIJz+QorrJqBwFk6y5sz8oLxPHJWCYPlzpbNiyHlMSm8AAAAAAAAD6AAAAAEAAAAHdWx5c3NlcwAAABcAAAAHdWx5c3NlcwAAAAhvZHlzc2V1cwAAAAAAAAAA//////////8AAAAAAAAAggAAABVwZXJtaXQtWDExLWZvcndhcmRpbmcAAAAAAAAAF3Blcm1pdC1hZ2VudC1mb3J3YXJkaW5nAAAAAAAAABZwZXJtaXQtcG9ydC1mb3J3YXJkaW5nAAAAAAAAAApwZXJtaXQtcHR5AAAAAAAAAA5wZXJtaXQtdXNlci1yYwAAAAAAAAAAAAAAMwAAAAtzc2gtZWQyNTUxOQAAACAz0F5hFTFS5nhUcmnyjFVoDw5L/P7kQU8JnBA2rWczAwAAAFMAAAALc3NoLWVkMjU1MTkAAABAjMQEZcbdUYJBjIC4GxByFDOb8tv71vDZdx7irHwaqIjx5rzpJUuOV1r8ZO4kY+Yaiun1yrWj2QYkfJrHBvD1DA== id_dsa.pub diff -ruN openssh-9.4p1/regress/misc/fuzz-harness/testdata/id_dsa.pub openssh-9.4p1+x509-14.2.1/regress/misc/fuzz-harness/testdata/id_dsa.pub --- openssh-9.4p1/regress/misc/fuzz-harness/testdata/id_dsa.pub 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/misc/fuzz-harness/testdata/id_dsa.pub 1970-01-01 02:00:00.000000000 +0200 @@ -1 +0,0 @@ -ssh-dss AAAAB3NzaC1kc3MAAACBAKwZN+OlDjrkQ6R9Bckz0E699FATR+qXKQCWz6dzP5PuGtt5JxG7zGnDOzOck2bGVbyjpxQOIeYEnk4eBqZQL03tgl5T/p+c4BmJ+A3yaorqTykoe6N7wA06JiAcuXTKIBJADf/+ozLNn5b+F6agtKYsBsSqV9ZV7JjH7C1rVWb5AAAAFQC9bJ6G9S90e9DFq9iBLmnS3lB3tQAAAIEAhED1jL5/grOqm/+ogI87fOTjZS4/tYCFJbacJtB0uUKJJPFyMqBy9c1FyTAk/jgmNIc60nL8Ay0ms8hstgboq5ZN0GUQcWIboNp+8sb6o8xIvZs+NdM6G44xsIchn7lYGRZMd4b82/XWIjTU5/1Xq1eSKDbcrfvR+WRGRcWL0x0AAACAK3phRxCQ3AbsH97kzUVmws/06RUHcHAsA6OZZ0enKG7cenBIlrdcsS+Fc3SLohUjYqA+j/Ya1gDqse3Xgv7q7WmaGHywC9CSynepkH7GH80/6EGp/SxsdfTJhvMo68jlIJz+QorrJqBwFk6y5sz8oLxPHJWCYPlzpbNiyHlMSm8= diff -ruN openssh-9.4p1/regress/misc/fuzz-harness/testdata/id_ecdsa openssh-9.4p1+x509-14.2.1/regress/misc/fuzz-harness/testdata/id_ecdsa --- openssh-9.4p1/regress/misc/fuzz-harness/testdata/id_ecdsa 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/misc/fuzz-harness/testdata/id_ecdsa 1970-01-01 02:00:00.000000000 +0200 @@ -1,8 +0,0 @@ ------BEGIN OPENSSH PRIVATE KEY----- -b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAaAAAABNlY2RzYS -1zaGEyLW5pc3RwMjU2AAAACG5pc3RwMjU2AAAAQQTDJ0VlMv+0rguNzaJ1DF2KueHaxRSQ -6LpIxGbulrg1a8RPbnMXwag5GcDiDllD2lDUJUuBEWyjXA0rZoZX35ELAAAAoE/Bbr5PwW -6+AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBMMnRWUy/7SuC43N -onUMXYq54drFFJDoukjEZu6WuDVrxE9ucxfBqDkZwOIOWUPaUNQlS4ERbKNcDStmhlffkQ -sAAAAhAIhE6hCID5oOm1TDktc++KFKyScjLifcZ6Cgv5xSSyLOAAAAAAECAwQFBgc= ------END OPENSSH PRIVATE KEY----- diff -ruN openssh-9.4p1/regress/misc/fuzz-harness/testdata/id_ecdsa-cert.pub openssh-9.4p1+x509-14.2.1/regress/misc/fuzz-harness/testdata/id_ecdsa-cert.pub --- openssh-9.4p1/regress/misc/fuzz-harness/testdata/id_ecdsa-cert.pub 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/misc/fuzz-harness/testdata/id_ecdsa-cert.pub 1970-01-01 02:00:00.000000000 +0200 @@ -1 +0,0 @@ -ecdsa-sha2-nistp256-cert-v01@openssh.com AAAAKGVjZHNhLXNoYTItbmlzdHAyNTYtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgVJZuM/1AOe6n++qRWMyUuAThYqLvvQxj5CGflLODp60AAAAIbmlzdHAyNTYAAABBBMMnRWUy/7SuC43NonUMXYq54drFFJDoukjEZu6WuDVrxE9ucxfBqDkZwOIOWUPaUNQlS4ERbKNcDStmhlffkQsAAAAAAAAD6QAAAAEAAAAHdWx5c3NlcwAAABcAAAAHdWx5c3NlcwAAAAhvZHlzc2V1cwAAAAAAAAAA//////////8AAAAAAAAAggAAABVwZXJtaXQtWDExLWZvcndhcmRpbmcAAAAAAAAAF3Blcm1pdC1hZ2VudC1mb3J3YXJkaW5nAAAAAAAAABZwZXJtaXQtcG9ydC1mb3J3YXJkaW5nAAAAAAAAAApwZXJtaXQtcHR5AAAAAAAAAA5wZXJtaXQtdXNlci1yYwAAAAAAAAAAAAAAMwAAAAtzc2gtZWQyNTUxOQAAACAz0F5hFTFS5nhUcmnyjFVoDw5L/P7kQU8JnBA2rWczAwAAAFMAAAALc3NoLWVkMjU1MTkAAABAtdJpcF6ZmQL+ueices4QZeL7AK8Xuo08jyLgiolhjKy2jj4LSUki4aX/ZeZeJuby1ovGrfaeFAgx3itPLR7IAQ== id_ecdsa.pub diff -ruN openssh-9.4p1/regress/misc/fuzz-harness/testdata/id_ecdsa.pub openssh-9.4p1+x509-14.2.1/regress/misc/fuzz-harness/testdata/id_ecdsa.pub --- openssh-9.4p1/regress/misc/fuzz-harness/testdata/id_ecdsa.pub 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/misc/fuzz-harness/testdata/id_ecdsa.pub 1970-01-01 02:00:00.000000000 +0200 @@ -1 +0,0 @@ -ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBMMnRWUy/7SuC43NonUMXYq54drFFJDoukjEZu6WuDVrxE9ucxfBqDkZwOIOWUPaUNQlS4ERbKNcDStmhlffkQs= diff -ruN openssh-9.4p1/regress/misc/fuzz-harness/testdata/id_ecdsa_sk openssh-9.4p1+x509-14.2.1/regress/misc/fuzz-harness/testdata/id_ecdsa_sk --- openssh-9.4p1/regress/misc/fuzz-harness/testdata/id_ecdsa_sk 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/misc/fuzz-harness/testdata/id_ecdsa_sk 1970-01-01 02:00:00.000000000 +0200 @@ -1,14 +0,0 @@ ------BEGIN OPENSSH PRIVATE KEY----- -b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAfwAAACJzay1lY2 -RzYS1zaGEyLW5pc3RwMjU2QG9wZW5zc2guY29tAAAACG5pc3RwMjU2AAAAQQTYyU76zop1 -VOb4DfKWYnR5b0TOC3zw8DzObAfHWB5o6xls+tOYiEleXvIEi00Da2iCK47habZTOhLyeB -X2Avu5AAAABHNzaDoAAAGYqUAQSKlAEEgAAAAic2stZWNkc2Etc2hhMi1uaXN0cDI1NkBv -cGVuc3NoLmNvbQAAAAhuaXN0cDI1NgAAAEEE2MlO+s6KdVTm+A3ylmJ0eW9Ezgt88PA8zm -wHx1geaOsZbPrTmIhJXl7yBItNA2togiuO4Wm2UzoS8ngV9gL7uQAAAARzc2g6AQAAAOMt -LS0tLUJFR0lOIEVDIFBSSVZBVEUgS0VZLS0tLS0KTUhjQ0FRRUVJSHFsZjNsWTkxZFhwUn -dYZDBrS0lYWmNpeDRRcDBNSU15Ny9JMUxXSTFuWG9Bb0dDQ3FHU000OQpBd0VIb1VRRFFn -QUUyTWxPK3M2S2RWVG0rQTN5bG1KMGVXOUV6Z3Q4OFBBOHptd0h4MWdlYU9zWmJQclRtSW -hKClhsN3lCSXROQTJ0b2dpdU80V20yVXpvUzhuZ1Y5Z0w3dVE9PQotLS0tLUVORCBFQyBQ -UklWQVRFIEtFWS0tLS0tCgAAAAAAAAAbZGptQGRqbS5zeWQuY29ycC5nb29nbGUuY29tAQ -IDBAUG ------END OPENSSH PRIVATE KEY----- diff -ruN openssh-9.4p1/regress/misc/fuzz-harness/testdata/id_ecdsa_sk-cert.pub openssh-9.4p1+x509-14.2.1/regress/misc/fuzz-harness/testdata/id_ecdsa_sk-cert.pub --- openssh-9.4p1/regress/misc/fuzz-harness/testdata/id_ecdsa_sk-cert.pub 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/misc/fuzz-harness/testdata/id_ecdsa_sk-cert.pub 1970-01-01 02:00:00.000000000 +0200 @@ -1 +0,0 @@ -sk-ecdsa-sha2-nistp256-cert-v01@openssh.com AAAAK3NrLWVjZHNhLXNoYTItbmlzdHAyNTYtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgKLHtIca++5VoDrUAXU/KqGJZ7jZEnuJSTvt7VrYY9foAAAAIbmlzdHAyNTYAAABBBNjJTvrOinVU5vgN8pZidHlvRM4LfPDwPM5sB8dYHmjrGWz605iISV5e8gSLTQNraIIrjuFptlM6EvJ4FfYC+7kAAAAEc3NoOgAAAAAAAAPqAAAAAQAAAAd1bHlzc2VzAAAAFwAAAAd1bHlzc2VzAAAACG9keXNzZXVzAAAAAAAAAAD//////////wAAAAAAAACCAAAAFXBlcm1pdC1YMTEtZm9yd2FyZGluZwAAAAAAAAAXcGVybWl0LWFnZW50LWZvcndhcmRpbmcAAAAAAAAAFnBlcm1pdC1wb3J0LWZvcndhcmRpbmcAAAAAAAAACnBlcm1pdC1wdHkAAAAAAAAADnBlcm1pdC11c2VyLXJjAAAAAAAAAAAAAAAzAAAAC3NzaC1lZDI1NTE5AAAAIDPQXmEVMVLmeFRyafKMVWgPDkv8/uRBTwmcEDatZzMDAAAAUwAAAAtzc2gtZWQyNTUxOQAAAEB1naZOQDLaDr+fwn6E9x8/8HeiaUubDzPexfNQMz+m/7RD0gd5uJhHYUfDb5+/sIx1I7bUEeRIDkBbmZ2foo0E djm@djm.syd.corp.google.com diff -ruN openssh-9.4p1/regress/misc/fuzz-harness/testdata/id_ecdsa_sk.pub openssh-9.4p1+x509-14.2.1/regress/misc/fuzz-harness/testdata/id_ecdsa_sk.pub --- openssh-9.4p1/regress/misc/fuzz-harness/testdata/id_ecdsa_sk.pub 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/misc/fuzz-harness/testdata/id_ecdsa_sk.pub 1970-01-01 02:00:00.000000000 +0200 @@ -1 +0,0 @@ -sk-ecdsa-sha2-nistp256@openssh.com AAAAInNrLWVjZHNhLXNoYTItbmlzdHAyNTZAb3BlbnNzaC5jb20AAAAIbmlzdHAyNTYAAABBBNjJTvrOinVU5vgN8pZidHlvRM4LfPDwPM5sB8dYHmjrGWz605iISV5e8gSLTQNraIIrjuFptlM6EvJ4FfYC+7kAAAAEc3NoOg== djm@djm.syd.corp.google.com diff -ruN openssh-9.4p1/regress/misc/fuzz-harness/testdata/id_ed25519 openssh-9.4p1+x509-14.2.1/regress/misc/fuzz-harness/testdata/id_ed25519 --- openssh-9.4p1/regress/misc/fuzz-harness/testdata/id_ed25519 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/misc/fuzz-harness/testdata/id_ed25519 1970-01-01 02:00:00.000000000 +0200 @@ -1,7 +0,0 @@ ------BEGIN OPENSSH PRIVATE KEY----- -b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW -QyNTUxOQAAACAz0F5hFTFS5nhUcmnyjFVoDw5L/P7kQU8JnBA2rWczAwAAAIhWlP99VpT/ -fQAAAAtzc2gtZWQyNTUxOQAAACAz0F5hFTFS5nhUcmnyjFVoDw5L/P7kQU8JnBA2rWczAw -AAAEDE1rlcMC0s0X3TKVZAOVavZOywwkXw8tO5dLObxaCMEDPQXmEVMVLmeFRyafKMVWgP -Dkv8/uRBTwmcEDatZzMDAAAAAAECAwQF ------END OPENSSH PRIVATE KEY----- diff -ruN openssh-9.4p1/regress/misc/fuzz-harness/testdata/id_ed25519-cert.pub openssh-9.4p1+x509-14.2.1/regress/misc/fuzz-harness/testdata/id_ed25519-cert.pub --- openssh-9.4p1/regress/misc/fuzz-harness/testdata/id_ed25519-cert.pub 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/misc/fuzz-harness/testdata/id_ed25519-cert.pub 1970-01-01 02:00:00.000000000 +0200 @@ -1 +0,0 @@ -ssh-ed25519-cert-v01@openssh.com AAAAIHNzaC1lZDI1NTE5LWNlcnQtdjAxQG9wZW5zc2guY29tAAAAIMDQjYH6XRzH3j3MW1DdjCoAfvrHfgjnVGF+sLK0pBfqAAAAIDPQXmEVMVLmeFRyafKMVWgPDkv8/uRBTwmcEDatZzMDAAAAAAAAA+sAAAABAAAAB3VseXNzZXMAAAAXAAAAB3VseXNzZXMAAAAIb2R5c3NldXMAAAAAAAAAAP//////////AAAAAAAAAIIAAAAVcGVybWl0LVgxMS1mb3J3YXJkaW5nAAAAAAAAABdwZXJtaXQtYWdlbnQtZm9yd2FyZGluZwAAAAAAAAAWcGVybWl0LXBvcnQtZm9yd2FyZGluZwAAAAAAAAAKcGVybWl0LXB0eQAAAAAAAAAOcGVybWl0LXVzZXItcmMAAAAAAAAAAAAAADMAAAALc3NoLWVkMjU1MTkAAAAgM9BeYRUxUuZ4VHJp8oxVaA8OS/z+5EFPCZwQNq1nMwMAAABTAAAAC3NzaC1lZDI1NTE5AAAAQBj0og+s09/HpwdHZbzN0twooKPDWWrxGfnP1Joy6cDnY2BCSQ7zg9vbq11kLF8H/sKOTZWAQrUZ7LlChOu9Ogw= id_ed25519.pub diff -ruN openssh-9.4p1/regress/misc/fuzz-harness/testdata/id_ed25519.pub openssh-9.4p1+x509-14.2.1/regress/misc/fuzz-harness/testdata/id_ed25519.pub --- openssh-9.4p1/regress/misc/fuzz-harness/testdata/id_ed25519.pub 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/misc/fuzz-harness/testdata/id_ed25519.pub 1970-01-01 02:00:00.000000000 +0200 @@ -1,2 +0,0 @@ -ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDPQXmEVMVLmeFRyafKMVWgPDkv8/uRBTwmcEDatZzMD - diff -ruN openssh-9.4p1/regress/misc/fuzz-harness/testdata/id_ed25519_sk openssh-9.4p1+x509-14.2.1/regress/misc/fuzz-harness/testdata/id_ed25519_sk --- openssh-9.4p1/regress/misc/fuzz-harness/testdata/id_ed25519_sk 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/misc/fuzz-harness/testdata/id_ed25519_sk 1970-01-01 02:00:00.000000000 +0200 @@ -1,8 +0,0 @@ ------BEGIN OPENSSH PRIVATE KEY----- -b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAASgAAABpzay1zc2 -gtZWQyNTUxOUBvcGVuc3NoLmNvbQAAACCTJtH10vWhIDxd62edvMLg9u2cwYKyqa7332je -RArHjAAAAARzc2g6AAAAwN7vvE3e77xNAAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY2 -9tAAAAIJMm0fXS9aEgPF3rZ528wuD27ZzBgrKprvffaN5ECseMAAAABHNzaDoBAAAAQEsS -xLFiVzfpH2mt9xh8i/zmHV646Hud4QruNBAGNl8gkybR9dL1oSA8XetnnbzC4PbtnMGCsq -mu999o3kQKx4wAAAAAAAAAG2RqbUBkam0uc3lkLmNvcnAuZ29vZ2xlLmNvbQECAwQFBg== ------END OPENSSH PRIVATE KEY----- diff -ruN openssh-9.4p1/regress/misc/fuzz-harness/testdata/id_ed25519_sk-cert.pub openssh-9.4p1+x509-14.2.1/regress/misc/fuzz-harness/testdata/id_ed25519_sk-cert.pub --- openssh-9.4p1/regress/misc/fuzz-harness/testdata/id_ed25519_sk-cert.pub 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/misc/fuzz-harness/testdata/id_ed25519_sk-cert.pub 1970-01-01 02:00:00.000000000 +0200 @@ -1 +0,0 @@ -sk-ssh-ed25519-cert-v01@openssh.com AAAAI3NrLXNzaC1lZDI1NTE5LWNlcnQtdjAxQG9wZW5zc2guY29tAAAAIJiT+C/VLMWholFZ4xhOyJr0nSLZSFRIM3I07wUNTRPaAAAAIJMm0fXS9aEgPF3rZ528wuD27ZzBgrKprvffaN5ECseMAAAABHNzaDoAAAAAAAAD7AAAAAEAAAAHdWx5c3NlcwAAABcAAAAHdWx5c3NlcwAAAAhvZHlzc2V1cwAAAAAAAAAA//////////8AAAAAAAAAggAAABVwZXJtaXQtWDExLWZvcndhcmRpbmcAAAAAAAAAF3Blcm1pdC1hZ2VudC1mb3J3YXJkaW5nAAAAAAAAABZwZXJtaXQtcG9ydC1mb3J3YXJkaW5nAAAAAAAAAApwZXJtaXQtcHR5AAAAAAAAAA5wZXJtaXQtdXNlci1yYwAAAAAAAAAAAAAAMwAAAAtzc2gtZWQyNTUxOQAAACAz0F5hFTFS5nhUcmnyjFVoDw5L/P7kQU8JnBA2rWczAwAAAFMAAAALc3NoLWVkMjU1MTkAAABAX0Pu13B94pVR3qq8MJQGkOS1Cd7AAM1k6O2VSwyDPM/LfsWIQ4ywgxDmk3hjXWOY7BqljuMxo5VO4JymEIhQBA== djm@djm.syd.corp.google.com diff -ruN openssh-9.4p1/regress/misc/fuzz-harness/testdata/id_ed25519_sk.pub openssh-9.4p1+x509-14.2.1/regress/misc/fuzz-harness/testdata/id_ed25519_sk.pub --- openssh-9.4p1/regress/misc/fuzz-harness/testdata/id_ed25519_sk.pub 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/misc/fuzz-harness/testdata/id_ed25519_sk.pub 1970-01-01 02:00:00.000000000 +0200 @@ -1 +0,0 @@ -sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIJMm0fXS9aEgPF3rZ528wuD27ZzBgrKprvffaN5ECseMAAAABHNzaDo= djm@djm.syd.corp.google.com diff -ruN openssh-9.4p1/regress/misc/fuzz-harness/testdata/id_rsa openssh-9.4p1+x509-14.2.1/regress/misc/fuzz-harness/testdata/id_rsa --- openssh-9.4p1/regress/misc/fuzz-harness/testdata/id_rsa 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/misc/fuzz-harness/testdata/id_rsa 1970-01-01 02:00:00.000000000 +0200 @@ -1,27 +0,0 @@ ------BEGIN OPENSSH PRIVATE KEY----- -b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABFwAAAAdzc2gtcn -NhAAAAAwEAAQAAAQEA3+epf+VGKoGPaAZXrf6S0cyumQnddkGBnVFX0A5eh37RtLug0qY5 -thxsBUbGGVr9mTd2QXwLujBwYg5l1MP/Fmg+5312Zgx9pHmS+qKULbar0hlNgptNEb+aNU -d3o9qg3aXqXm7+ZnjAV05ef/mxNRN2ZvuEkw7cRppTJcbBI+vF3lXuCXnX2klDI95Gl2AW -3WHRtanqLHZXuBkjjRBDKc7MUq/GP1hmLiAd95dvU7fZjRlIEsP84zGEI1Fb0L/kmPHcOt -iVfHft8CtmC9v6+94JrOiPBBNScV+dyrgAGPsdKdr/1vIpQmCNiI8s3PCiD8J7ZiBaYm0I -8fq5G/qnUwAAA7ggw2dXIMNnVwAAAAdzc2gtcnNhAAABAQDf56l/5UYqgY9oBlet/pLRzK -6ZCd12QYGdUVfQDl6HftG0u6DSpjm2HGwFRsYZWv2ZN3ZBfAu6MHBiDmXUw/8WaD7nfXZm -DH2keZL6opQttqvSGU2Cm00Rv5o1R3ej2qDdpepebv5meMBXTl5/+bE1E3Zm+4STDtxGml -MlxsEj68XeVe4JedfaSUMj3kaXYBbdYdG1qeosdle4GSONEEMpzsxSr8Y/WGYuIB33l29T -t9mNGUgSw/zjMYQjUVvQv+SY8dw62JV8d+3wK2YL2/r73gms6I8EE1JxX53KuAAY+x0p2v -/W8ilCYI2Ijyzc8KIPwntmIFpibQjx+rkb+qdTAAAAAwEAAQAAAQEArWm5B4tFasppjUHM -SsAuajtCxtizI1Hc10EW59cZM4vvUzE2f6+qZvdgWj3UU/L7Et23w0QVuSCnCerox379ZB -ddEOFFAAiQjwBx65hbd4RRUymxtIQfjq18++LcMJW1nbVQ7c69ThQbtALIggmbS+ZE/8Gx -jkwmIrCH0Ww8TlpsPe+mNHuyNk7UEZoXLm22lNLqq5qkIL5JgT6M2iNJpMOJy9/CKi6kO4 -JPuVwjdG4C5pBPaMN3KJ1IvAlSlLGNaXnfXcn85gWfsCjsZmH3liey2NJamqp/w83BrKUg -YZvMR2qeWZaKkFTahpzN5KRK1BFeB37O0P84Dzh1biDX8QAAAIEAiWXW8ePYFwLpa2mFIh -VvRTdcrN70rVK5eWVaL3pyS4vGA56Jixq86dHveOnbSY+iNb1jQidtXc8SWUt2wtHqZ32h -Lji9/hMSKqe9SEP3xvDRDmUJqsVw0ySyrFrzm4160QY6RKU3CIQCVFslMZ9fxmrfZ/hxoU -0X3FVsxmC4+kwAAACBAPOc1YERpV6PjANBrGR+1o1RCdACbm5myc42QzSNIaOZmgrYs+Gt -7+EcoqSdbJzHJNCNQfF+A+vjbIkFiuZqq/5wwr59qXx5OAlijLB/ywwKmTWq6lp//Zxny+ -ka3sIGNO14eQvmxNDnlLL+RIZleCTEKBXSW6CZhr+uHMZFKKMtAAAAgQDrSkm+LbILB7H9 -jxEBZLhv53aAn4u81kFKQOJ7PzzpBGSoD12i7oIJu5siSD5EKDNVEr+SvCf0ISU3BuMpzl -t3YrPrHRheOFhn5e3j0e//zB8rBC0DGB4CtTDdeh7rOXUL4K0pz+8wEpNkV62SWxhC6NRW -I79JhtGkh+GtcnkEfwAAAAAB ------END OPENSSH PRIVATE KEY----- diff -ruN openssh-9.4p1/regress/misc/fuzz-harness/testdata/id_rsa-cert.pub openssh-9.4p1+x509-14.2.1/regress/misc/fuzz-harness/testdata/id_rsa-cert.pub --- openssh-9.4p1/regress/misc/fuzz-harness/testdata/id_rsa-cert.pub 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/misc/fuzz-harness/testdata/id_rsa-cert.pub 1970-01-01 02:00:00.000000000 +0200 @@ -1 +0,0 @@ -ssh-rsa-cert-v01@openssh.com AAAAHHNzaC1yc2EtY2VydC12MDFAb3BlbnNzaC5jb20AAAAg89JX6OBMYDSxER8fnU5y8xxeMCHR/hI0uVqdEhNyCpcAAAADAQABAAABAQDf56l/5UYqgY9oBlet/pLRzK6ZCd12QYGdUVfQDl6HftG0u6DSpjm2HGwFRsYZWv2ZN3ZBfAu6MHBiDmXUw/8WaD7nfXZmDH2keZL6opQttqvSGU2Cm00Rv5o1R3ej2qDdpepebv5meMBXTl5/+bE1E3Zm+4STDtxGmlMlxsEj68XeVe4JedfaSUMj3kaXYBbdYdG1qeosdle4GSONEEMpzsxSr8Y/WGYuIB33l29Tt9mNGUgSw/zjMYQjUVvQv+SY8dw62JV8d+3wK2YL2/r73gms6I8EE1JxX53KuAAY+x0p2v/W8ilCYI2Ijyzc8KIPwntmIFpibQjx+rkb+qdTAAAAAAAAA+0AAAABAAAAB3VseXNzZXMAAAAXAAAAB3VseXNzZXMAAAAIb2R5c3NldXMAAAAAAAAAAP//////////AAAAAAAAAIIAAAAVcGVybWl0LVgxMS1mb3J3YXJkaW5nAAAAAAAAABdwZXJtaXQtYWdlbnQtZm9yd2FyZGluZwAAAAAAAAAWcGVybWl0LXBvcnQtZm9yd2FyZGluZwAAAAAAAAAKcGVybWl0LXB0eQAAAAAAAAAOcGVybWl0LXVzZXItcmMAAAAAAAAAAAAAADMAAAALc3NoLWVkMjU1MTkAAAAgM9BeYRUxUuZ4VHJp8oxVaA8OS/z+5EFPCZwQNq1nMwMAAABTAAAAC3NzaC1lZDI1NTE5AAAAQGCDA6PWw4x9bHQl0w7NqifHepumqD3dmyMx+hZGuPRon+TsyCjfytu7hWmV7l9XUF0fPQNFQ7FGat5e+7YUNgE= id_rsa.pub diff -ruN openssh-9.4p1/regress/misc/fuzz-harness/testdata/id_rsa.pub openssh-9.4p1+x509-14.2.1/regress/misc/fuzz-harness/testdata/id_rsa.pub --- openssh-9.4p1/regress/misc/fuzz-harness/testdata/id_rsa.pub 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/misc/fuzz-harness/testdata/id_rsa.pub 1970-01-01 02:00:00.000000000 +0200 @@ -1 +0,0 @@ -ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDf56l/5UYqgY9oBlet/pLRzK6ZCd12QYGdUVfQDl6HftG0u6DSpjm2HGwFRsYZWv2ZN3ZBfAu6MHBiDmXUw/8WaD7nfXZmDH2keZL6opQttqvSGU2Cm00Rv5o1R3ej2qDdpepebv5meMBXTl5/+bE1E3Zm+4STDtxGmlMlxsEj68XeVe4JedfaSUMj3kaXYBbdYdG1qeosdle4GSONEEMpzsxSr8Y/WGYuIB33l29Tt9mNGUgSw/zjMYQjUVvQv+SY8dw62JV8d+3wK2YL2/r73gms6I8EE1JxX53KuAAY+x0p2v/W8ilCYI2Ijyzc8KIPwntmIFpibQjx+rkb+qdT diff -ruN openssh-9.4p1/regress/misc/fuzz-harness/testdata/README openssh-9.4p1+x509-14.2.1/regress/misc/fuzz-harness/testdata/README --- openssh-9.4p1/regress/misc/fuzz-harness/testdata/README 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/misc/fuzz-harness/testdata/README 1970-01-01 02:00:00.000000000 +0200 @@ -1,4 +0,0 @@ -This is preparatory data for fuzzing testing including scripts and test keys, -corresponding to ../fixed-keys that are used in the fuzz tests and consequent -fuzzing seed corpora. They should not be changed unless the affected seed -corpora are also regenerated. diff -ruN openssh-9.4p1/regress/misc/Makefile openssh-9.4p1+x509-14.2.1/regress/misc/Makefile --- openssh-9.4p1/regress/misc/Makefile 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/misc/Makefile 2023-08-20 10:07:00.000000000 +0300 @@ -1,3 +1,3 @@ -SUBDIR= sk-dummy +SUBDIR= .include diff -ruN openssh-9.4p1/regress/misc/sk-dummy/fatal.c openssh-9.4p1+x509-14.2.1/regress/misc/sk-dummy/fatal.c --- openssh-9.4p1/regress/misc/sk-dummy/fatal.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/misc/sk-dummy/fatal.c 1970-01-01 02:00:00.000000000 +0200 @@ -1,27 +0,0 @@ -/* public domain */ - -#include "includes.h" - -#include -#include -#include -#include - -#include "log.h" - -void -sshfatal(const char *file, const char *func, int line, int showfunc, - LogLevel level, const char *suffix, const char *fmt, ...) -{ - va_list ap; - - if (showfunc) - fprintf(stderr, "%s: ", func); - va_start(ap, fmt); - vfprintf(stderr, fmt, ap); - va_end(ap); - if (suffix != NULL) - fprintf(stderr, ": %s", suffix); - fputc('\n', stderr); - _exit(1); -} diff -ruN openssh-9.4p1/regress/misc/sk-dummy/Makefile openssh-9.4p1+x509-14.2.1/regress/misc/sk-dummy/Makefile --- openssh-9.4p1/regress/misc/sk-dummy/Makefile 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/misc/sk-dummy/Makefile 1970-01-01 02:00:00.000000000 +0200 @@ -1,66 +0,0 @@ -# $OpenBSD: Makefile,v 1.3 2023/01/15 23:35:10 djm Exp $ - -.include -.include - -PROG= sk-dummy.so -NOMAN= - -SSHREL=../../../../../usr.bin/ssh -.PATH: ${.CURDIR}/${SSHREL} - -SRCS=sk-dummy.c -# From usr.bin/ssh -SRCS+=ed25519.c hash.c -OPENSSL?= yes - -CFLAGS+= -fPIC - -.if (${OPENSSL:L} == "yes") -CFLAGS+= -DWITH_OPENSSL -.endif - -# enable warnings -WARNINGS=Yes - -DEBUG=-g -CFLAGS+= -fstack-protector-all -CDIAGFLAGS= -Wall -CDIAGFLAGS+= -Wextra -CDIAGFLAGS+= -Werror -CDIAGFLAGS+= -Wchar-subscripts -CDIAGFLAGS+= -Wcomment -CDIAGFLAGS+= -Wformat -CDIAGFLAGS+= -Wformat-security -CDIAGFLAGS+= -Wimplicit -CDIAGFLAGS+= -Winline -CDIAGFLAGS+= -Wmissing-declarations -CDIAGFLAGS+= -Wmissing-prototypes -CDIAGFLAGS+= -Wparentheses -CDIAGFLAGS+= -Wpointer-arith -CDIAGFLAGS+= -Wreturn-type -CDIAGFLAGS+= -Wshadow -CDIAGFLAGS+= -Wsign-compare -CDIAGFLAGS+= -Wstrict-aliasing -CDIAGFLAGS+= -Wstrict-prototypes -CDIAGFLAGS+= -Wswitch -CDIAGFLAGS+= -Wtrigraphs -CDIAGFLAGS+= -Wuninitialized -CDIAGFLAGS+= -Wunused -CDIAGFLAGS+= -Wno-unused-parameter -.if ${COMPILER_VERSION:L} != "gcc3" -CDIAGFLAGS+= -Wold-style-definition -.endif - -CFLAGS+=-I${.CURDIR}/${SSHREL} - -.if (${OPENSSL:L} == "yes") -LDADD+= -lcrypto -DPADD+= ${LIBCRYPTO} -.endif - -$(PROG): $(OBJS) - $(CC) $(LDFLAGS) -shared -o $@ $(OBJS) $(LDADD) - -.include - diff -ruN openssh-9.4p1/regress/misc/sk-dummy/sk-dummy.c openssh-9.4p1+x509-14.2.1/regress/misc/sk-dummy/sk-dummy.c --- openssh-9.4p1/regress/misc/sk-dummy/sk-dummy.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/misc/sk-dummy/sk-dummy.c 1970-01-01 02:00:00.000000000 +0200 @@ -1,543 +0,0 @@ -/* - * Copyright (c) 2019 Markus Friedl - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include "includes.h" - -#ifdef HAVE_STDINT_H -#include -#endif -#include -#include -#include -#include -#include - -#include "crypto_api.h" -#include "sk-api.h" - -#ifdef WITH_OPENSSL -#include -#include -#include -#include -#include -#include -#include -#include - -/* Use OpenSSL SHA256 instead of libc */ -#define SHA256Init(x) SHA256_Init(x) -#define SHA256Update(x, y, z) SHA256_Update(x, y, z) -#define SHA256Final(x, y) SHA256_Final(x, y) -#define SHA2_CTX SHA256_CTX - -#elif defined(HAVE_SHA2_H) -#include -#endif /* WITH_OPENSSL */ - -/* #define SK_DEBUG 1 */ - -#if SSH_SK_VERSION_MAJOR != 0x000a0000 -# error SK API has changed, sk-dummy.c needs an update -#endif - -#ifdef SK_DUMMY_INTEGRATE -# define sk_api_version ssh_sk_api_version -# define sk_enroll ssh_sk_enroll -# define sk_sign ssh_sk_sign -# define sk_load_resident_keys ssh_sk_load_resident_keys -#endif /* !SK_STANDALONE */ - -static void skdebug(const char *func, const char *fmt, ...) - __attribute__((__format__ (printf, 2, 3))); - -static void -skdebug(const char *func, const char *fmt, ...) -{ -#if defined(SK_DEBUG) - va_list ap; - - va_start(ap, fmt); - fprintf(stderr, "sk-dummy %s: ", func); - vfprintf(stderr, fmt, ap); - fputc('\n', stderr); - va_end(ap); -#else - (void)func; /* XXX */ - (void)fmt; /* XXX */ -#endif -} - -uint32_t -sk_api_version(void) -{ - return SSH_SK_VERSION_MAJOR; -} - -static int -pack_key_ecdsa(struct sk_enroll_response *response) -{ -#ifdef OPENSSL_HAS_ECC - EC_KEY *key = NULL; - const EC_GROUP *g; - const EC_POINT *q; - int ret = -1; - long privlen; - BIO *bio = NULL; - char *privptr; - - response->public_key = NULL; - response->public_key_len = 0; - response->key_handle = NULL; - response->key_handle_len = 0; - - if ((key = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1)) == NULL) { - skdebug(__func__, "EC_KEY_new_by_curve_name"); - goto out; - } - if (EC_KEY_generate_key(key) != 1) { - skdebug(__func__, "EC_KEY_generate_key"); - goto out; - } - EC_KEY_set_asn1_flag(key, OPENSSL_EC_NAMED_CURVE); - if ((bio = BIO_new(BIO_s_mem())) == NULL || - (g = EC_KEY_get0_group(key)) == NULL || - (q = EC_KEY_get0_public_key(key)) == NULL) { - skdebug(__func__, "couldn't get key parameters"); - goto out; - } - response->public_key_len = EC_POINT_point2oct(g, q, - POINT_CONVERSION_UNCOMPRESSED, NULL, 0, NULL); - if (response->public_key_len == 0 || response->public_key_len > 2048) { - skdebug(__func__, "bad pubkey length %zu", - response->public_key_len); - goto out; - } - if ((response->public_key = malloc(response->public_key_len)) == NULL) { - skdebug(__func__, "malloc pubkey failed"); - goto out; - } - if (EC_POINT_point2oct(g, q, POINT_CONVERSION_UNCOMPRESSED, - response->public_key, response->public_key_len, NULL) == 0) { - skdebug(__func__, "EC_POINT_point2oct failed"); - goto out; - } - /* Key handle contains PEM encoded private key */ - if (!PEM_write_bio_ECPrivateKey(bio, key, NULL, NULL, 0, NULL, NULL)) { - skdebug(__func__, "PEM_write_bio_ECPrivateKey failed"); - goto out; - } - if ((privlen = BIO_get_mem_data(bio, &privptr)) <= 0) { - skdebug(__func__, "BIO_get_mem_data failed"); - goto out; - } - if ((response->key_handle = malloc(privlen)) == NULL) { - skdebug(__func__, "malloc key_handle failed"); - goto out; - } - response->key_handle_len = (size_t)privlen; - memcpy(response->key_handle, privptr, response->key_handle_len); - /* success */ - ret = 0; - out: - if (ret != 0) { - if (response->public_key != NULL) { - memset(response->public_key, 0, - response->public_key_len); - free(response->public_key); - response->public_key = NULL; - } - if (response->key_handle != NULL) { - memset(response->key_handle, 0, - response->key_handle_len); - free(response->key_handle); - response->key_handle = NULL; - } - } - BIO_free(bio); - EC_KEY_free(key); - return ret; -#else - return -1; -#endif -} - -static int -pack_key_ed25519(struct sk_enroll_response *response) -{ - int ret = -1; - u_char pk[crypto_sign_ed25519_PUBLICKEYBYTES]; - u_char sk[crypto_sign_ed25519_SECRETKEYBYTES]; - - response->public_key = NULL; - response->public_key_len = 0; - response->key_handle = NULL; - response->key_handle_len = 0; - - memset(pk, 0, sizeof(pk)); - memset(sk, 0, sizeof(sk)); - crypto_sign_ed25519_keypair(pk, sk); - - response->public_key_len = sizeof(pk); - if ((response->public_key = malloc(response->public_key_len)) == NULL) { - skdebug(__func__, "malloc pubkey failed"); - goto out; - } - memcpy(response->public_key, pk, sizeof(pk)); - /* Key handle contains sk */ - response->key_handle_len = sizeof(sk); - if ((response->key_handle = malloc(response->key_handle_len)) == NULL) { - skdebug(__func__, "malloc key_handle failed"); - goto out; - } - memcpy(response->key_handle, sk, sizeof(sk)); - /* success */ - ret = 0; - out: - if (ret != 0) - free(response->public_key); - return ret; -} - -static int -check_options(struct sk_option **options) -{ - size_t i; - - if (options == NULL) - return 0; - for (i = 0; options[i] != NULL; i++) { - skdebug(__func__, "requested unsupported option %s", - options[i]->name); - if (options[i]->required) { - skdebug(__func__, "unknown required option"); - return -1; - } - } - return 0; -} - -int -sk_enroll(uint32_t alg, const uint8_t *challenge, size_t challenge_len, - const char *application, uint8_t flags, const char *pin, - struct sk_option **options, struct sk_enroll_response **enroll_response) -{ - struct sk_enroll_response *response = NULL; - int ret = SSH_SK_ERR_GENERAL; - - (void)flags; /* XXX; unused */ - - if (enroll_response == NULL) { - skdebug(__func__, "enroll_response == NULL"); - goto out; - } - *enroll_response = NULL; - if (check_options(options) != 0) - goto out; /* error already logged */ - if ((response = calloc(1, sizeof(*response))) == NULL) { - skdebug(__func__, "calloc response failed"); - goto out; - } - response->flags = flags; - switch(alg) { - case SSH_SK_ECDSA: - if (pack_key_ecdsa(response) != 0) - goto out; - break; - case SSH_SK_ED25519: - if (pack_key_ed25519(response) != 0) - goto out; - break; - default: - skdebug(__func__, "unsupported key type %d", alg); - return -1; - } - /* Have to return something here */ - if ((response->signature = calloc(1, 1)) == NULL) { - skdebug(__func__, "calloc signature failed"); - goto out; - } - response->signature_len = 0; - - *enroll_response = response; - response = NULL; - ret = 0; - out: - if (response != NULL) { - free(response->public_key); - free(response->key_handle); - free(response->signature); - free(response->attestation_cert); - free(response); - } - return ret; -} - -static void -dump(const char *preamble, const void *sv, size_t l) -{ -#ifdef SK_DEBUG - const u_char *s = (const u_char *)sv; - size_t i; - - fprintf(stderr, "%s (len %zu):\n", preamble, l); - for (i = 0; i < l; i++) { - if (i % 16 == 0) - fprintf(stderr, "%04zu: ", i); - fprintf(stderr, "%02x", s[i]); - if (i % 16 == 15 || i == l - 1) - fprintf(stderr, "\n"); - } -#endif -} - -static int -sig_ecdsa(const uint8_t *message, size_t message_len, - const char *application, uint32_t counter, uint8_t flags, - const uint8_t *key_handle, size_t key_handle_len, - struct sk_sign_response *response) -{ -#ifdef OPENSSL_HAS_ECC - ECDSA_SIG *sig = NULL; - const BIGNUM *sig_r, *sig_s; - int ret = -1; - BIO *bio = NULL; - EVP_PKEY *pk = NULL; - EC_KEY *ec = NULL; - SHA2_CTX ctx; - uint8_t apphash[SHA256_DIGEST_LENGTH]; - uint8_t sighash[SHA256_DIGEST_LENGTH]; - uint8_t countbuf[4]; - - /* Decode EC_KEY from key handle */ - if ((bio = BIO_new(BIO_s_mem())) == NULL || - BIO_write(bio, key_handle, key_handle_len) != (int)key_handle_len) { - skdebug(__func__, "BIO setup failed"); - goto out; - } - if ((pk = PEM_read_bio_PrivateKey(bio, NULL, NULL, "")) == NULL) { - skdebug(__func__, "PEM_read_bio_PrivateKey failed"); - goto out; - } - if (EVP_PKEY_base_id(pk) != EVP_PKEY_EC) { - skdebug(__func__, "Not an EC key: %d", EVP_PKEY_base_id(pk)); - goto out; - } - if ((ec = EVP_PKEY_get1_EC_KEY(pk)) == NULL) { - skdebug(__func__, "EVP_PKEY_get1_EC_KEY failed"); - goto out; - } - /* Expect message to be pre-hashed */ - if (message_len != SHA256_DIGEST_LENGTH) { - skdebug(__func__, "bad message len %zu", message_len); - goto out; - } - /* Prepare data to be signed */ - dump("message", message, message_len); - SHA256Init(&ctx); - SHA256Update(&ctx, (const u_char *)application, strlen(application)); - SHA256Final(apphash, &ctx); - dump("apphash", apphash, sizeof(apphash)); - countbuf[0] = (counter >> 24) & 0xff; - countbuf[1] = (counter >> 16) & 0xff; - countbuf[2] = (counter >> 8) & 0xff; - countbuf[3] = counter & 0xff; - dump("countbuf", countbuf, sizeof(countbuf)); - dump("flags", &flags, sizeof(flags)); - SHA256Init(&ctx); - SHA256Update(&ctx, apphash, sizeof(apphash)); - SHA256Update(&ctx, &flags, sizeof(flags)); - SHA256Update(&ctx, countbuf, sizeof(countbuf)); - SHA256Update(&ctx, message, message_len); - SHA256Final(sighash, &ctx); - dump("sighash", sighash, sizeof(sighash)); - /* create and encode signature */ - if ((sig = ECDSA_do_sign(sighash, sizeof(sighash), ec)) == NULL) { - skdebug(__func__, "ECDSA_do_sign failed"); - goto out; - } - ECDSA_SIG_get0(sig, &sig_r, &sig_s); - response->sig_r_len = BN_num_bytes(sig_r); - response->sig_s_len = BN_num_bytes(sig_s); - if ((response->sig_r = calloc(1, response->sig_r_len)) == NULL || - (response->sig_s = calloc(1, response->sig_s_len)) == NULL) { - skdebug(__func__, "calloc signature failed"); - goto out; - } - BN_bn2bin(sig_r, response->sig_r); - BN_bn2bin(sig_s, response->sig_s); - ret = 0; - out: - explicit_bzero(&ctx, sizeof(ctx)); - explicit_bzero(&apphash, sizeof(apphash)); - explicit_bzero(&sighash, sizeof(sighash)); - ECDSA_SIG_free(sig); - if (ret != 0) { - free(response->sig_r); - free(response->sig_s); - response->sig_r = NULL; - response->sig_s = NULL; - } - BIO_free(bio); - EC_KEY_free(ec); - EVP_PKEY_free(pk); - return ret; -#else - return -1; -#endif -} - -static int -sig_ed25519(const uint8_t *message, size_t message_len, - const char *application, uint32_t counter, uint8_t flags, - const uint8_t *key_handle, size_t key_handle_len, - struct sk_sign_response *response) -{ - size_t o; - int ret = -1; - SHA2_CTX ctx; - uint8_t apphash[SHA256_DIGEST_LENGTH]; - uint8_t signbuf[sizeof(apphash) + sizeof(flags) + - sizeof(counter) + SHA256_DIGEST_LENGTH]; - uint8_t sig[crypto_sign_ed25519_BYTES + sizeof(signbuf)]; - unsigned long long smlen; - - if (key_handle_len != crypto_sign_ed25519_SECRETKEYBYTES) { - skdebug(__func__, "bad key handle length %zu", key_handle_len); - goto out; - } - /* Expect message to be pre-hashed */ - if (message_len != SHA256_DIGEST_LENGTH) { - skdebug(__func__, "bad message len %zu", message_len); - goto out; - } - /* Prepare data to be signed */ - dump("message", message, message_len); - SHA256Init(&ctx); - SHA256Update(&ctx, (const u_char *)application, strlen(application)); - SHA256Final(apphash, &ctx); - dump("apphash", apphash, sizeof(apphash)); - - memcpy(signbuf, apphash, sizeof(apphash)); - o = sizeof(apphash); - signbuf[o++] = flags; - signbuf[o++] = (counter >> 24) & 0xff; - signbuf[o++] = (counter >> 16) & 0xff; - signbuf[o++] = (counter >> 8) & 0xff; - signbuf[o++] = counter & 0xff; - memcpy(signbuf + o, message, message_len); - o += message_len; - if (o != sizeof(signbuf)) { - skdebug(__func__, "bad sign buf len %zu, expected %zu", - o, sizeof(signbuf)); - goto out; - } - dump("signbuf", signbuf, sizeof(signbuf)); - /* create and encode signature */ - smlen = sizeof(signbuf); - if (crypto_sign_ed25519(sig, &smlen, signbuf, sizeof(signbuf), - key_handle) != 0) { - skdebug(__func__, "crypto_sign_ed25519 failed"); - goto out; - } - if (smlen <= sizeof(signbuf)) { - skdebug(__func__, "bad sign smlen %llu, expected min %zu", - smlen, sizeof(signbuf) + 1); - goto out; - } - response->sig_r_len = (size_t)(smlen - sizeof(signbuf)); - if ((response->sig_r = calloc(1, response->sig_r_len)) == NULL) { - skdebug(__func__, "calloc signature failed"); - goto out; - } - memcpy(response->sig_r, sig, response->sig_r_len); - dump("sig_r", response->sig_r, response->sig_r_len); - ret = 0; - out: - explicit_bzero(&ctx, sizeof(ctx)); - explicit_bzero(&apphash, sizeof(apphash)); - explicit_bzero(&signbuf, sizeof(signbuf)); - explicit_bzero(&sig, sizeof(sig)); - if (ret != 0) { - free(response->sig_r); - response->sig_r = NULL; - } - return ret; -} - -int -sk_sign(uint32_t alg, const uint8_t *data, size_t datalen, - const char *application, const uint8_t *key_handle, size_t key_handle_len, - uint8_t flags, const char *pin, struct sk_option **options, - struct sk_sign_response **sign_response) -{ - struct sk_sign_response *response = NULL; - int ret = SSH_SK_ERR_GENERAL; - SHA2_CTX ctx; - uint8_t message[32]; - - if (sign_response == NULL) { - skdebug(__func__, "sign_response == NULL"); - goto out; - } - *sign_response = NULL; - if (check_options(options) != 0) - goto out; /* error already logged */ - if ((response = calloc(1, sizeof(*response))) == NULL) { - skdebug(__func__, "calloc response failed"); - goto out; - } - SHA256Init(&ctx); - SHA256Update(&ctx, data, datalen); - SHA256Final(message, &ctx); - response->flags = flags; - response->counter = 0x12345678; - switch(alg) { - case SSH_SK_ECDSA: - if (sig_ecdsa(message, sizeof(message), application, - response->counter, flags, key_handle, key_handle_len, - response) != 0) - goto out; - break; - case SSH_SK_ED25519: - if (sig_ed25519(message, sizeof(message), application, - response->counter, flags, key_handle, key_handle_len, - response) != 0) - goto out; - break; - default: - skdebug(__func__, "unsupported key type %d", alg); - return -1; - } - *sign_response = response; - response = NULL; - ret = 0; - out: - explicit_bzero(message, sizeof(message)); - if (response != NULL) { - free(response->sig_r); - free(response->sig_s); - free(response); - } - return ret; -} - -int -sk_load_resident_keys(const char *pin, struct sk_option **options, - struct sk_resident_key ***rks, size_t *nrks) -{ - return SSH_SK_ERR_UNSUPPORTED; -} diff -ruN openssh-9.4p1/regress/modpipe.c openssh-9.4p1+x509-14.2.1/regress/modpipe.c --- openssh-9.4p1/regress/modpipe.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/modpipe.c 2023-08-20 10:07:01.000000000 +0300 @@ -53,7 +53,7 @@ char what[16+1]; int n, m1, m2; - bzero(m, sizeof(*m)); + memset(m, 0, sizeof(*m)); if ((n = sscanf(s, "%16[^:]%*[:]%llu%*[:]%i%*[:]%i", what, &m->offset, &m1, &m2)) < 3) errx(1, "Invalid modification spec \"%s\"", s); @@ -107,7 +107,7 @@ r = s = read(STDIN_FILENO, buf, sizeof(buf)); if (r == 0) break; - if (r < 0) { + if (r == -1) { if (errno == EAGAIN || errno == EINTR) continue; err(1, "read"); @@ -130,7 +130,7 @@ r = write(STDOUT_FILENO, buf, s - o); if (r == 0) break; - if (r < 0) { + if (r == -1) { if (errno == EAGAIN || errno == EINTR) continue; err(1, "write"); diff -ruN openssh-9.4p1/regress/multiplex.sh openssh-9.4p1+x509-14.2.1/regress/multiplex.sh --- openssh-9.4p1/regress/multiplex.sh 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/multiplex.sh 2023-08-20 10:07:00.000000000 +0300 @@ -1,18 +1,17 @@ -# $OpenBSD: multiplex.sh,v 1.36 2023/03/01 09:29:32 dtucker Exp $ +# $OpenBSD: multiplex.sh,v 1.34 2022/06/03 04:31:54 djm Exp $ # Placed in the Public Domain. make_tmpdir -CTL=${SSH_REGRESS_TMP}/ctl-sock +CTL="$SSH_REGRESS_TMP"/ctl-sock tid="connection multiplexing" trace "will use ProxyCommand $proxycmd" if config_defined DISABLE_FD_PASSING ; then - echo "skipped (not supported on this platform)" - exit 0 + skip "not supported on this platform" fi -P=3301 # test port +P=${TEST_MULTIPLEX_PORT-3301} wait_for_mux_master_ready() { @@ -24,14 +23,13 @@ fatal "mux master never becomes ready" } -maybe_add_scp_path_to_sshd start_sshd start_mux_master() { trace "start master, fork to background" - ${SSH} -Nn2 -MS$CTL -F $OBJ/ssh_config -oSendEnv="_XXX_TEST" somehost \ - -E $TEST_REGRESS_LOGFILE 2>&1 & + $SSH -Nn2 -MS$CTL -F $OBJ/ssh_config -oSendEnv="_XXX_TEST" somehost \ + -E $TEST_REGRESS_LOGFILE 2>&1 & # NB. $SSH_PID will be killed by test-exec.sh:cleanup on fatal errors. SSH_PID=$! wait_for_mux_master_ready @@ -41,53 +39,74 @@ verbose "test $tid: setenv" trace "setenv over multiplexed connection" -_XXX_TEST=blah ${SSH} -F $OBJ/ssh_config -oSendEnv="_XXX_TEST" -S$CTL otherhost sh << 'EOF' +$SSH -F $OBJ/ssh_config -oSetEnv="_XXX_TEST=blah _XXX_TEST=blah1" -S$CTL otherhost sh << 'EOF' test X"$_XXX_TEST" = X"blah" EOF -if [ $? -ne 0 ]; then - fail "environment not found" +if test $? -ne 0 ; then + fail "environment not set" fi verbose "test $tid: envpass" trace "env passing over multiplexed connection" -${SSH} -F $OBJ/ssh_config -oSetEnv="_XXX_TEST=foo" -S$CTL otherhost sh << 'EOF' - test X"$_XXX_TEST" = X"foo" +_XXX_TEST=blah ${SSH} -F $OBJ/ssh_config -oSendEnv="_XXX_TEST" -S$CTL otherhost sh << 'EOF' + test X"$_XXX_TEST" = X"blah" EOF -if [ $? -ne 0 ]; then +if test $? -ne 0 ; then fail "environment not found" fi +if tty > /dev/null ; then +verbose "test $tid: pass TERM (tty)" +else +verbose "test $tid: pass TERM (stdin)" +fi +trace "pass env TERM over multiplexed connection" +( +if tty ; then +TERM=blah $SSH -F $OBJ/ssh_config -S$CTL -t otherhost \ + 'echo XXX${TERM}TEST' +else +echo "simulate some build environments where stdin is not tty" | \ +TERM=blah $SSH -F $OBJ/ssh_config -S$CTL -tt otherhost \ + 'echo XXX${TERM}TEST' +fi +) 2>>$TEST_REGRESS_LOGFILE | grep XXXblahTEST > /dev/null +if test $? -ne 0 ; then + fail "pass env TERM fail" +fi verbose "test $tid: transfer" rm -f ${COPY} trace "ssh transfer over multiplexed connection and check result" ${SSH} -F $OBJ/ssh_config -S$CTL otherhost cat ${DATA} > ${COPY} -test -f ${COPY} || fail "ssh -Sctl: failed copy ${DATA}" +test -f ${COPY} || fail "ssh -Sctl: failed copy ${DATA}" cmp ${DATA} ${COPY} || fail "ssh -Sctl: corrupted copy of ${DATA}" rm -f ${COPY} trace "ssh transfer over multiplexed connection and check result" ${SSH} -F $OBJ/ssh_config -S $CTL otherhost cat ${DATA} > ${COPY} -test -f ${COPY} || fail "ssh -S ctl: failed copy ${DATA}" +test -f ${COPY} || fail "ssh -S ctl: failed copy ${DATA}" cmp ${DATA} ${COPY} || fail "ssh -S ctl: corrupted copy of ${DATA}" rm -f ${COPY} trace "sftp transfer over multiplexed connection and check result" echo "get ${DATA} ${COPY}" | \ ${SFTP} -S ${SSH} -F $OBJ/ssh_config -oControlPath=$CTL otherhost >>$TEST_REGRESS_LOGFILE 2>&1 -test -f ${COPY} || fail "sftp: failed copy ${DATA}" +test -f ${COPY} || fail "sftp: failed copy ${DATA}" cmp ${DATA} ${COPY} || fail "sftp: corrupted copy of ${DATA}" rm -f ${COPY} trace "scp transfer over multiplexed connection and check result" -${SCP} -S ${SSH} -F $OBJ/ssh_config -oControlPath=$CTL otherhost:${DATA} ${COPY} >>$TEST_REGRESS_LOGFILE 2>&1 -test -f ${COPY} || fail "scp: failed copy ${DATA}" +# test requires pre-installed scp command +SCP_REMOTE_PREFIX=$BUILDDIR/ \ +$SCP -q -S $SSH -F $OBJ/ssh_config -oControlPath=$CTL otherhost:$DATA $COPY +test -f ${COPY} || fail "scp: failed copy ${DATA}" cmp ${DATA} ${COPY} || fail "scp: corrupted copy of ${DATA}" rm -f ${COPY} verbose "test $tid: forward" trace "forward over TCP/IP and check result" -$NC -N -l 127.0.0.1 $((${PORT} + 1)) < ${DATA} >`ssh_logfile nc` & +$NC -N -l 127.0.0.1 $((${PORT} + 1)) < ${DATA} > /dev/null & netcat_pid=$! ${SSH} -F $OBJ/ssh_config -S $CTL -Oforward -L127.0.0.1:$((${PORT} + 2)):127.0.0.1:$((${PORT} + 1)) otherhost >>$TEST_SSH_LOGFILE 2>&1 sleep 1 # XXX remove once race fixed @@ -108,18 +127,20 @@ rm -f ${COPY} $OBJ/unix-[123].fwd for s in 0 1 4 5 44; do - for mode in "" "-Oproxy"; do - trace "exit status $s over multiplexed connection ($mode)" - verbose "test $tid: status $s ($mode)" - ${SSH} -F $OBJ/ssh_config -S $CTL $mode otherhost exit $s + for ctlcmd in "" "-Oproxy"; do + ctlmsg= + test -n "$ctlcmd" && ctlmsg=" ($ctlcmd)" + trace "exit status $s over multiplexed connection$ctlmsg" + verbose "test $tid: status $s$ctlmsg" + ${SSH} -F $OBJ/ssh_config -S $CTL $ctlcmd otherhost exit $s r=$? if [ $r -ne $s ]; then fail "exit code mismatch: $r != $s" fi # same with early close of stdout/err - trace "exit status $s with early close over multiplexed connection ($mode)" - ${SSH} -F $OBJ/ssh_config -S $CTL -n $mode otherhost \ + trace "exit status $s with early close over multiplexed connection$ctlmsg" + ${SSH} -F $OBJ/ssh_config -S $CTL $ctlcmd -n otherhost \ exec sh -c \'"sleep 2; exec > /dev/null 2>&1; sleep 3; exit $s"\' r=$? if [ $r -ne $s ]; then @@ -130,7 +151,7 @@ verbose "test $tid: cmd check" ${SSH} -F $OBJ/ssh_config -S $CTL -Ocheck otherhost >>$TEST_REGRESS_LOGFILE 2>&1 \ - || fail "check command failed" + || fail "check command failed" verbose "test $tid: cmd forward local (TCP)" ${SSH} -F $OBJ/ssh_config -S $CTL -Oforward -L $P:localhost:$PORT otherhost \ @@ -158,12 +179,12 @@ ${SSH} -F $OBJ/ssh_config -S $CTL -Oforward -L $OBJ/unix-1.fwd:localhost:$PORT otherhost \ || fail "request local forward failed" sleep 1 # XXX remove once race fixed -echo "" | $NC -U $OBJ/unix-1.fwd | \ +printf '\r\n' | $NC -U $OBJ/unix-1.fwd | \ grep "Invalid SSH identification string" >/dev/null 2>&1 \ || fail "connect to local forward path failed" ${SSH} -F $OBJ/ssh_config -S $CTL -Ocancel -L $OBJ/unix-1.fwd:localhost:$PORT otherhost \ || fail "cancel local forward failed" -N=$(echo "xyzzy" | $NC -U $OBJ/unix-1.fwd 2>&1 | grep "xyzzy" | wc -l) +N=$(printf 'xyzzy\r\n' | $NC -U $OBJ/unix-1.fwd 2>&1 | wc -l) test ${N} -eq 0 || fail "local forward path still listening" rm -f $OBJ/unix-1.fwd @@ -171,18 +192,18 @@ ${SSH} -F $OBJ/ssh_config -S $CTL -Oforward -R $OBJ/unix-1.fwd:localhost:$PORT otherhost \ || fail "request remote forward failed" sleep 1 # XXX remove once race fixed -echo "" | $NC -U $OBJ/unix-1.fwd | \ +printf '\r\n' | $NC -U $OBJ/unix-1.fwd | \ grep "Invalid SSH identification string" >/dev/null 2>&1 \ || fail "connect to remote forwarded path failed" ${SSH} -F $OBJ/ssh_config -S $CTL -Ocancel -R $OBJ/unix-1.fwd:localhost:$PORT otherhost \ || fail "cancel remote forward failed" -N=$(echo "xyzzy" | $NC -U $OBJ/unix-1.fwd 2>&1 | grep "xyzzy" | wc -l) +N=$(printf 'xyzzy\r\n' | $NC -U $OBJ/unix-1.fwd 2>&1 | wc -l) test ${N} -eq 0 || fail "remote forward path still listening" rm -f $OBJ/unix-1.fwd verbose "test $tid: cmd exit" ${SSH} -F $OBJ/ssh_config -S $CTL -Oexit otherhost >>$TEST_REGRESS_LOGFILE 2>&1 \ - || fail "send exit command failed" + || fail "send exit command failed" # Wait for master to exit wait $SSH_PID @@ -194,8 +215,7 @@ start_mux_master # start a long-running command then immediately request a stop -${SSH} -F $OBJ/ssh_config -S $CTL otherhost "sleep 10; exit 0" \ - >>$TEST_REGRESS_LOGFILE 2>&1 & +$SSH -F $OBJ/ssh_config -S $CTL otherhost "sleep 10; exit 0" & SLEEP_PID=$! ${SSH} -F $OBJ/ssh_config -S $CTL -Ostop otherhost >>$TEST_REGRESS_LOGFILE 2>&1 \ || fail "send stop command failed" @@ -207,4 +227,3 @@ [ $! != 0 ] || fail "waiting for master stop" kill -0 $SSH_PID >/dev/null 2>&1 && fatal "stop command failed" SSH_PID="" # Already gone, so don't kill in cleanup - diff -ruN openssh-9.4p1/regress/multipubkey.sh openssh-9.4p1+x509-14.2.1/regress/multipubkey.sh --- openssh-9.4p1/regress/multipubkey.sh 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/multipubkey.sh 2023-08-20 10:07:00.000000000 +0300 @@ -31,20 +31,22 @@ opts="-oProtocol=2 -F $OBJ/ssh_proxy -oIdentitiesOnly=yes" opts="$opts -i $OBJ/cert_user_key1 -i $OBJ/user_key1 -i $OBJ/user_key2" +for privsep in $SSHD_PRIVSEP ; do for match in no yes ; do ( - cat $OBJ/sshd_proxy.orig + grep -v "Protocol" $OBJ/sshd_proxy.orig echo "Protocol 2" + echo "UsePrivilegeSeparation $privsep" echo "TrustedUserCAKeys $OBJ/user_ca_key.pub" echo "AuthorizedPrincipalsFile $OBJ/authorized_principals_%u" - ) > $OBJ/sshd_proxy if test "$match" = "yes" ; then - echo "AuthenticationMethods none" >> $OBJ/sshd_proxy - echo "PubkeyAuthentication no" >> $OBJ/sshd_proxy - echo "Match all" >> $OBJ/sshd_proxy - echo "PubkeyAuthentication yes" >> $OBJ/sshd_proxy + echo "AuthenticationMethods none" + echo "PubkeyAuthentication no" + echo "Match all" + echo "PubkeyAuthentication yes" fi - echo "AuthenticationMethods publickey,publickey" >> $OBJ/sshd_proxy + echo "AuthenticationMethods publickey,publickey" + ) > $OBJ/sshd_proxy # Single key should fail. trace "match $match single key" @@ -72,4 +74,4 @@ cat $OBJ/user_key2.pub > $OBJ/authorized_keys_$USER ${SSH} $opts proxy true || fail "ssh failed with key/cert" done - +done diff -ruN openssh-9.4p1/regress/netcat.c openssh-9.4p1+x509-14.2.1/regress/netcat.c --- openssh-9.4p1/regress/netcat.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/netcat.c 2023-08-20 10:07:01.000000000 +0300 @@ -56,7 +56,7 @@ #include "atomicio.h" #ifdef HAVE_POLL_H -#include +# include #else # ifdef HAVE_SYS_POLL_H # include @@ -79,11 +79,6 @@ #define WONT 252 #define WILL 251 -#ifndef SUN_LEN -#define SUN_LEN(su) \ - (sizeof(*(su)) - sizeof((su)->sun_path) + strlen((su)->sun_path)) -#endif - #define PORT_MAX 65535 #define PORT_MAX_LEN 6 #define UNIX_DG_TMP_SOCKET_SIZE 19 @@ -388,7 +383,7 @@ for (;;) { if (family != AF_UNIX) s = local_listen(host, uport, hints); - if (s < 0) + if (s == -1) err(1, "local_listen"); /* * For UDP and -k, don't connect the socket, let it @@ -414,7 +409,7 @@ err(1, "recvfrom"); rv = connect(s, (struct sockaddr *)&z, len); - if (rv < 0) + if (rv == -1) err(1, "connect"); if (vflag) @@ -439,7 +434,7 @@ if (family != AF_UNIX) close(s); else if (uflag) { - if (connect(s, NULL, 0) < 0) + if (connect(s, NULL, 0) == -1) err(1, "connect"); } @@ -530,7 +525,7 @@ /* Create unix domain socket. */ if ((s = socket(AF_UNIX, uflag ? SOCK_DGRAM : SOCK_STREAM, - 0)) < 0) + 0)) == -1) return (-1); memset(&sun_sa, 0, sizeof(struct sockaddr_un)); @@ -543,7 +538,7 @@ return (-1); } - if (bind(s, (struct sockaddr *)&sun_sa, SUN_LEN(&sun_sa)) < 0) { + if (bind(s, (struct sockaddr *)&sun_sa, sizeof(sun_sa)) == -1) { close(s); return (-1); } @@ -564,7 +559,7 @@ if ((s = unix_bind(unix_dg_tmp_socket)) < 0) return (-1); } else { - if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) + if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) return (-1); } (void)fcntl(s, F_SETFD, FD_CLOEXEC); @@ -578,7 +573,7 @@ errno = ENAMETOOLONG; return (-1); } - if (connect(s, (struct sockaddr *)&sun_sa, SUN_LEN(&sun_sa)) < 0) { + if (connect(s, (struct sockaddr *)&sun_sa, sizeof(sun_sa)) < 0) { close(s); return (-1); } @@ -597,7 +592,7 @@ if ((s = unix_bind(path)) < 0) return (-1); - if (listen(s, 5) < 0) { + if (listen(s, 5) == -1) { close(s); return (-1); } @@ -624,7 +619,7 @@ res0 = res; do { if ((s = socket(res0->ai_family, res0->ai_socktype, - res0->ai_protocol)) < 0) + res0->ai_protocol)) == -1) continue; #ifdef SO_RTABLE @@ -649,7 +644,7 @@ errx(1, "getaddrinfo: %s", gai_strerror(error)); if (bind(s, (struct sockaddr *)ares->ai_addr, - ares->ai_addrlen) < 0) + ares->ai_addrlen) == -1) err(1, "bind failed"); freeaddrinfo(ares); } @@ -685,7 +680,7 @@ err(1, "set non-blocking mode"); } - if ((ret = connect(s, name, namelen)) != 0 && errno == EINPROGRESS) { + if ((ret = connect(s, name, namelen)) == -1 && errno == EINPROGRESS) { pfd.fd = s; pfd.events = POLLOUT; if ((ret = poll(&pfd, 1, timeout)) == 1) { @@ -736,7 +731,7 @@ res0 = res; do { if ((s = socket(res0->ai_family, res0->ai_socktype, - res0->ai_protocol)) < 0) + res0->ai_protocol)) == -1) continue; #ifdef SO_RTABLE @@ -757,7 +752,7 @@ set_common_sockopts(s, res0->ai_family); if (bind(s, (struct sockaddr *)res0->ai_addr, - res0->ai_addrlen) == 0) + res0->ai_addrlen) != -1) break; close(s); @@ -765,7 +760,7 @@ } while ((res0 = res0->ai_next) != NULL); if (!uflag && s != -1) { - if (listen(s, 1) < 0) + if (listen(s, 1) == -1) err(1, "listen"); } @@ -1030,7 +1025,7 @@ cmsg->cmsg_len = CMSG_LEN(sizeof(int)); cmsg->cmsg_level = SOL_SOCKET; cmsg->cmsg_type = SCM_RIGHTS; - *(int *)CMSG_DATA(cmsg) = nfd; + memmove(CMSG_DATA(cmsg), &nfd, sizeof(nfd)); #endif vec.iov_base = &ch; @@ -1038,7 +1033,7 @@ msg.msg_iov = &vec; msg.msg_iovlen = 1; - bzero(&pfd, sizeof(pfd)); + memset(&pfd, 0, sizeof(pfd)); pfd.fd = STDOUT_FILENO; pfd.events = POLLOUT; for (;;) { @@ -1254,7 +1249,7 @@ { "netcontrol", IPTOS_PREC_NETCONTROL }, { "reliability", IPTOS_RELIABILITY }, { "throughput", IPTOS_THROUGHPUT }, - { NULL, -1 }, + { NULL, -1 }, }; for (t = toskeywords; t->keyword != NULL; t++) { @@ -1410,7 +1405,7 @@ int r; struct addrinfo hints, *res; - bzero(&hints, sizeof(hints)); + memset(&hints, 0, sizeof(hints)); hints.ai_family = v4only ? PF_INET : PF_UNSPEC; hints.ai_flags = numeric ? AI_NUMERICHOST : 0; hints.ai_socktype = SOCK_STREAM; @@ -1625,7 +1620,7 @@ "CONNECT %s:%d HTTP/1.0\r\n", host, ntohs(serverport)); } - if (r == -1 || (size_t)r >= sizeof(buf)) + if (r < 0 || (size_t)r >= sizeof(buf)) errx(1, "hostname too long"); r = strlen(buf); @@ -1639,13 +1634,13 @@ proxypass = getproxypass(proxyuser, proxyhost); r = snprintf(buf, sizeof(buf), "%s:%s", proxyuser, proxypass); - if (r == -1 || (size_t)r >= sizeof(buf) || + if (r < 0 || (size_t)r >= sizeof(buf) || b64_ntop(buf, strlen(buf), resp, sizeof(resp)) == -1) errx(1, "Proxy username/password too long"); r = snprintf(buf, sizeof(buf), "Proxy-Authorization: " "Basic %s\r\n", resp); - if (r == -1 || (size_t)r >= sizeof(buf)) + if (r < 0 || (size_t)r >= sizeof(buf)) errx(1, "Proxy auth response too long"); r = strlen(buf); if ((cnt = atomicio(vwrite, proxyfd, buf, r)) != (size_t)r) diff -ruN openssh-9.4p1/regress/percent.sh openssh-9.4p1+x509-14.2.1/regress/percent.sh --- openssh-9.4p1/regress/percent.sh 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/percent.sh 2023-08-20 10:07:00.000000000 +0300 @@ -10,9 +10,10 @@ USER=`id -u -n` USERID=`id -u` -HOST=`hostname | cut -f1 -d.` HOSTNAME=`hostname` -HASH="" +test -z "$HOSTNAME" && HOSTNAME=`uname -n` +HOST=`echo $HOSTNAME | cut -f1 -d.` +HASH= # Localcommand is evaluated after connection because %T is not available # until then. Because of this we use a different method of exercising it, @@ -22,8 +23,7 @@ trial() { - opt="$1"; arg="$2" - expect=`echo "$3" | sed 's|^//|/|'` # approximate realpath + opt="$1"; arg="$2"; expect="$3" trace "test $opt=$arg $expect" rm -f $OBJ/actual @@ -52,12 +52,12 @@ *forward) # LocalForward and RemoteForward take two args and only # operate on Unix domain socket paths - got=`${SSH} -F $OBJ/ssh_proxy -o $opt="/$arg /$arg" -G \ + got=`${SSH} -F $OBJ/ssh_proxy -o $opt="/$arg /$arg" -d \ remuser@somehost | awk '$1=="'$opt'"{print $2" "$3}'` expect="/$expect /$expect" ;; *) - got=`${SSH} -F $OBJ/ssh_proxy -o $opt="$arg" -G \ + got=`${SSH} -F $OBJ/ssh_proxy -o $opt="$arg" -d \ remuser@somehost | awk '$1=="'$opt'"{print $2}'` esac if [ "$got" != "$expect" ]; then @@ -81,12 +81,11 @@ trial $i '%T' NONE fi # Matches implementation in readconf.c:ssh_connection_hash() - if [ ! -z "${OPENSSL_BIN}" ]; then - HASH=`printf "${HOSTNAME}127.0.0.1${PORT}$REMUSER" | - $OPENSSL_BIN sha1 | cut -f2 -d' '` - trial $i '%C' $HASH - fi + HASH=`printf "${HOSTNAME}127.0.0.1${PORT}$REMUSER" | + $OPENSSL sha1 | cut -f2 -d' '` trial $i '%%' '%' + test -n "$HASH" && \ + trial $i '%C' $HASH trial $i '%i' $USERID trial $i '%h' 127.0.0.1 trial $i '%L' $HOST @@ -102,7 +101,7 @@ trial $i '%d' $HOME in='%%/%i/%h/%d/%L/%l/%n/%p/%r/%u' out="%/$USERID/127.0.0.1/$HOME/$HOST/$HOSTNAME/somehost/$PORT/$REMUSER/$USER" - if [ ! -z "${HASH}" ]; then + if test -n "$HASH" ; then in="$in/%C" out="$out/$HASH" fi @@ -122,8 +121,10 @@ # A subset of options support tilde expansion +PREFIX=$HOME +test "$PREFIX" = "/" && PREFIX= for i in controlpath identityagent forwardagent; do verbose $tid $i tilde - trial $i '~' $HOME/ - trial $i '~/.ssh' $HOME/.ssh + trial $i '~' $PREFIX/ + trial $i '~/.ssh' $PREFIX/.ssh done diff -ruN openssh-9.4p1/regress/principals-command.sh openssh-9.4p1+x509-14.2.1/regress/principals-command.sh --- openssh-9.4p1/regress/principals-command.sh 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/principals-command.sh 2023-08-20 10:07:00.000000000 +0300 @@ -10,10 +10,11 @@ skip "need SUDO to create file in /var/run, test won't work without" fi -case "$SSH_KEYTYPES" in - *ssh-rsa*) userkeytype=rsa ;; - *) userkeytype=ed25519 ;; -esac +if expr "$SSH_KEYTYPES" : '.*rsa' > /dev/null ; then + userkeytype=rsa +else + userkeytype=ed25519 +fi SERIAL=$$ @@ -36,7 +37,7 @@ PRINCIPALS_COMMAND="/var/run/principals_command_${LOGNAME}.$$" trap "$SUDO rm -f ${PRINCIPALS_COMMAND}" 0 cat << _EOF | $SUDO sh -c "cat > '$PRINCIPALS_COMMAND'" -#!/bin/sh +#! $TEST_SHELL test "x\$1" != "x${LOGNAME}" && exit 1 test "x\$2" != "xssh-${userkeytype}-cert-v01@openssh.com" && exit 1 test "x\$3" != "xssh-ed25519" && exit 1 @@ -53,22 +54,25 @@ $SUDO chmod 0755 "$PRINCIPALS_COMMAND" if ! $OBJ/check-perm -m keys-command $PRINCIPALS_COMMAND ; then - echo "skipping: $PRINCIPALS_COMMAND is unsuitable as " \ - "AuthorizedPrincipalsCommand" $SUDO rm -f $PRINCIPALS_COMMAND - exit 0 + skip "$PRINCIPALS_COMMAND is unsuitable as " \ + "AuthorizedPrincipalsCommand" fi -if [ ! -x $PRINCIPALS_COMMAND ]; then +if test ! -x $PRINCIPALS_COMMAND ; then skip "$PRINCIPALS_COMMAND not executable " \ "(/var/run mounted noexec?)" fi # Test explicitly-specified principals +for privsep in $SSHD_PRIVSEP ; do + _prefix="privsep $privsep" + # Setup for AuthorizedPrincipalsCommand rm -f $OBJ/authorized_keys_$USER ( cat $OBJ/sshd_proxy_bak + echo "UsePrivilegeSeparation $privsep" echo "AuthorizedKeysFile none" echo "AuthorizedPrincipalsCommand $PRINCIPALS_COMMAND" \ "%u %t %T %i %s %F %f %k %K" @@ -80,7 +84,7 @@ # XXX test failing command # Empty authorized_principals -verbose "$tid: empty authorized_principals" +verbose "$tid: ${_prefix} empty authorized_principals" echo > $OBJ/authorized_principals_$USER ${SSH} -i $OBJ/cert_user_key \ -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1 @@ -89,7 +93,7 @@ fi # Wrong authorized_principals -verbose "$tid: wrong authorized_principals" +verbose "$tid: ${_prefix} wrong authorized_principals" echo gregorsamsa > $OBJ/authorized_principals_$USER ${SSH} -i $OBJ/cert_user_key \ -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1 @@ -98,7 +102,7 @@ fi # Correct authorized_principals -verbose "$tid: correct authorized_principals" +verbose "$tid: ${_prefix} correct authorized_principals" echo mekmitasdigoat > $OBJ/authorized_principals_$USER ${SSH} -i $OBJ/cert_user_key \ -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1 @@ -107,7 +111,7 @@ fi # authorized_principals with bad key option -verbose "$tid: authorized_principals bad key opt" +verbose "$tid: ${_prefix} authorized_principals bad key opt" echo 'blah mekmitasdigoat' > $OBJ/authorized_principals_$USER ${SSH} -i $OBJ/cert_user_key \ -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1 @@ -116,7 +120,7 @@ fi # authorized_principals with command=false -verbose "$tid: authorized_principals command=false" +verbose "$tid: ${_prefix} authorized_principals command=false" echo 'command="false" mekmitasdigoat' > \ $OBJ/authorized_principals_$USER ${SSH} -i $OBJ/cert_user_key \ @@ -125,9 +129,8 @@ fail "ssh cert connect succeeded unexpectedly" fi - # authorized_principals with command=true -verbose "$tid: authorized_principals command=true" +verbose "$tid: ${_prefix} authorized_principals command=true" echo 'command="true" mekmitasdigoat' > \ $OBJ/authorized_principals_$USER ${SSH} -i $OBJ/cert_user_key \ @@ -137,14 +140,14 @@ fi # Setup for principals= key option -# TODO: remove? rm -f $OBJ/authorized_principals_$USER ( cat $OBJ/sshd_proxy_bak + echo "UsePrivilegeSeparation $privsep" ) > $OBJ/sshd_proxy # Wrong principals list -verbose "$tid: wrong principals key option" +verbose "$tid: ${_prefix} wrong principals key option" ( printf 'cert-authority,principals="gregorsamsa" ' cat $OBJ/user_ca_key.pub @@ -156,7 +159,7 @@ fi # Correct principals list -verbose "$tid: correct principals key option" +verbose "$tid: ${_prefix} correct principals key option" ( printf 'cert-authority,principals="mekmitasdigoat" ' cat $OBJ/user_ca_key.pub @@ -166,3 +169,4 @@ if [ $? -ne 0 ]; then fail "ssh cert connect failed" fi +done diff -ruN openssh-9.4p1/regress/proxy-connect.sh openssh-9.4p1+x509-14.2.1/regress/proxy-connect.sh --- openssh-9.4p1/regress/proxy-connect.sh 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/proxy-connect.sh 2023-08-20 10:07:00.000000000 +0300 @@ -9,18 +9,24 @@ comp="no yes" fi +mv $OBJ/sshd_proxy $OBJ/sshd_proxy.orig + +for ps in $SSHD_PRIVSEP ; do + cp $OBJ/sshd_proxy.orig $OBJ/sshd_proxy + echo "UsePrivilegeSeparation $ps" >> $OBJ/sshd_proxy for c in $comp; do - verbose "plain username comp=$c" + verbose "plain username privsep=$ps comp=$c" opts="-oCompression=$c -F $OBJ/ssh_proxy" SSH_CONNECTION=`${SSH} $opts 999.999.999.999 'echo $SSH_CONNECTION'` if [ $? -ne 0 ]; then - fail "ssh proxyconnect comp=$c failed" + fail "ssh proxyconnect privsep=$ps comp=$c failed" fi if [ "$SSH_CONNECTION" != "UNKNOWN 65535 UNKNOWN 65535" ]; then - fail "bad SSH_CONNECTION comp=$c: " \ + fail "bad SSH_CONNECTION privsep=$ps comp=$c: " \ "$SSH_CONNECTION" fi done +done verbose "username with style" ${SSH} -F $OBJ/ssh_proxy ${USER}:style@999.999.999.999 true || \ diff -ruN openssh-9.4p1/regress/putty-ciphers.sh openssh-9.4p1+x509-14.2.1/regress/putty-ciphers.sh --- openssh-9.4p1/regress/putty-ciphers.sh 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/putty-ciphers.sh 2023-08-20 10:07:00.000000000 +0300 @@ -3,16 +3,8 @@ tid="putty ciphers" -if test "x$REGRESS_INTEROP_PUTTY" != "xyes" ; then - skip "putty interop tests not enabled" -fi - -# Re-enable ssh-rsa on older PuTTY versions. -oldver="`${PLINK} --version | awk '/plink: Release/{if ($3<0.76)print "yes"}'`" -if [ "x$oldver" = "xyes" ]; then - echo "HostKeyAlgorithms +ssh-rsa" >> ${OBJ}/sshd_proxy - echo "PubkeyAcceptedKeyTypes +ssh-rsa" >> ${OBJ}/sshd_proxy -fi +$REGRESS_INTEROP_PUTTY || { RESUILT=1; skip "putty interop tests are not enabled"; } +echo "PLINK: $PLINK" >&2 for c in aes 3des aes128-ctr aes192-ctr aes256-ctr chacha20 ; do verbose "$tid: cipher $c" diff -ruN openssh-9.4p1/regress/putty-kex.sh openssh-9.4p1+x509-14.2.1/regress/putty-kex.sh --- openssh-9.4p1/regress/putty-kex.sh 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/putty-kex.sh 2023-08-20 10:07:00.000000000 +0300 @@ -3,16 +3,8 @@ tid="putty KEX" -if test "x$REGRESS_INTEROP_PUTTY" != "xyes" ; then - skip "putty interop tests not enabled" -fi - -# Re-enable ssh-rsa on older PuTTY versions. -oldver="`${PLINK} --version | awk '/plink: Release/{if ($3<0.76)print "yes"}'`" -if [ "x$oldver" = "xyes" ]; then - echo "HostKeyAlgorithms +ssh-rsa" >> ${OBJ}/sshd_proxy - echo "PubkeyAcceptedKeyTypes +ssh-rsa" >> ${OBJ}/sshd_proxy -fi +$REGRESS_INTEROP_PUTTY || { RESUILT=1; skip "putty interop tests are not enabled"; } +echo "PLINK: $PLINK" >&2 for k in dh-gex-sha1 dh-group1-sha1 dh-group14-sha1 ecdh ; do verbose "$tid: kex $k" diff -ruN openssh-9.4p1/regress/putty-transfer.sh openssh-9.4p1+x509-14.2.1/regress/putty-transfer.sh --- openssh-9.4p1/regress/putty-transfer.sh 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/putty-transfer.sh 2023-08-20 10:07:00.000000000 +0300 @@ -3,16 +3,8 @@ tid="putty transfer data" -if test "x$REGRESS_INTEROP_PUTTY" != "xyes" ; then - skip "putty interop tests not enabled" -fi - -# Re-enable ssh-rsa on older PuTTY versions. -oldver="`${PLINK} --version | awk '/plink: Release/{if ($3<0.76)print "yes"}'`" -if [ "x$oldver" = "xyes" ]; then - echo "HostKeyAlgorithms +ssh-rsa" >> ${OBJ}/sshd_proxy - echo "PubkeyAcceptedKeyTypes +ssh-rsa" >> ${OBJ}/sshd_proxy -fi +$REGRESS_INTEROP_PUTTY || { RESUILT=1; skip "putty interop tests are not enabled"; } +echo "PLINK: $PLINK" >&2 if [ "`${SSH} -Q compression`" = "none" ]; then comp="0" @@ -20,7 +12,7 @@ comp="0 1" fi -for c in $comp; do +for c in $comp; do verbose "$tid: compression $c" rm -f ${COPY} cp ${OBJ}/.putty/sessions/localhost_proxy \ diff -ruN openssh-9.4p1/regress/README.regress openssh-9.4p1+x509-14.2.1/regress/README.regress --- openssh-9.4p1/regress/README.regress 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/README.regress 2023-08-20 10:07:00.000000000 +0300 @@ -36,7 +36,7 @@ before running each test. TEST_SSH_SSH_CONFOPTS: Configuration directives to be added to ssh_config before running each test. -TEST_SSH_TRACE: set to "yes" for verbose output from tests +TEST_SSH_TRACE: set to "yes" for verbose output from tests TEST_SSH_x: path to "ssh" command under test, where x is one of SSH, SSHD, SSHAGENT, SSHADD, SSHKEYGEN, SSHKEYSCAN, SFTP or SFTPSERVER diff -ruN openssh-9.4p1/regress/reconfigure.sh openssh-9.4p1+x509-14.2.1/regress/reconfigure.sh --- openssh-9.4p1/regress/reconfigure.sh 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/reconfigure.sh 2023-08-20 10:07:00.000000000 +0300 @@ -1,4 +1,4 @@ -# $OpenBSD: reconfigure.sh,v 1.9 2021/06/10 09:46:28 dtucker Exp $ +# $OpenBSD: reconfigure.sh,v 1.6 2017/04/30 23:34:55 djm Exp $ # Placed in the Public Domain. tid="simple connect after reconfigure" @@ -40,26 +40,4 @@ ${SSH} -F $OBJ/ssh_config somehost true if [ $? -ne 0 ]; then fail "ssh connect with failed after reconfigure" -fi - -trace "reconfigure with active clients" -${SSH} -F $OBJ/ssh_config somehost sleep 10 # authenticated client -${NC} -d 127.0.0.1 $PORT >/dev/null & # unauthenticated client -PID=`$SUDO cat $PIDFILE` -rm -f $PIDFILE -$SUDO kill -HUP $PID - -trace "wait for sshd to restart" -i=0; -while [ ! -f $PIDFILE -a $i -lt 10 ]; do - i=`expr $i + 1` - sleep $i -done - -test -f $PIDFILE || fatal "sshd did not restart" - -trace "connect after restart with active clients" -${SSH} -F $OBJ/ssh_config somehost true -if [ $? -ne 0 ]; then - fail "ssh connect with failed after reconfigure" fi diff -ruN openssh-9.4p1/regress/reexec.sh openssh-9.4p1+x509-14.2.1/regress/reexec.sh --- openssh-9.4p1/regress/reexec.sh 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/reexec.sh 2023-08-20 10:07:00.000000000 +0300 @@ -1,4 +1,4 @@ -# $OpenBSD: reexec.sh,v 1.13 2023/01/19 07:53:45 dtucker Exp $ +# $OpenBSD: reexec.sh,v 1.12 2017/08/07 03:52:55 dtucker Exp $ # Placed in the Public Domain. tid="reexec tests" @@ -6,13 +6,12 @@ SSHD_ORIG=$SSHD SSHD_COPY=$OBJ/sshd +cp $OBJ/sshd_config $OBJ/sshd_config.orig + # Start a sshd and then delete it start_sshd_copy () { - # NB. prefer ln to cp here. On some OSX 19.4 configurations, - # djm has seen failure after fork() when the executable image - # has been removed from the filesystem. - ln $SSHD_ORIG $SSHD_COPY || cp $SSHD_ORIG $SSHD_COPY + cp $SSHD_ORIG $SSHD_COPY SSHD=$SSHD_COPY start_sshd SSHD=$SSHD_ORIG @@ -26,6 +25,8 @@ cat ${DATA} > ${COPY} if [ $? -ne 0 ]; then fail "ssh cat $DATA failed" + rm -f ${COPY} + return fi cmp ${DATA} ${COPY} || fail "corrupted copy" rm -f ${COPY} @@ -33,7 +34,8 @@ verbose "test config passing" -cp $OBJ/sshd_config $OBJ/sshd_config.orig +cp $OBJ/sshd_config.orig $OBJ/sshd_config + start_sshd echo "InvalidXXX=no" >> $OBJ/sshd_config @@ -41,17 +43,30 @@ stop_sshd -cp $OBJ/sshd_config.orig $OBJ/sshd_config - # cygwin can't fork a deleted binary if [ "$os" != "cygwin" ]; then verbose "test reexec fallback" +cp $OBJ/sshd_config.orig $OBJ/sshd_config + start_sshd_copy -$SUDO rm -f $SSHD_COPY +rm -f $SSHD_COPY copy_tests stop_sshd + +verbose "test reexec fallback without privsep" + +cp $OBJ/sshd_config.orig $OBJ/sshd_config +echo "UsePrivilegeSeparation=no" >> $OBJ/sshd_config + +start_sshd_copy +rm -f $SSHD_COPY + +copy_tests + +stop_sshd + fi diff -ruN openssh-9.4p1/regress/rekey.sh openssh-9.4p1+x509-14.2.1/regress/rekey.sh --- openssh-9.4p1/regress/rekey.sh 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/rekey.sh 2023-08-20 10:07:00.000000000 +0300 @@ -13,15 +13,15 @@ ssh_data_rekeying() { _kexopt=$1 ; shift - _opts="$@" - if ! test -z "$_kexopts" ; then + _opts=${1+"$@"} + if test -n "$_kexopt" ; then cp $OBJ/sshd_proxy_bak $OBJ/sshd_proxy echo "$_kexopt" >> $OBJ/sshd_proxy _opts="$_opts -o$_kexopt" fi rm -f ${COPY} ${LOG} _opts="$_opts -oCompression=no" - ${SSH} <${DATA} $_opts -v -F $OBJ/ssh_proxy somehost "cat > ${COPY}" + ${SSH} <${DATA} $_opts -vv -F $OBJ/ssh_proxy somehost "cat > ${COPY}" if [ $? -ne 0 ]; then fail "ssh failed ($@)" fi @@ -62,6 +62,9 @@ done fi +# restore configuration to prevent impact from previous tests +cp $OBJ/sshd_proxy_bak $OBJ/sshd_proxy + for s in 16 1k 128k 256k; do verbose "client rekeylimit ${s}" ssh_data_rekeying "" -oCompression=no -oRekeyLimit=$s diff -ruN openssh-9.4p1/regress/rsa_openssh.prv openssh-9.4p1+x509-14.2.1/regress/rsa_openssh.prv --- openssh-9.4p1/regress/rsa_openssh.prv 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/rsa_openssh.prv 2023-08-20 10:07:00.000000000 +0300 @@ -1,15 +1,16 @@ ------BEGIN RSA PRIVATE KEY----- -MIICWgIBAAKBgQDsilwKcaKN6wSMNd1WgQ9+HRqQEkD0kCTVttrazGu0OhBU3Uko -+dFD1Ip0CxdXmN25JQWxOYF7h/Ocu8P3jzv3RTX87xKR0YzlXTLX+SLtF/ySebS3 -xWPrlfRUDhh03hR5V+8xxvvy9widPYKw/oItwGSueOsEq1LTczCDv2dAjQIDAQAB -An8nH5VzvHkMbSqJ6eOYDsVwomRvYbH5IEaYl1x6VATITNvAu9kUdQ4NsSpuMc+7 -Jj9gKZvmO1y2YCKc0P/iO+i/eV0L+yQh1Rw18jQZll+12T+LZrKRav03YNvMx0gN -wqWY48Kt6hv2/N/ebQzKRe79+D0t2cTh92hT7xENFLIBAkEBGnoGKFjAUkJCwO1V -mzpUqMHpRZVOrqP9hUmPjzNJ5oBPFGe4+h1hoSRFOAzaNuZt8ssbqaLCkzB8bfzj -qhZqAQJBANZekuUpp8iBLeLSagw5FkcPwPzq6zfExbhvsZXb8Bo/4SflNs4JHXwI -7SD9Z8aJLvM4uQ/5M70lblDMQ40i3o0CQQDIJvBYBFL5tlOgakq/O7yi+wt0L5BZ -9H79w5rCSAA0IHRoK/qI1urHiHC3f3vbbLk5UStfrqEaND/mm0shyNIBAkBLsYdC -/ctt5Bc0wUGK4Vl5bBmj9LtrrMJ4FpBpLwj/69BwCuKoK9XKZ0h73p6XHveCEGRg -PIlFX4MtaoLrwgU9AkBV2k4dgIws+X8YX65EsyyFjnlDqX4x0nSOjQB1msIKfHBr -dh5XLDBTTCxnKhMJ0Yx/opgOvf09XHBFwaQntR5i ------END RSA PRIVATE KEY----- +-----BEGIN PRIVATE KEY----- +MIICdAIBADANBgkqhkiG9w0BAQEFAASCAl4wggJaAgEAAoGBAOyKXApxoo3rBIw1 +3VaBD34dGpASQPSQJNW22trMa7Q6EFTdSSj50UPUinQLF1eY3bklBbE5gXuH85y7 +w/ePO/dFNfzvEpHRjOVdMtf5Iu0X/JJ5tLfFY+uV9FQOGHTeFHlX7zHG+/L3CJ09 +grD+gi3AZK546wSrUtNzMIO/Z0CNAgMBAAECfycflXO8eQxtKonp45gOxXCiZG9h +sfkgRpiXXHpUBMhM28C72RR1Dg2xKm4xz7smP2Apm+Y7XLZgIpzQ/+I76L95XQv7 +JCHVHDXyNBmWX7XZP4tmspFq/Tdg28zHSA3CpZjjwq3qG/b8395tDMpF7v34PS3Z +xOH3aFPvEQ0UsgECQQEaegYoWMBSQkLA7VWbOlSowelFlU6uo/2FSY+PM0nmgE8U +Z7j6HWGhJEU4DNo25m3yyxuposKTMHxt/OOqFmoBAkEA1l6S5SmnyIEt4tJqDDkW +Rw/A/OrrN8TFuG+xldvwGj/hJ+U2zgkdfAjtIP1nxoku8zi5D/kzvSVuUMxDjSLe +jQJBAMgm8FgEUvm2U6BqSr87vKL7C3QvkFn0fv3DmsJIADQgdGgr+ojW6seIcLd/ +e9tsuTlRK1+uoRo0P+abSyHI0gECQEuxh0L9y23kFzTBQYrhWXlsGaP0u2uswngW +kGkvCP/r0HAK4qgr1cpnSHvenpce94IQZGA8iUVfgy1qguvCBT0CQFXaTh2AjCz5 +fxhfrkSzLIWOeUOpfjHSdI6NAHWawgp8cGt2HlcsMFNMLGcqEwnRjH+imA69/T1c +cEXBpCe1HmI= +-----END PRIVATE KEY----- diff -ruN openssh-9.4p1/regress/scp3.sh openssh-9.4p1+x509-14.2.1/regress/scp3.sh --- openssh-9.4p1/regress/scp3.sh 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/scp3.sh 2023-08-20 10:07:00.000000000 +0300 @@ -1,20 +1,15 @@ -# $OpenBSD: scp3.sh,v 1.4 2023/01/13 04:47:34 dtucker Exp $ +# $OpenBSD: scp3.sh,v 1.3 2021/08/10 03:35:45 djm Exp $ # Placed in the Public Domain. tid="scp3" -set -x +#set -x COPY2=${OBJ}/copy2 DIR=${COPY}.dd DIR2=${COPY}.dd2 -maybe_add_scp_path_to_sshd - SRC=`dirname ${SCRIPT}` -cp ${SRC}/scp-ssh-wrapper.sh ${OBJ}/scp-ssh-wrapper.scp -chmod 755 ${OBJ}/scp-ssh-wrapper.scp -export SCP # used in scp-ssh-wrapper.scp scpclean() { rm -rf ${COPY} ${COPY2} ${DIR} ${DIR2} @@ -22,23 +17,27 @@ chmod 755 ${DIR} ${DIR2} } -for mode in scp sftp ; do - scpopts="-F${OBJ}/ssh_proxy -S ${SSH} -q" +for mode in $SCP_MODES ; do tag="$tid: $mode mode" + scpopts="-q" if test $mode = scp ; then - scpopts="$scpopts -O" + scpopts="$scpopts -O -S ${SSH} -F${OBJ}/ssh_proxy" else - scpopts="-s -D ${SFTPSERVER}" + scpopts="$scpopts -s -D ${SFTPSERVER}" fi verbose "$tag: simple copy remote file to remote file" scpclean + SCP_REMOTE_PREFIX=$BUILDDIR/ \ + SCP_REMOTE_PREFIX2=$BUILDDIR/ \ $SCP $scpopts -3 hostA:${DATA} hostB:${COPY} || fail "copy failed" cmp ${DATA} ${COPY} || fail "corrupted copy" verbose "$tag: simple copy remote file to remote dir" scpclean cp ${DATA} ${COPY} + SCP_REMOTE_PREFIX=$BUILDDIR/ \ + SCP_REMOTE_PREFIX2=$BUILDDIR/ \ $SCP $scpopts -3 hostA:${COPY} hostB:${DIR} || fail "copy failed" cmp ${COPY} ${DIR}/copy || fail "corrupted copy" @@ -46,6 +45,8 @@ scpclean rm -rf ${DIR2} cp ${DATA} ${DIR}/copy + SCP_REMOTE_PREFIX=$BUILDDIR/ \ + SCP_REMOTE_PREFIX2=$BUILDDIR/ \ $SCP $scpopts -3r hostA:${DIR} hostB:${DIR2} || fail "copy failed" diff -r ${DIR} ${DIR2} || fail "corrupted copy" diff -r ${DIR2} ${DIR} || fail "corrupted copy" @@ -54,9 +55,10 @@ scpclean echo a > ${COPY} echo b > ${COPY2} + SCP_REMOTE_PREFIX=$BUILDDIR/ \ + SCP_REMOTE_PREFIX2=$BUILDDIR/ \ $SCP $scpopts -3 hostA:${DATA} hostA:${COPY} hostB:${COPY2} cmp ${COPY} ${COPY2} >/dev/null && fail "corrupt target" done scpclean -rm -f ${OBJ}/scp-ssh-wrapper.exe diff -ruN openssh-9.4p1/regress/scp.sh openssh-9.4p1+x509-14.2.1/regress/scp.sh --- openssh-9.4p1/regress/scp.sh 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/scp.sh 2023-08-20 10:07:00.000000000 +0300 @@ -1,4 +1,4 @@ -# $OpenBSD: scp.sh,v 1.18 2023/01/13 04:47:34 dtucker Exp $ +# $OpenBSD: scp.sh,v 1.16 2022/10/30 18:42:07 dtucker Exp $ # Placed in the Public Domain. tid="scp" @@ -17,12 +17,9 @@ DIFFOPT="-r" fi -maybe_add_scp_path_to_sshd - SRC=`dirname ${SCRIPT}` cp ${SRC}/scp-ssh-wrapper.sh ${OBJ}/scp-ssh-wrapper.scp chmod 755 ${OBJ}/scp-ssh-wrapper.scp -export SCP # used in scp-ssh-wrapper.scp scpclean() { rm -rf ${COPY} ${COPY2} ${DIR} ${DIR2} ${COPY3} ${DIR3} @@ -30,12 +27,13 @@ chmod 755 ${DIR} ${DIR2} ${DIR3} } -for mode in scp sftp ; do +for mode in $SCP_MODES ; do tag="$tid: $mode mode" + scpopts="-q" if test $mode = scp ; then - scpopts="-O -q -S ${OBJ}/scp-ssh-wrapper.scp" + scpopts="$scpopts -O -S ${OBJ}/scp-ssh-wrapper.scp" else - scpopts="-s -D ${SFTPSERVER}" + scpopts="$scpopts -s -D ${SFTPSERVER}" fi verbose "$tag: simple copy local file to local file" scpclean @@ -68,7 +66,6 @@ scpclean cat ${DATA} ${DATA} > ${COPY} $SCP $scpopts ${DATA} somehost:${COPY} || fail "copy failed" - ls -l $DATA $COPY cmp ${DATA} ${COPY} || fail "corrupted copy" verbose "$tag: copy remote file to local file clobber" @@ -147,7 +144,7 @@ $SCP $scpopts *metachar* ${DIR2} 2>/dev/null; \ [ ! -f metachartest ] ) || fail "shell metacharacters" - if [ ! -z "$SUDO" ]; then + if test -n "$SUDO" ; then verbose "$tag: skipped file after scp -p with failed chown+utimes" scpclean cp -p ${DATA} ${DIR}/copy @@ -187,7 +184,7 @@ scpclean echo a > ${COPY} echo b > ${COPY2} - $SCP $scpopts ${DATA} ${COPY} ${COPY2} + $SCP $scpopts ${DATA} ${COPY} ${COPY2} >>$TEST_REGRESS_LOGFILE 2>&1 cmp ${COPY} ${COPY2} >/dev/null && fail "corrupt target" done diff -ruN openssh-9.4p1/regress/scp-ssh-wrapper.sh openssh-9.4p1+x509-14.2.1/regress/scp-ssh-wrapper.sh --- openssh-9.4p1/regress/scp-ssh-wrapper.sh 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/scp-ssh-wrapper.sh 2023-08-20 10:07:00.000000000 +0300 @@ -66,6 +66,6 @@ *) set -- $arg shift - exec $SCP "$@" + exec $SCP ${1+"$@"} ;; esac diff -ruN openssh-9.4p1/regress/scp-uri.sh openssh-9.4p1+x509-14.2.1/regress/scp-uri.sh --- openssh-9.4p1/regress/scp-uri.sh 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/scp-uri.sh 2023-08-20 10:07:00.000000000 +0300 @@ -1,4 +1,4 @@ -# $OpenBSD: scp-uri.sh,v 1.5 2023/01/13 04:47:34 dtucker Exp $ +# $OpenBSD: scp-uri.sh,v 1.4 2021/08/10 03:35:45 djm Exp $ # Placed in the Public Domain. tid="scp-uri" @@ -9,8 +9,6 @@ DIR=${COPY}.dd DIR2=${COPY}.dd2 -maybe_add_scp_path_to_sshd - SRC=`dirname ${SCRIPT}` cp ${SRC}/scp-ssh-wrapper.sh ${OBJ}/scp-ssh-wrapper.scp chmod 755 ${OBJ}/scp-ssh-wrapper.scp @@ -25,12 +23,13 @@ cp $OBJ/ssh_config $OBJ/ssh_config.orig egrep -v '^ +(Port|User) +.*$' $OBJ/ssh_config.orig > $OBJ/ssh_config -for mode in scp sftp ; do +for mode in $SCP_MODES ; do tag="$tid: $mode mode" + scpopts="-q" if test $mode = scp ; then - scpopts="-O -q -S ${OBJ}/scp-ssh-wrapper.scp" + scpopts="$scpopts -O -S ${OBJ}/scp-ssh-wrapper.scp" else - scpopts="-s -D ${SFTPSERVER}" + scpopts="$scpopts -s -D ${SFTPSERVER}" fi verbose "$tag: simple copy local file to remote file" scpclean @@ -76,4 +75,4 @@ done scpclean -rm -f ${OBJ}/scp-ssh-wrapper.exe +rm -f ${OBJ}/scp-ssh-wrapper.scp diff -ruN openssh-9.4p1/regress/servcfginclude.sh openssh-9.4p1+x509-14.2.1/regress/servcfginclude.sh --- openssh-9.4p1/regress/servcfginclude.sh 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/servcfginclude.sh 2023-08-20 10:07:00.000000000 +0300 @@ -2,6 +2,13 @@ tid="server config include" +# cross-project configuration +if test "$sshd_type" = "pkix" ; then + unset_arg='' +else + unset_arg=none +fi + cat > $OBJ/sshd_config.i << _EOF HostKey $OBJ/host.ssh-ed25519 Match host a @@ -9,17 +16,17 @@ Match host b Banner /bb - Include $OBJ/sshd_config.i.* # comment + Include $OBJ/sshd_config.i.* Match host c - Include $OBJ/sshd_config.i.* # comment + Include $OBJ/sshd_config.i.* Banner /cc Match host m Include $OBJ/sshd_config.i.* Match Host d - Banner /dd # comment + Banner /dd Match Host e Banner /ee @@ -64,7 +71,7 @@ Match host b Banner /bbbb -Match host c # comment +Match host c Banner /cccc Match Host d @@ -103,7 +110,7 @@ trial f /fff trial m /xxxx trial n /xxxx -trial x none +trial x $unset_arg # Prepare an included config with an error. @@ -150,7 +157,7 @@ -C "host=x,user=test,addr=127.0.0.1" 2>/dev/null && \ fail "sshd allowed Include with no argument" -# Ensure the Include before any Match block works as expected (bug #3122) +# ensure the Include before any Match block works as expected cat > $OBJ/sshd_config.i << _EOF Banner /xx HostKey $OBJ/host.ssh-ed25519 @@ -166,7 +173,7 @@ trace "Include before match blocks" trial a /aa "included file before match blocks is properly evaluated" -# Port in included file is correctly interpretted (bug #3169) +# test if port in included file is correctly interpreted cat > $OBJ/sshd_config.i << _EOF Include $OBJ/sshd_config.i.2 Port 7722 diff -ruN openssh-9.4p1/regress/sftp-badcmds.sh openssh-9.4p1+x509-14.2.1/regress/sftp-badcmds.sh --- openssh-9.4p1/regress/sftp-badcmds.sh 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/sftp-badcmds.sh 2023-08-20 10:07:00.000000000 +0300 @@ -57,7 +57,7 @@ rm -rf ${COPY} cp ${DATA2} ${COPY} verbose "$tid: glob put files to local file" -echo "put /bin/l* $COPY" | ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 +echo "put /bin/l* $COPY" | ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 cmp ${DATA2} ${COPY} || fail "put succeeded when it should have failed" rm -rf ${COPY} ${COPY}.1 ${COPY}.2 ${COPY}.dd diff -ruN openssh-9.4p1/regress/sftp-chroot.sh openssh-9.4p1+x509-14.2.1/regress/sftp-chroot.sh --- openssh-9.4p1/regress/sftp-chroot.sh 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/sftp-chroot.sh 2023-08-20 10:07:00.000000000 +0300 @@ -16,32 +16,31 @@ skip "$CHROOT is unsuitable as ChrootDirectory" fi +verbose "test $tid: get" $SUDO sh -c "echo mekmitastdigoat > $PRIVDATA" || \ fatal "create $PRIVDATA failed" echo "ForceCommand internal-sftp -d /" >> $OBJ/sshd_config start_sshd -oChrootDirectory=$CHROOT - -verbose "test $tid: get" ${SFTP} -S "$SSH" -F $OBJ/ssh_config host:/${FILENAME} $COPY \ >>$TEST_REGRESS_LOGFILE 2>&1 || \ fatal "Fetch ${FILENAME} failed" cmp $PRIVDATA $COPY || fail "$PRIVDATA $COPY differ" - stop_sshd verbose "test $tid: match" +$SUDO sh -c "echo orpheanbeholder > $PRIVDATA" || \ + fatal "create $PRIVDATA failed" + cat << EOF >> $OBJ/sshd_config Match All ChrootDirectory $CHROOT EOF + start_sshd -$SUDO sh -c "echo orpheanbeholder > $PRIVDATA" || \ - fatal "create $PRIVDATA failed" ${SFTP} -S "$SSH" -F $OBJ/ssh_config host:/${FILENAME} $COPY \ >>$TEST_REGRESS_LOGFILE 2>&1 || \ fatal "Fetch ${FILENAME} failed" cmp $PRIVDATA $COPY || fail "$PRIVDATA $COPY differ" - stop_sshd diff -ruN openssh-9.4p1/regress/sftp-cmds.sh openssh-9.4p1+x509-14.2.1/regress/sftp-cmds.sh --- openssh-9.4p1/regress/sftp-cmds.sh 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/sftp-cmds.sh 2023-08-20 10:07:00.000000000 +0300 @@ -1,7 +1,7 @@ -# $OpenBSD: sftp-cmds.sh,v 1.15 2022/03/31 03:07:33 djm Exp $ +# $OpenBSD: sftp-cmds.sh,v 1.14 2013/06/21 02:26:26 djm Exp $ # Placed in the Public Domain. -# XXX - TODO: +# XXX - TODO: # - chmod / chown / chgrp # - -p flag for get & put @@ -197,11 +197,6 @@ echo "ln -s ${COPY}.1 ${COPY}.2" | ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 || fail "ln -s failed" test -h ${COPY}.2 || fail "missing file after ln -s" -verbose "$tid: cp" -rm -f ${COPY}.2 -echo "cp ${COPY}.1 ${COPY}.2" | ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 || fail "cp failed" -cmp ${COPY}.1 ${COPY}.2 || fail "created file is not equal after cp" - verbose "$tid: mkdir" echo "mkdir ${COPY}.dd" | ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 \ || fail "mkdir failed" diff -ruN openssh-9.4p1/regress/sftp-perm.sh openssh-9.4p1+x509-14.2.1/regress/sftp-perm.sh --- openssh-9.4p1/regress/sftp-perm.sh 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/sftp-perm.sh 2023-08-20 10:07:00.000000000 +0300 @@ -1,4 +1,4 @@ -# $OpenBSD: sftp-perm.sh,v 1.3 2021/03/31 21:59:26 djm Exp $ +# $OpenBSD: sftp-perm.sh,v 1.2 2013/10/17 22:00:18 djm Exp $ # Placed in the Public Domain. tid="sftp permissions" @@ -7,14 +7,28 @@ CLIENT_LOG=${OBJ}/sftp.log TEST_SFTP_SERVER=${OBJ}/sftp-server.sh +prepare_server_bad() { +# NOTE: Some shells expand all arguments as single quoted string! +# Also some getopt(1) on split "-f option" command argument did +# not clean leading spaces. + cat > $TEST_SFTP_SERVER < $SERVER_LOG +EOF + chmod a+x $TEST_SFTP_SERVER +} + prepare_server() { - printf "#!/bin/sh\nexec $SFTPSERVER -el debug3 $* 2>$SERVER_LOG\n" \ - > $TEST_SFTP_SERVER +# NOTE: Caller does not use arguments with spaces. + cat > $TEST_SFTP_SERVER < $SERVER_LOG +EOF chmod a+x $TEST_SFTP_SERVER } run_client() { - echo "$@" | ${SFTP} -D ${TEST_SFTP_SERVER} -vvvb - >$CLIENT_LOG 2>&1 + echo ${1+"$@"} | $SFTP -D $TEST_SFTP_SERVER -vvvb - >$CLIENT_LOG 2>&1 } prepare_files() { @@ -220,15 +234,13 @@ "test ! -d ${COPY}.dd" \ "test -d ${COPY}.dd" -# Can't readily test this because the client falls back to traditional rename. -# XXX maybe there is a behaviorial difference we can test for? -#perm_test \ -# "posix-rename" \ -# "realpath,stat,lstat" \ -# "rename $COPY ${COPY}.1" \ -# "touch $COPY" \ -# "test -f ${COPY}.1 -a ! -f $COPY" \ -# "test -f $COPY -a ! -f ${COPY}.1" +perm_test \ + "posix-rename" \ + "realpath,stat,lstat" \ + "rename $COPY ${COPY}.1" \ + "touch $COPY" \ + "test -f ${COPY}.1 -a ! -f $COPY" \ + "test -f $COPY -a ! -f ${COPY}.1" perm_test \ "rename" \ @@ -268,4 +280,4 @@ # fstatvfs rm -rf ${COPY} ${COPY}.1 ${COPY}.dd - +rm -rf ${OBJ}/sftp-server.sh diff -ruN openssh-9.4p1/regress/sftp-uri.sh openssh-9.4p1+x509-14.2.1/regress/sftp-uri.sh --- openssh-9.4p1/regress/sftp-uri.sh 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/sftp-uri.sh 2023-08-20 10:07:00.000000000 +0300 @@ -5,13 +5,12 @@ #set -x -COPY2=${OBJ}/copy2 DIR=${COPY}.dd DIR2=${COPY}.dd2 SRC=`dirname ${SCRIPT}` sftpclean() { - rm -rf ${COPY} ${COPY2} ${DIR} ${DIR2} + rm -rf ${COPY} ${DIR} ${DIR2} mkdir ${DIR} ${DIR2} } diff -ruN openssh-9.4p1/regress/ssh2putty.sh openssh-9.4p1+x509-14.2.1/regress/ssh2putty.sh --- openssh-9.4p1/regress/ssh2putty.sh 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/ssh2putty.sh 2023-08-20 10:07:00.000000000 +0300 @@ -1,5 +1,5 @@ #!/bin/sh -# $OpenBSD: ssh2putty.sh,v 1.9 2021/07/25 12:13:03 dtucker Exp $ +# $OpenBSD: ssh2putty.sh,v 1.8 2021/06/02 00:17:45 dtucker Exp $ if test "x$1" = "x" -o "x$2" = "x" -o "x$3" = "x" ; then echo "Usage: ssh2putty hostname port ssh-private-key" @@ -10,7 +10,7 @@ PORT=$2 KEYFILE=$3 -OPENSSL_BIN="${OPENSSL_BIN:-openssl}" +OPENSSL=${OPENSSL-openssl} # XXX - support DSA keys too if grep "BEGIN RSA PRIVATE KEY" $KEYFILE >/dev/null 2>&1 ; then @@ -21,13 +21,13 @@ fi public_exponent=` - $OPENSSL_BIN rsa -noout -text -in $KEYFILE | grep ^publicExponent | + $OPENSSL rsa -noout -text -in $KEYFILE | grep ^publicExponent | sed 's/.*(//;s/).*//' ` test $? -ne 0 && exit 1 modulus=` - $OPENSSL_BIN rsa -noout -modulus -in $KEYFILE | grep ^Modulus= | + $OPENSSL rsa -noout -modulus -in $KEYFILE | grep ^Modulus= | sed 's/^Modulus=/0x/' | tr A-Z a-z ` test $? -ne 0 && exit 1 diff -ruN openssh-9.4p1/regress/sshcfgparse.sh openssh-9.4p1+x509-14.2.1/regress/sshcfgparse.sh --- openssh-9.4p1/regress/sshcfgparse.sh 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/sshcfgparse.sh 2023-08-20 10:07:00.000000000 +0300 @@ -3,105 +3,57 @@ tid="ssh config parse" -dsa=0 -for t in $SSH_KEYTYPES; do - case "$t" in - ssh-dss) dsa=1 ;; - esac -done - expect_result_present() { _str="$1" ; shift - for _expect in "$@" ; do + for _expect in ${1+"$@"} ; do echo "$f" | tr ',' '\n' | grep "^$_expect\$" >/dev/null if test $? -ne 0 ; then fail "missing expected \"$_expect\" from \"$_str\"" fi done } -expect_result_absent() { - _str="$1" ; shift - for _expect in "$@" ; do - echo "$f" | tr ',' '\n' | grep "^$_expect\$" >/dev/null - if test $? -eq 0 ; then - fail "unexpected \"$_expect\" present in \"$_str\"" - fi - done -} verbose "reparse minimal config" -(${SSH} -G -F $OBJ/ssh_config somehost >$OBJ/ssh_config.1 && - ${SSH} -G -F $OBJ/ssh_config.1 somehost >$OBJ/ssh_config.2 && +(${SSH} -d -F $OBJ/ssh_config somehost >$OBJ/ssh_config.1 && + ${SSH} -d -F $OBJ/ssh_config.1 somehost >$OBJ/ssh_config.2 && diff $OBJ/ssh_config.1 $OBJ/ssh_config.2) || fail "failed to reparse minimal" verbose "ssh -W opts" -f=`${SSH} -GF $OBJ/ssh_config host | awk '/exitonforwardfailure/{print $2}'` +f=`${SSH} -dF $OBJ/ssh_config host | awk '/exitonforwardfailure/{print $2}'` test "$f" = "no" || fail "exitonforwardfailure default" -f=`${SSH} -GF $OBJ/ssh_config -W a:1 h | awk '/exitonforwardfailure/{print $2}'` +f=`${SSH} -dF $OBJ/ssh_config -W a:1 h | awk '/exitonforwardfailure/{print $2}'` test "$f" = "yes" || fail "exitonforwardfailure enable" -f=`${SSH} -GF $OBJ/ssh_config -W a:1 -o exitonforwardfailure=no h | \ +f=`${SSH} -dF $OBJ/ssh_config -W a:1 -o exitonforwardfailure=no h | \ awk '/exitonforwardfailure/{print $2}'` test "$f" = "no" || fail "exitonforwardfailure override" -f=`${SSH} -GF $OBJ/ssh_config host | awk '/clearallforwardings/{print $2}'` +f=`${SSH} -dF $OBJ/ssh_config host | awk '/clearallforwardings/{print $2}'` test "$f" = "no" || fail "clearallforwardings default" -f=`${SSH} -GF $OBJ/ssh_config -W a:1 h | awk '/clearallforwardings/{print $2}'` +f=`${SSH} -dF $OBJ/ssh_config -W a:1 h | awk '/clearallforwardings/{print $2}'` test "$f" = "yes" || fail "clearallforwardings enable" -f=`${SSH} -GF $OBJ/ssh_config -W a:1 -o clearallforwardings=no h | \ +f=`${SSH} -dF $OBJ/ssh_config -W a:1 -o clearallforwardings=no h | \ awk '/clearallforwardings/{print $2}'` test "$f" = "no" || fail "clearallforwardings override" verbose "user first match" user=`awk '$1=="User" {print $2}' $OBJ/ssh_config` -f=`${SSH} -GF $OBJ/ssh_config host | awk '/^user /{print $2}'` +f=`${SSH} -dF $OBJ/ssh_config host | awk '/^user /{print $2}'` test "$f" = "$user" || fail "user from config, expected '$user' got '$f'" -f=`${SSH} -GF $OBJ/ssh_config -o user=foo -l bar baz@host | awk '/^user /{print $2}'` +f=`${SSH} -dF $OBJ/ssh_config -o user=foo -l bar baz@host | awk '/^user /{print $2}'` test "$f" = "foo" || fail "user first match -oUser, expected 'foo' got '$f' " -f=`${SSH} -GF $OBJ/ssh_config -lbar baz@host user=foo baz@host | awk '/^user /{print $2}'` +f=`${SSH} -dF $OBJ/ssh_config -lbar baz@host user=foo baz@host | awk '/^user /{print $2}'` test "$f" = "bar" || fail "user first match -l, expected 'bar' got '$f'" -f=`${SSH} -GF $OBJ/ssh_config baz@host -o user=foo -l bar baz@host | awk '/^user /{print $2}'` +f=`${SSH} -dF $OBJ/ssh_config baz@host -o user=foo -l bar baz@host | awk '/^user /{print $2}'` test "$f" = "baz" || fail "user first match user@host, expected 'baz' got '$f'" -verbose "pubkeyacceptedalgorithms" -# Default set -f=`${SSH} -GF none host | awk '/^pubkeyacceptedalgorithms /{print $2}'` -expect_result_present "$f" "ssh-ed25519" "ssh-ed25519-cert-v01.*" -expect_result_absent "$f" "ssh-dss" -# Explicit override -f=`${SSH} -GF none -opubkeyacceptedalgorithms=ssh-ed25519 host | \ - awk '/^pubkeyacceptedalgorithms /{print $2}'` -expect_result_present "$f" "ssh-ed25519" -expect_result_absent "$f" "ssh-ed25519-cert-v01.*" "ssh-dss" -# Removal from default set -f=`${SSH} -GF none -opubkeyacceptedalgorithms=-ssh-ed25519-cert* host | \ - awk '/^pubkeyacceptedalgorithms /{print $2}'` -expect_result_present "$f" "ssh-ed25519" -expect_result_absent "$f" "ssh-ed25519-cert-v01.*" "ssh-dss" -f=`${SSH} -GF none -opubkeyacceptedalgorithms=-ssh-ed25519 host | \ - awk '/^pubkeyacceptedalgorithms /{print $2}'` -expect_result_present "$f" "ssh-ed25519-cert-v01.*" -expect_result_absent "$f" "ssh-ed25519" "ssh-dss" -# Append to default set. -# This is not tested when built !WITH_OPENSSL -if [ "$dsa" = "1" ]; then - f=`${SSH} -GF none -opubkeyacceptedalgorithms=+ssh-dss-cert* host | \ - awk '/^pubkeyacceptedalgorithms /{print $2}'` - expect_result_present "$f" "ssh-ed25519" "ssh-dss-cert-v01.*" - expect_result_absent "$f" "ssh-dss" - f=`${SSH} -GF none -opubkeyacceptedalgorithms=+ssh-dss host | \ - awk '/^pubkeyacceptedalgorithms /{print $2}'` - expect_result_present "$f" "ssh-ed25519" "ssh-ed25519-cert-v01.*" "ssh-dss" - expect_result_absent "$f" "ssh-dss-cert-v01.*" -fi - verbose "agentforwarding" -f=`${SSH} -GF none host | awk '/^forwardagent /{print$2}'` +f=`${SSH} -dF none host | awk '/^forwardagent /{print$2}'` expect_result_present "$f" "no" -f=`${SSH} -GF none -oforwardagent=no host | awk '/^forwardagent /{print$2}'` +f=`${SSH} -dF none -oforwardagent=no host | awk '/^forwardagent /{print$2}'` expect_result_present "$f" "no" -f=`${SSH} -GF none -oforwardagent=yes host | awk '/^forwardagent /{print$2}'` +f=`${SSH} -dF none -oforwardagent=yes host | awk '/^forwardagent /{print$2}'` expect_result_present "$f" "yes" -f=`${SSH} -GF none '-oforwardagent=SSH_AUTH_SOCK.forward' host | awk '/^forwardagent /{print$2}'` +f=`${SSH} -dF none '-oforwardagent=SSH_AUTH_SOCK.forward' host | awk '/^forwardagent /{print$2}'` expect_result_present "$f" "SSH_AUTH_SOCK.forward" verbose "command line override" @@ -110,9 +62,9 @@ IPQoS af21 cs1 TunnelDevice 1:2 EOD -f=`${SSH} -GF $OBJ/ssh_config.0 -oipqos=cs1 host | awk '/^ipqos /{print$2}'` +f=`${SSH} -dF $OBJ/ssh_config.0 -oipqos=cs1 host | awk '/^ipqos /{print$2}'` expect_result_present "$f" "cs1" -f=`${SSH} -GF $OBJ/ssh_config.0 -otunneldevice=3:4 host | awk '/^tunneldevice /{print$2}'` +f=`${SSH} -dF $OBJ/ssh_config.0 -otunneldevice=3:4 host | awk '/^tunneldevice /{print$2}'` expect_result_present "$f" "3:4" # cleanup diff -ruN openssh-9.4p1/regress/sshd-log-wrapper.sh openssh-9.4p1+x509-14.2.1/regress/sshd-log-wrapper.sh --- openssh-9.4p1/regress/sshd-log-wrapper.sh 1970-01-01 02:00:00.000000000 +0200 +++ openssh-9.4p1+x509-14.2.1/regress/sshd-log-wrapper.sh 2023-08-20 10:07:00.000000000 +0300 @@ -0,0 +1,12 @@ +#!/bin/sh +# $OpenBSD: sshd-log-wrapper.sh,v 1.5 2022/01/04 08:38:53 dtucker Exp $ +# Placed in the Public Domain. +# +# simple wrapper for sshd proxy mode to catch stderr output +# sh sshd-log-wrapper.sh /path/to/logfile /path/to/sshd [args...] + +log=$1 +shift + +echo Executing: ${1+"$@"} >>$log +exec ${1+"$@"} -E$log diff -ruN openssh-9.4p1/regress/sshfp-connect.sh openssh-9.4p1+x509-14.2.1/regress/sshfp-connect.sh --- openssh-9.4p1/regress/sshfp-connect.sh 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/sshfp-connect.sh 1970-01-01 02:00:00.000000000 +0200 @@ -1,66 +0,0 @@ -# $OpenBSD: sshfp-connect.sh,v 1.4 2021/09/01 00:50:27 dtucker Exp $ -# Placed in the Public Domain. - -# This test requires external setup and thus is skipped unless -# TEST_SSH_SSHFP_DOMAIN is set. It requires: -# 1) A DNSSEC-enabled domain, which TEST_SSH_SSHFP_DOMAIN points to. -# 2) A DNSSEC-validating resolver such as unwind(8). -# 3) The following SSHFP records with fingerprints from rsa_openssh.pub -# in that domain that are expected to succeed: -# sshtest: valid sha1 and sha256 fingerprints. -# sshtest-sha{1,256}, : valid fingerprints for that type only. -# and the following records that are expected to fail: -# sshtest-bad: invalid sha1 fingerprint and good sha256 fingerprint -# sshtest-sha{1,256}-bad: invalid fingerprints for that type only. -# -# sshtest IN SSHFP 1 1 99C79CC09F5F81069CC017CDF9552CFC94B3B929 -# sshtest IN SSHFP 1 2 E30D6B9EB7A4DE495324E4D5870B8220577993EA6AF417E8E4A4F1C5 BF01A9B6 -# sshtest-sha1 IN SSHFP 1 1 99C79CC09F5F81069CC017CDF9552CFC94B3B929 -# sshtest-sha256 IN SSHFP 1 2 E30D6B9EB7A4DE495324E4D5870B8220577993EA6AF417E8E4A4F1C5 BF01A9B6 -# sshtest-bad IN SSHFP 1 2 E30D6B9EB7A4DE495324E4D5870B8220577993EA6AF417E8E4A4F1C5 BF01A9B6 -# sshtest-bad IN SSHFP 1 1 99C79CC09F5F81069CC017CDF9552CFC94B3B928 -# sshtest-sha1-bad IN SSHFP 1 1 99D79CC09F5F81069CC017CDF9552CFC94B3B929 -# sshtest-sha256-bad IN SSHFP 1 2 E30D6B9EB7A4DE495324E4D5870B8220577993EA6AF417E8E4A4F1C5 BF01A9B5 - -tid="sshfp connect" - -if ! $SSH -Q key-plain | grep ssh-rsa >/dev/null; then - skip "RSA keys not supported." -elif [ -z "${TEST_SSH_SSHFP_DOMAIN}" ]; then - skip "TEST_SSH_SSHFP_DOMAIN not set." -else - # Set RSA host key to match fingerprints above. - mv $OBJ/sshd_proxy $OBJ/sshd_proxy.orig - $SUDO cp $SRC/rsa_openssh.prv $OBJ/host.ssh-rsa - $SUDO chmod 600 $OBJ/host.ssh-rsa - sed -e "s|$OBJ/ssh-rsa|$OBJ/host.ssh-rsa|" \ - $OBJ/sshd_proxy.orig > $OBJ/sshd_proxy - - # Zero out known hosts and key aliases to force use of SSHFP records. - > $OBJ/known_hosts - mv $OBJ/ssh_proxy $OBJ/ssh_proxy.orig - sed -e "/HostKeyAlias.*localhost-with-alias/d" \ - -e "/Hostname.*127.0.0.1/d" \ - $OBJ/ssh_proxy.orig > $OBJ/ssh_proxy - - for n in sshtest sshtest-sha1 sshtest-sha256; do - trace "sshfp connect $n good fingerprint" - host="${n}.dtucker.net" - opts="-F $OBJ/ssh_proxy -o VerifyHostKeyDNS=yes " - opts="$opts -o HostKeyAlgorithms=rsa-sha2-512,rsa-sha2-256" - host="${n}.${TEST_SSH_SSHFP_DOMAIN}" - SSH_CONNECTION=`${SSH} $opts $host 'echo $SSH_CONNECTION'` - if [ $? -ne 0 ]; then - fail "ssh sshfp connect failed" - fi - if [ "$SSH_CONNECTION" != "UNKNOWN 65535 UNKNOWN 65535" ]; then - fail "bad SSH_CONNECTION: $SSH_CONNECTION" - fi - - trace "sshfp connect $n bad fingerprint" - host="${n}-bad.${TEST_SSH_SSHFP_DOMAIN}" - if ${SSH} $opts ${host} true; then - fail "sshfp-connect succeeded with bad SSHFP record" - fi - done -fi diff -ruN openssh-9.4p1/regress/sshsig.sh openssh-9.4p1+x509-14.2.1/regress/sshsig.sh --- openssh-9.4p1/regress/sshsig.sh 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/sshsig.sh 1970-01-01 02:00:00.000000000 +0200 @@ -1,476 +0,0 @@ -# $OpenBSD: sshsig.sh,v 1.14 2022/02/01 23:37:15 djm Exp $ -# Placed in the Public Domain. - -tid="sshsig" - -DATA2=$OBJ/${DATANAME}.2 -cat ${DATA} ${DATA} > ${DATA2} - -rm -f $OBJ/sshsig-*.sig $OBJ/wrong-key* $OBJ/sigca-key* - -sig_namespace="test-$$" -sig_principal="user-$$@example.com" - -# Make a "wrong key" -${SSHKEYGEN} -q -t ed25519 -f $OBJ/wrong-key \ - -C "wrong trousers, Grommit" -N '' \ - || fatal "couldn't generate key" -WRONG=$OBJ/wrong-key.pub - -# Make a CA key. -${SSHKEYGEN} -q -t ed25519 -f $OBJ/sigca-key -C "CA" -N '' \ - || fatal "couldn't generate key" -CA_PRIV=$OBJ/sigca-key -CA_PUB=$OBJ/sigca-key.pub - -trace "start agent" -eval `${SSHAGENT} ${EXTRA_AGENT_ARGS} -s` > /dev/null -r=$? -if [ $r -ne 0 ]; then - fatal "could not start ssh-agent: exit code $r" -fi - -SIGNKEYS="$SSH_KEYTYPES" -verbose "$tid: make certificates" -for t in $SSH_KEYTYPES ; do - ${SSHKEYGEN} -q -s $CA_PRIV -z $$ \ - -I "regress signature key for $USER" \ - -V "19840101:19860101" \ - -n $sig_principal $OBJ/${t} || \ - fatal "couldn't sign ${t}" - SIGNKEYS="$SIGNKEYS ${t}-cert.pub" -done - -for t in $SIGNKEYS; do - verbose "$tid: check signature for $t" - keybase=`basename $t .pub` - privkey=${OBJ}/`basename $t -cert.pub` - sigfile=${OBJ}/sshsig-${keybase}.sig - sigfile_agent=${OBJ}/sshsig-agent-${keybase}.sig - pubkey=${OBJ}/${keybase}.pub - cert=${OBJ}/${keybase}-cert.pub - sigfile_cert=${OBJ}/sshsig-${keybase}-cert.sig - - ${SSHKEYGEN} -vvv -Y sign -f ${OBJ}/$t -n $sig_namespace \ - -Ohashalg=sha1 < $DATA > $sigfile 2>/dev/null && \ - fail "sign using $t with bad hash algorithm succeeded" - - for h in default sha256 sha512 ; do - case "$h" in - default) hashalg_arg="" ;; - *) hashalg_arg="-Ohashalg=$h" ;; - esac - ${SSHKEYGEN} -vvv -Y sign -f ${OBJ}/$t -n $sig_namespace \ - $hashalg_arg < $DATA > $sigfile 2>/dev/null || \ - fail "sign using $t / $h failed" - (printf "$sig_principal " ; cat $pubkey) > $OBJ/allowed_signers - ${SSHKEYGEN} -vvv -Y verify -s $sigfile -n $sig_namespace \ - -I $sig_principal -f $OBJ/allowed_signers \ - < $DATA >/dev/null 2>&1 || \ - fail "failed signature for $t / $h key" - done - - (printf "$sig_principal namespaces=\"$sig_namespace,whatever\" "; - cat $pubkey) > $OBJ/allowed_signers - ${SSHKEYGEN} -vvv -Y verify -s $sigfile -n $sig_namespace \ - -I $sig_principal -f $OBJ/allowed_signers \ - < $DATA >/dev/null 2>&1 || \ - fail "failed signature for $t key w/ limited namespace" - - (printf "$sig_principal namespaces=\"$sig_namespace,whatever\" "; - cat $pubkey) > $OBJ/allowed_signers - ${SSHKEYGEN} -q -Y verify -s $sigfile -n $sig_namespace \ - -I $sig_principal -f $OBJ/allowed_signers \ - -O print-pubkey \ - < $DATA | cut -d' ' -f1-2 > ${OBJ}/${keybase}-fromsig.pub || \ - fail "failed signature for $t key w/ print-pubkey" - cut -d' ' -f1-2 ${OBJ}/${keybase}.pub > ${OBJ}/${keybase}-strip.pub - diff -r ${OBJ}/${keybase}-strip.pub ${OBJ}/${keybase}-fromsig.pub || \ - fail "print-pubkey differs from signature key" - - # Invalid option - (printf "$sig_principal octopus " ; cat $pubkey) > $OBJ/allowed_signers - ${SSHKEYGEN} -vvv -Y verify -s $sigfile -n $sig_namespace \ - -I $sig_principal -f $OBJ/allowed_signers \ - < $DATA >/dev/null 2>&1 && \ - fail "accepted signature for $t key with bad signers option" - - # Wrong key trusted. - (printf "$sig_principal " ; cat $WRONG) > $OBJ/allowed_signers - ${SSHKEYGEN} -vvv -Y verify -s $sigfile -n $sig_namespace \ - -I $sig_principal -f $OBJ/allowed_signers \ - < $DATA >/dev/null 2>&1 && \ - fail "accepted signature for $t key with wrong key trusted" - - # incorrect data - (printf "$sig_principal " ; cat $pubkey) > $OBJ/allowed_signers - ${SSHKEYGEN} -vvv -Y verify -s $sigfile -n $sig_namespace \ - -I $sig_principal -f $OBJ/allowed_signers \ - < $DATA2 >/dev/null 2>&1 && \ - fail "passed signature for wrong data with $t key" - - # wrong principal in signers - (printf "josef.k@example.com " ; cat $pubkey) > $OBJ/allowed_signers - ${SSHKEYGEN} -vvv -Y verify -s $sigfile -n $sig_namespace \ - -I $sig_principal -f $OBJ/allowed_signers \ - < $DATA >/dev/null 2>&1 && \ - fail "accepted signature for $t key with wrong principal" - - # wrong namespace - (printf "$sig_principal " ; cat $pubkey) > $OBJ/allowed_signers - ${SSHKEYGEN} -vvv -Y verify -s $sigfile -n COWS_COWS_COWS \ - -I $sig_principal -f $OBJ/allowed_signers \ - < $DATA >/dev/null 2>&1 && \ - fail "accepted signature for $t key with wrong namespace" - - # namespace excluded by option - (printf "$sig_principal namespaces=\"whatever\" " ; - cat $pubkey) > $OBJ/allowed_signers - ${SSHKEYGEN} -vvv -Y verify -s $sigfile -n $sig_namespace \ - -I $sig_principal -f $OBJ/allowed_signers \ - < $DATA >/dev/null 2>&1 && \ - fail "accepted signature for $t key with excluded namespace" - - ( printf "$sig_principal " ; - printf "valid-after=\"19800101\",valid-before=\"19900101\" " ; - cat $pubkey) > $OBJ/allowed_signers - - # key lifespan valid - ${SSHKEYGEN} -vvv -Y verify -s $sigfile -n $sig_namespace \ - -I $sig_principal -f $OBJ/allowed_signers \ - -Overify-time=19850101 \ - < $DATA >/dev/null 2>&1 || \ - fail "failed signature for $t key with valid expiry interval" - # key not yet valid - ${SSHKEYGEN} -vvv -Y verify -s $sigfile -n $sig_namespace \ - -I $sig_principal -f $OBJ/allowed_signers \ - -Overify-time=19790101 \ - < $DATA >/dev/null 2>&1 && \ - fail "failed signature for $t not-yet-valid key" - # key expired - ${SSHKEYGEN} -vvv -Y verify -s $sigfile -n $sig_namespace \ - -I $sig_principal -f $OBJ/allowed_signers \ - -Overify-time=19910101 \ - < $DATA >/dev/null 2>&1 && \ - fail "failed signature for $t with expired key" - # NB. assumes we're not running this test in the 1980s - ${SSHKEYGEN} -vvv -Y verify -s $sigfile -n $sig_namespace \ - -I $sig_principal -f $OBJ/allowed_signers \ - < $DATA >/dev/null 2>&1 && \ - fail "failed signature for $t with expired key" - - # key lifespan valid - ${SSHKEYGEN} -vvv -Y find-principals -s $sigfile \ - -Overify-time="19850101" \ - -f $OBJ/allowed_signers >/dev/null 2>&1 || \ - fail "failed find-principals for $t key with valid expiry interval" - # key not yet valid - ${SSHKEYGEN} -vvv -Y find-principals -s $sigfile \ - -Overify-time="19790101" \ - -f $OBJ/allowed_signers >/dev/null 2>&1 && \ - fail "failed find-principals for $t not-yet-valid key" - # key expired - ${SSHKEYGEN} -vvv -Y find-principals -s $sigfile \ - -Overify-time="19990101" \ - -f $OBJ/allowed_signers >/dev/null 2>&1 && \ - fail "failed find-principals for $t with expired key" - # NB. assumes we're not running this test in the 1980s - ${SSHKEYGEN} -vvv -Y find-principals -s $sigfile \ - -f $OBJ/allowed_signers >/dev/null 2>&1 && \ - fail "failed find-principals for $t with expired key" - - # public key in revoked keys file - cat $pubkey > $OBJ/revoked_keys - (printf "$sig_principal namespaces=\"whatever\" " ; - cat $pubkey) > $OBJ/allowed_signers - ${SSHKEYGEN} -vvv -Y verify -s $sigfile -n $sig_namespace \ - -I $sig_principal -f $OBJ/allowed_signers \ - -r $OBJ/revoked_keys \ - < $DATA >/dev/null 2>&1 && \ - fail "accepted signature for $t key, but key is in revoked_keys" - - # public key not revoked, but others are present in revoked_keysfile - cat $WRONG > $OBJ/revoked_keys - (printf "$sig_principal " ; cat $pubkey) > $OBJ/allowed_signers - ${SSHKEYGEN} -vvv -Y verify -s $sigfile -n $sig_namespace \ - -I $sig_principal -f $OBJ/allowed_signers \ - -r $OBJ/revoked_keys \ - < $DATA >/dev/null 2>&1 || \ - fail "couldn't verify signature for $t key, but key not in revoked_keys" - - # check-novalidate with valid data - ${SSHKEYGEN} -vvv -Y check-novalidate -s $sigfile -n $sig_namespace \ - < $DATA >/dev/null 2>&1 || \ - fail "failed to check valid signature for $t key" - - # check-novalidate with invalid data - ${SSHKEYGEN} -vvv -Y check-novalidate -s $sigfile -n $sig_namespace \ - < $DATA2 >/dev/null 2>&1 && \ - fail "succeeded checking signature for $t key with invalid data" - - # find-principals with valid public key - (printf "$sig_principal " ; cat $pubkey) > $OBJ/allowed_signers - ${SSHKEYGEN} -vvv -Y find-principals -s $sigfile -f $OBJ/allowed_signers >/dev/null 2>&1 || \ - fail "failed to find valid principals in allowed_signers" - - # find-principals with wrong key not in allowed_signers - (printf "$sig_principal " ; cat $WRONG) > $OBJ/allowed_signers - ${SSHKEYGEN} -vvv -Y find-principals -s $sigfile -f $OBJ/allowed_signers >/dev/null 2>&1 && \ - fail "succeeded finding principal with invalid signers file" - - # find-principals with a configured namespace but none on command-line - (printf "$sig_principal " ; - printf "namespaces=\"test1,test2\" "; - cat $pubkey) > $OBJ/allowed_signers - ${SSHKEYGEN} -vvv -Y find-principals -s $sigfile \ - -f $OBJ/allowed_signers >/dev/null 2>&1 || \ - fail "failed finding principal when namespaces are configured" - - # Check signing keys using ssh-agent. - ${SSHADD} -D >/dev/null 2>&1 # Remove all previously-loaded keys. - ${SSHADD} ${privkey} > /dev/null 2>&1 || fail "ssh-add failed" - - # Move private key to ensure agent key is used - mv ${privkey} ${privkey}.tmp - - ${SSHKEYGEN} -vvv -Y sign -f $pubkey -n $sig_namespace \ - < $DATA > $sigfile_agent 2>/dev/null || \ - fail "ssh-agent based sign using $pubkey failed" - ${SSHKEYGEN} -vvv -Y check-novalidate -s $sigfile_agent \ - -n $sig_namespace < $DATA >/dev/null 2>&1 || \ - fail "failed to check valid signature for $t key" - - # Move private key back - mv ${privkey}.tmp ${privkey} - - # Duplicate principals & keys in allowed_signers but with different validities - ( printf "$sig_principal " ; - printf "valid-after=\"19800101\",valid-before=\"19900101\" " ; - cat $pubkey; - printf "${sig_principal} " ; - printf "valid-after=\"19850101\",valid-before=\"20000101\" " ; - cat $pubkey) > $OBJ/allowed_signers - - # find-principals outside of any validity lifespan - ${SSHKEYGEN} -vvv -Y find-principals -s $sigfile \ - -Overify-time="20100101" \ - -f $OBJ/allowed_signers >/dev/null 2>&1 && \ - fail "succeeded find-principals for $t verify-time outside of validity" - # find-principals matching only the first lifespan - ${SSHKEYGEN} -vvv -Y find-principals -s $sigfile \ - -Overify-time="19830101" \ - -f $OBJ/allowed_signers >/dev/null 2>&1 || \ - fail "failed find-principals for $t verify-time within first span" - # find-principals matching both lifespans - ${SSHKEYGEN} -vvv -Y find-principals -s $sigfile \ - -Overify-time="19880101" \ - -f $OBJ/allowed_signers >/dev/null 2>&1 || \ - fail "failed find-principals for $t verify-time within both spans" - # find-principals matching only the second lifespan - ${SSHKEYGEN} -vvv -Y find-principals -s $sigfile \ - -Overify-time="19950101" \ - -f $OBJ/allowed_signers >/dev/null 2>&1 || \ - fail "failed find-principals for $t verify-time within second span" - - # verify outside of any validity lifespan - ${SSHKEYGEN} -vvv -Y verify -s $sigfile -n $sig_namespace \ - -Overify-time="20100101" -I $sig_principal \ - -r $OBJ/revoked_keys -f $OBJ/allowed_signers \ - < $DATA >/dev/null 2>&1 && \ - fail "succeeded verify for $t verify-time outside of validity" - # verify matching only the first lifespan - ${SSHKEYGEN} -vvv -Y verify -s $sigfile -n $sig_namespace \ - -Overify-time="19830101" -I $sig_principal \ - -r $OBJ/revoked_keys -f $OBJ/allowed_signers \ - < $DATA >/dev/null 2>&1 || \ - fail "failed verify for $t verify-time within first span" - # verify matching both lifespans - ${SSHKEYGEN} -vvv -Y verify -s $sigfile -n $sig_namespace \ - -Overify-time="19880101" -I $sig_principal \ - -r $OBJ/revoked_keys -f $OBJ/allowed_signers \ - < $DATA >/dev/null 2>&1 || \ - fail "failed verify for $t verify-time within both spans" - # verify matching only the second lifespan - ${SSHKEYGEN} -vvv -Y verify -s $sigfile -n $sig_namespace \ - -Overify-time="19950101" -I $sig_principal \ - -r $OBJ/revoked_keys -f $OBJ/allowed_signers \ - < $DATA >/dev/null 2>&1 || \ - fail "failed verify for $t verify-time within second span" - - # Remaining tests are for certificates only. - case "$keybase" in - *-cert) ;; - *) continue ;; - esac - - # Check key lifespan on find-principals when using the CA - ( printf "$sig_principal " ; - printf "cert-authority,valid-after=\"19800101\",valid-before=\"19900101\" "; - cat $CA_PUB) > $OBJ/allowed_signers - # key lifespan valid - ${SSHKEYGEN} -vvv -Y find-principals -s $sigfile \ - -Overify-time="19850101" \ - -f $OBJ/allowed_signers >/dev/null 2>&1 || \ - fail "failed find-principals for $t key with valid expiry interval" - # key not yet valid - ${SSHKEYGEN} -vvv -Y find-principals -s $sigfile \ - -Overify-time="19790101" \ - -f $OBJ/allowed_signers >/dev/null 2>&1 && \ - fail "failed find-principals for $t not-yet-valid key" - # key expired - ${SSHKEYGEN} -vvv -Y find-principals -s $sigfile \ - -Overify-time="19990101" \ - -f $OBJ/allowed_signers >/dev/null 2>&1 && \ - fail "failed find-principals for $t with expired key" - # NB. assumes we're not running this test in the 1980s - ${SSHKEYGEN} -vvv -Y find-principals -s $sigfile \ - -f $OBJ/allowed_signers >/dev/null 2>&1 && \ - fail "failed find-principals for $t with expired key" - - # correct CA key - (printf "$sig_principal cert-authority " ; - cat $CA_PUB) > $OBJ/allowed_signers - ${SSHKEYGEN} -vvv -Y verify -s $sigfile -n $sig_namespace \ - -I $sig_principal -f $OBJ/allowed_signers \ - -Overify-time=19850101 \ - < $DATA >/dev/null 2>&1 || \ - fail "failed signature for $t cert" - - # find-principals - ${SSHKEYGEN} -vvv -Y find-principals -s $sigfile \ - -Overify-time=19850101 \ - -f $OBJ/allowed_signers >/dev/null 2>&1 || \ - fail "failed find-principals for $t with ca key" - - # CA with wildcard principal - (printf "*@example.com cert-authority " ; - cat $CA_PUB) > $OBJ/allowed_signers - # find-principals CA with wildcard principal - ${SSHKEYGEN} -vvv -Y find-principals -s $sigfile \ - -Overify-time=19850101 \ - -f $OBJ/allowed_signers 2>/dev/null | \ - fgrep "$sig_principal" >/dev/null || \ - fail "failed find-principals for $t with ca key using wildcard principal" - - # verify CA with wildcard principal - ${SSHKEYGEN} -vvv -Y verify -s $sigfile -n $sig_namespace \ - -I $sig_principal -f $OBJ/allowed_signers \ - -Overify-time=19850101 \ - < $DATA >/dev/null 2>&1 || \ - fail "failed signature for $t cert using wildcard principal" - - # signing key listed as cert-authority - (printf "$sig_principal cert-authority " ; - cat $pubkey) > $OBJ/allowed_signers - ${SSHKEYGEN} -vvv -Y verify -s $sigfile -n $sig_namespace \ - -I $sig_principal -f $OBJ/allowed_signers \ - < $DATA >/dev/null 2>&1 && \ - fail "accepted signature with $t key listed as CA" - - # CA key not flagged cert-authority - (printf "$sig_principal " ; cat $CA_PUB) > $OBJ/allowed_signers - ${SSHKEYGEN} -vvv -Y verify -s $sigfile -n $sig_namespace \ - -I $sig_principal -f $OBJ/allowed_signers \ - < $DATA >/dev/null 2>&1 && \ - fail "accepted signature for $t cert with CA not marked" - - # mismatch between cert principal and file - (printf "josef.k@example.com cert-authority " ; - cat $CA_PUB) > $OBJ/allowed_signers - ${SSHKEYGEN} -vvv -Y verify -s $sigfile -n $sig_namespace \ - -I $sig_principal -f $OBJ/allowed_signers \ - < $DATA >/dev/null 2>&1 && \ - fail "accepted signature for $t cert with wrong principal" - - # Cert valid but CA revoked - cat $CA_PUB > $OBJ/revoked_keys - (printf "$sig_principal " ; cat $pubkey) > $OBJ/allowed_signers - ${SSHKEYGEN} -vvv -Y verify -s $sigfile -n $sig_namespace \ - -I $sig_principal -f $OBJ/allowed_signers \ - -r $OBJ/revoked_keys \ - < $DATA >/dev/null 2>&1 && \ - fail "accepted signature for $t key, but CA key in revoked_keys" - - # Set lifespan of CA key and verify signed user certs behave accordingly - ( printf "$sig_principal " ; - printf "cert-authority,valid-after=\"19800101\",valid-before=\"19900101\" " ; - cat $CA_PUB) > $OBJ/allowed_signers - - # CA key lifespan valid - ${SSHKEYGEN} -vvv -Y verify -s $sigfile -n $sig_namespace \ - -I $sig_principal -f $OBJ/allowed_signers \ - -Overify-time=19850101 \ - < $DATA >/dev/null 2>&1 >/dev/null 2>&1 || \ - fail "failed signature for $t key with valid CA expiry interval" - # CA lifespan is valid but user key not yet valid - ${SSHKEYGEN} -vvv -Y verify -s $sigfile -n $sig_namespace \ - -I $sig_principal -f $OBJ/allowed_signers \ - -Overify-time=19810101 \ - < $DATA >/dev/null 2>&1 && \ - fail "accepted signature for $t key with valid CA expiry interval but not yet valid cert" - # CA lifespan is valid but user key expired - ${SSHKEYGEN} -vvv -Y verify -s $sigfile -n $sig_namespace \ - -I $sig_principal -f $OBJ/allowed_signers \ - -Overify-time=19890101 \ - < $DATA >/dev/null 2>&1 && \ - fail "accepted signature for $t key with valid CA expiry interval but expired cert" - # CA key not yet valid - ${SSHKEYGEN} -vvv -Y verify -s $sigfile -n $sig_namespace \ - -I $sig_principal -f $OBJ/allowed_signers \ - -Overify-time=19790101 \ - < $DATA >/dev/null 2>&1 && \ - fail "accepted signature for $t not-yet-valid CA key" - # CA key expired - ${SSHKEYGEN} -vvv -Y verify -s $sigfile -n $sig_namespace \ - -I $sig_principal -f $OBJ/allowed_signers \ - -Overify-time=19910101 \ - < $DATA >/dev/null 2>&1 && \ - fail "accepted signature for $t with expired CA key" - # NB. assumes we're not running this test in the 1980s - ${SSHKEYGEN} -vvv -Y verify -s $sigfile -n $sig_namespace \ - -I $sig_principal -f $OBJ/allowed_signers \ - < $DATA >/dev/null 2>&1 && \ - fail "accepted signature for $t with expired CA key" - - # Set lifespan of CA outside of the cert validity - ( printf "$sig_principal " ; - printf "cert-authority,valid-after=\"19800101\",valid-before=\"19820101\" " ; - cat $CA_PUB) > $OBJ/allowed_signers - # valid cert validity but expired CA - ${SSHKEYGEN} -vvv -Y verify -s $sigfile -n $sig_namespace \ - -I $sig_principal -f $OBJ/allowed_signers \ - -Overify-time=19840101 \ - < $DATA >/dev/null 2>&1 && \ - fail "accepted signature for $t key with expired CA but valid cert" - -done - -# Test key independant match-principals -( - printf "principal1 " ; cat $pubkey; - printf "princi* " ; cat $pubkey; - printf "unique " ; cat $pubkey; -) > $OBJ/allowed_signers - -verbose "$tid: match principals" -${SSHKEYGEN} -Y match-principals -f $OBJ/allowed_signers -I "unique" | \ - fgrep "unique" >/dev/null || \ - fail "faild to match static principal" - -${SSHKEYGEN} -Y match-principals -f $OBJ/allowed_signers -I "princip" | \ - fgrep "princi*" >/dev/null || \ - fail "faild to match wildcard principal" - -${SSHKEYGEN} -Y match-principals -f $OBJ/allowed_signers -I "principal1" | \ - fgrep -e "principal1" -e "princi*" >/dev/null || \ - fail "faild to match static and wildcard principal" -verbose "$tid: nomatch principals" -for x in princ prince unknown ; do - ${SSHKEYGEN} -Y match-principals -f $OBJ/allowed_signers \ - -I $x >/dev/null 2>&1 && \ - fail "succeeded to match unknown principal \"$x\"" -done - -trace "kill agent" -${SSHAGENT} -k > /dev/null - diff -ruN openssh-9.4p1/regress/test-env.sh openssh-9.4p1+x509-14.2.1/regress/test-env.sh --- openssh-9.4p1/regress/test-env.sh 1970-01-01 02:00:00.000000000 +0200 +++ openssh-9.4p1+x509-14.2.1/regress/test-env.sh 2023-08-20 10:07:00.000000000 +0300 @@ -0,0 +1,23 @@ +#! /bin/sh +# Placed in the Public Domain. + +cat >&2 </dev/null` +PUTTYGEN=`which $PUTTYGEN 2>/dev/null` +CONCH=`which $CONCH 2>/dev/null` # Tools used by multiple tests NC=$OBJ/netcat -# Always use the one configure tells us to, even if that's empty. -#OPENSSL_BIN="${OPENSSL_BIN:-openssl}" +OPENSSL=${OPENSSL-openssl} +OPENSSL=`which $OPENSSL 2>/dev/null` +test -n "$OPENSSL" && export OPENSSL if [ "x$TEST_SSH_SSH" != "x" ]; then SSH="${TEST_SSH_SSH}" @@ -132,35 +150,8 @@ if [ "x$TEST_SSH_SCP" != "x" ]; then SCP="${TEST_SSH_SCP}" fi -if [ "x$TEST_SSH_PLINK" != "x" ]; then - # Find real binary, if it exists - case "${TEST_SSH_PLINK}" in - /*) PLINK="${TEST_SSH_PLINK}" ;; - *) PLINK=`which ${TEST_SSH_PLINK} 2>/dev/null` ;; - esac -fi -if [ "x$TEST_SSH_PUTTYGEN" != "x" ]; then - # Find real binary, if it exists - case "${TEST_SSH_PUTTYGEN}" in - /*) PUTTYGEN="${TEST_SSH_PUTTYGEN}" ;; - *) PUTTYGEN=`which ${TEST_SSH_PUTTYGEN} 2>/dev/null` ;; - esac -fi -if [ "x$TEST_SSH_CONCH" != "x" ]; then - # Find real binary, if it exists - case "${TEST_SSH_CONCH}" in - /*) CONCH="${TEST_SSH_CONCH}" ;; - *) CONCH=`which ${TEST_SSH_CONCH} 2>/dev/null` ;; - esac -fi -if [ "x$TEST_SSH_PKCS11_HELPER" != "x" ]; then - SSH_PKCS11_HELPER="${TEST_SSH_PKCS11_HELPER}" -fi -if [ "x$TEST_SSH_SK_HELPER" != "x" ]; then - SSH_SK_HELPER="${TEST_SSH_SK_HELPER}" -fi -if [ "x$TEST_SSH_OPENSSL" != "x" ]; then - OPENSSL_BIN="${TEST_SSH_OPENSSL}" +if [ "x$TEST_SSH_SSHPKCS11HELPER" != "x" ]; then + SSH_PKCS11_HELPER="${TEST_SSH_SSHPKCS11HELPER}" fi # Path to sshd must be absolute for rexec @@ -189,7 +180,7 @@ rm -rf $OBJ/valgrind-out $OBJ/valgrind-vgdb mkdir -p $OBJ/valgrind-out $OBJ/valgrind-vgdb # When using sudo ensure low-priv tests can write pipes and logs. - if [ "x$SUDO" != "x" ]; then + if test -n "$SUDO" ; then chmod 777 $OBJ/valgrind-out $OBJ/valgrind-vgdb fi VG_TEST=`basename $SCRIPT .sh` @@ -199,7 +190,7 @@ reexec) VG_SKIP=1 ;; sftp-chroot) - if [ "x${SUDO}" != "x" ]; then + if test -n "$SUDO" ; then VG_SKIP=1 fi ;; esac @@ -229,8 +220,8 @@ SFTP="$VG --log-file=${VG_LOG}sftp.%p ${SFTP}" SCP="$VG --log-file=${VG_LOG}scp.%p $SCP" cat > $OBJ/valgrind-sftp-server.sh << EOF -#!/bin/sh -exec $VG --log-file=${VG_LOG}sftp-server.%p $SFTPSERVER "\$@" +#! $TEST_SHELL +exec $VG --log-file=${VG_LOG}sftp-server.%p $SFTPSERVER \${1+"\$@"} EOF chmod a+rx $OBJ/valgrind-sftp-server.sh SFTPSERVER="$OBJ/valgrind-sftp-server.sh" @@ -240,13 +231,7 @@ # Logfiles. # SSH_LOGFILE should be the debug output of ssh(1) only # SSHD_LOGFILE should be the debug output of sshd(8) only -# REGRESS_LOGFILE is the log of progress of the regress test itself. -# TEST_SSH_LOGDIR will contain datestamped logs of all binaries run in -# chronological order. -if [ "x$TEST_SSH_LOGDIR" = "x" ]; then - TEST_SSH_LOGDIR=$OBJ/log - mkdir -p $TEST_SSH_LOGDIR -fi +# REGRESS_LOGFILE is the output of the test itself stdout and stderr if [ "x$TEST_SSH_LOGFILE" = "x" ]; then TEST_SSH_LOGFILE=$OBJ/ssh.log fi @@ -259,79 +244,60 @@ # If set, keep track of successful tests and skip them them if we've # previously completed that test. -if [ "x$TEST_REGRESS_CACHE_DIR" != "x" ]; then - if [ ! -d "$TEST_REGRESS_CACHE_DIR" ]; then - mkdir -p "$TEST_REGRESS_CACHE_DIR" - fi - TEST="`basename $SCRIPT .sh`" - CACHE="${TEST_REGRESS_CACHE_DIR}/${TEST}.cache" +if test "x$TEST_REGRESS_CACHE_DIR" != "x" ; then + $SRC/../install-sh -d "$TEST_REGRESS_CACHE_DIR" + TEST="${SCRIPT##*/}" + TEST="${TEST%.sh}" + CACHE="$TEST_REGRESS_CACHE_DIR/$TEST.pass" for i in ${SSH} ${SSHD} ${SSHAGENT} ${SSHADD} ${SSHKEYGEN} ${SCP} \ ${SFTP} ${SFTPSERVER} ${SSHKEYSCAN}; do - case $i in - /*) bin="$i" ;; - *) bin="`which $i`" ;; - esac - if [ "$bin" -nt "$CACHE" ]; then + bin="`which $i`" + if test "$bin" -nt "$CACHE" ; then rm -f "$CACHE" fi done - if [ -f "$CACHE" ]; then - echo ok cached $CACHE + if test -f "$CACHE" ; then + echo "ok $TEST (cached) - $CACHE" >&2 exit 0 fi fi # truncate logfiles +echo "=== $SCRIPT ..." > $TEST_SSH_LOGFILE +>$TEST_SSHD_LOGFILE >$TEST_REGRESS_LOGFILE -# Create ssh and sshd wrappers with logging. These create a datestamped -# unique file for every invocation so that we can retain all logs from a -# given test no matter how many times it's invoked. It also leaves a -# symlink with the original name for tests (and people) who look for that. - -# For ssh, e can't just specify "SSH=ssh -E..." because sftp and scp don't -# handle spaces in arguments. scp and sftp like to use -q so we remove those -# to preserve our debug logging. In the rare instance where -q is desirable -# -qq is equivalent and is not removed. +# Create wrapper ssh with logging. We can not just specify "SSH=ssh -E..." +# because sftp and scp do not handle spaces in arguments. +# Some tests use -q so wrapper remove argument to preserve debug logging. +# In the rare instance where -q is desirable -qq is equivalent and is not +# removed. SSHLOGWRAP=$OBJ/ssh-log-wrapper.sh -cat >$SSHLOGWRAP <>$TEST_REGRESS_LOGFILE -echo "Executing: ${SSH} \$@" >>\${logfile} -for i in "\$@";do shift;case "\$i" in -q):;; *) set -- "\$@" "\$i";;esac;done -rm -f $TEST_SSH_LOGFILE -ln -f -s \${logfile} $TEST_SSH_LOGFILE -exec ${SSH} -E\${logfile} "\$@" -EOD +cat > $SSHLOGWRAP <>$TEST_SSH_LOGFILE +exec $SSH -E$TEST_SSH_LOGFILE \${1+"\$@"} +EOF chmod a+rx $OBJ/ssh-log-wrapper.sh + REAL_SSH="$SSH" REAL_SSHD="$SSHD" SSH="$SSHLOGWRAP" -SSHDLOGWRAP=$OBJ/sshd-log-wrapper.sh -cat >$SSHDLOGWRAP <>$TEST_REGRESS_LOGFILE -echo "Executing: ${SSHD} \$@" >>\${logfile} -exec ${SSHD} -E\${logfile} "\$@" -EOD -chmod a+rx $OBJ/sshd-log-wrapper.sh - -ssh_logfile () -{ - tool="$1" - timestamp="`$OBJ/timestamp`" - logfile="${TEST_SSH_LOGDIR}/${timestamp}.$tool.$$.log" - echo "Logging $tool to log \${logfile}" >>$TEST_REGRESS_LOGFILE - echo $logfile -} +if "$REAL_SSHD" -? 2>&1 | grep 'PKIX-SSH' > /dev/null; then + sshd_type=pkix +else + sshd_type=other +fi # Some test data. We make a copy because some tests will overwrite it. # The tests may assume that $DATA exists and is writable and $COPY does @@ -353,42 +319,35 @@ # these should be used in tests export SSH SSHD SSHAGENT SSHADD SSHKEYGEN SSHKEYSCAN SFTP SFTPSERVER SCP -export SSH_PKCS11_HELPER SSH_SK_HELPER #echo $SSH $SSHD $SSHAGENT $SSHADD $SSHKEYGEN $SSHKEYSCAN $SFTP $SFTPSERVER $SCP +# these should be used by executables +export SSH_PKCS11_HELPER -# Portable specific functions -which() -{ - saved_IFS="$IFS" - IFS=":" - for i in $PATH - do - if [ -x $i/$1 ]; then - IFS="$saved_IFS" - echo "$i/$1" - return 0 - fi - done - IFS="$saved_IFS" - echo "$i/$1" - return 1 -} +# NOTE: always unset OPENSSL_FIPS even for build with FIPS +# capable OpenSSL library. It will be set latter only if +# fips test is requested. +unset OPENSSL_FIPS || : +# Portable specific functions have_prog() { which "$1" >/dev/null 2>&1 - return $? } jot() { awk "BEGIN { for (i = $2; i < $2 + $1; i++) { printf \"%d\n\", i } exit }" } -if [ ! -x "`which rev`" ]; then -rev() -{ - awk '{for (i=length; i>0; i--) printf "%s", substr($0, i, 1); print ""}' + +# cross-project configuration +# $1: ssh-keygen key type +keytype_compat() { + keytype_val="-t $1" + if test "$sshd_type" != "pkix" ; then + case "$1" in + *25519*) keytype_val="$keytype_val -m OpenSSH" + esac + fi } -fi # Check whether preprocessor symbols are defined in config.h. config_defined () @@ -404,31 +363,20 @@ md5 () { if have_prog md5sum; then md5sum - elif have_prog openssl; then - openssl md5 + elif test -x "$OPENSSL" ; then + $OPENSSL md5 elif have_prog cksum; then cksum elif have_prog sum; then sum - elif [ -x ${OPENSSL_BIN} ]; then - ${OPENSSL_BIN} md5 else wc -c fi } -# Some platforms don't have hostname at all, but on others uname -n doesn't -# provide the fully qualified name we need, so in the former case we create -# our own hostname function. -if ! have_prog hostname; then - hostname() { - uname -n - } -fi - make_tmpdir () { - SSH_REGRESS_TMP="$($OBJ/mkdtemp openssh-XXXXXXXX)" || \ + SSH_REGRESS_TMP="`$OBJ/mkdtemp ssh-regress-XXXXXXXXXX`" || \ fatal "failed to create temporary directory" } # End of portable specific functions @@ -478,61 +426,45 @@ rm -rf "$SSH_REGRESS_TMP" fi stop_sshd - if [ ! -z "$TEST_SSH_ELAPSED_TIMES" ]; then - now=`date '+%s'` + if test -n "$TEST_SSH_ELAPSED_TIME" ; then + now=`date -u '+%s'` elapsed=$(($now - $STARTTIME)) - echo elapsed $elapsed `basename $SCRIPT .sh` + echo "- ${SCRIPT##*/} elapsed time: $elapsed" fi } start_debug_log () { - echo "trace: $@" >>$TEST_REGRESS_LOGFILE - if [ -d "$TEST_SSH_LOGDIR" ]; then - rm -f $TEST_SSH_LOGDIR/* - fi + echo "begin: $@" >$TEST_REGRESS_LOGFILE + echo "begin: $@" >$TEST_SSH_LOGFILE + echo "begin: $@" >$TEST_SSHD_LOGFILE } save_debug_log () { - testname=`echo $tid | tr ' ' _` - tarname="$OBJ/failed-$testname-logs.tar" - - echo $@ >>$TEST_REGRESS_LOGFILE - echo $@ >>$TEST_SSH_LOGFILE - echo $@ >>$TEST_SSHD_LOGFILE - echo "Saving debug logs to $tarname" >>$TEST_REGRESS_LOGFILE + echo ${1+"$@"} >>$TEST_REGRESS_LOGFILE + echo ${1+"$@"} >>$TEST_SSH_LOGFILE + echo ${1+"$@"} >>$TEST_SSHD_LOGFILE (cat $TEST_REGRESS_LOGFILE; echo) >>$OBJ/failed-regress.log (cat $TEST_SSH_LOGFILE; echo) >>$OBJ/failed-ssh.log (cat $TEST_SSHD_LOGFILE; echo) >>$OBJ/failed-sshd.log - - # Save all logfiles in a tarball. - (cd $OBJ && - logfiles="" - for i in $TEST_REGRESS_LOGFILE $TEST_SSH_LOGFILE $TEST_SSHD_LOGFILE \ - $TEST_SSH_LOGDIR; do - if [ -e "`basename $i`" ]; then - logfiles="$logfiles `basename $i`" - else - logfiles="$logfiles $i" - fi - done - tar cf "$tarname" $logfiles) } trace () { - start_debug_log $@ + echo "trace: $@" >>$TEST_REGRESS_LOGFILE + echo "trace: $@" >>$TEST_SSH_LOGFILE + echo "trace: $@" >>$TEST_SSHD_LOGFILE if [ "X$TEST_SSH_TRACE" = "Xyes" ]; then - echo "$@" + echo ${1+"$@"} fi } verbose () { - start_debug_log $@ + start_debug_log ${1+"$@"} if [ "X$TEST_SSH_QUIET" != "Xyes" ]; then - echo "$@" + echo ${1+"$@"} fi } @@ -540,7 +472,7 @@ { save_debug_log "FAIL: $@" RESULT=1 - echo "$@" + echo ${1+"$@"} if test "x$TEST_SSH_FAIL_FATAL" != "x" ; then cleanup exit $RESULT @@ -551,7 +483,7 @@ { save_debug_log "FATAL: $@" printf "FATAL: " - fail "$@" + fail ${1+"$@"} cleanup exit $RESULT } @@ -564,18 +496,6 @@ exit $RESULT } -maybe_add_scp_path_to_sshd () -{ - # If we're testing a non-installed scp, add its directory to sshd's - # PATH so we can test it. We don't do this for all tests as it - # breaks the SetEnv tests. - case "$SCP" in - /*) PATH_WITH_SCP="`dirname $SCP`:$PATH" - echo " SetEnv PATH='$PATH_WITH_SCP'" >>$OBJ/sshd_config - echo " SetEnv PATH='$PATH_WITH_SCP'" >>$OBJ/sshd_proxy ;; - esac -} - RESULT=0 PIDFILE=$OBJ/pidfile @@ -596,44 +516,12 @@ Subsystem sftp $SFTPSERVER EOF -# This may be necessary if /usr/src and/or /usr/obj are group-writable, -# but if you aren't careful with permissions then the unit tests could -# be abused to locally escalate privileges. -if [ ! -z "$TEST_SSH_UNSAFE_PERMISSIONS" ]; then - echo " StrictModes no" >> $OBJ/sshd_config -else - # check and warn if excessive permissions are likely to cause failures. - unsafe="" - dir="${OBJ}" - while test ${dir} != "/"; do - if test -d "${dir}" && ! test -h "${dir}"; then - perms=`ls -ld ${dir}` - case "${perms}" in - ?????w????*|????????w?*) unsafe="${unsafe} ${dir}" ;; - esac - fi - dir=`dirname ${dir}` - done - if ! test -z "${unsafe}"; then - cat <> $OBJ/sshd_config + echo " ModuliFile $TEST_SSH_MODULI_FILE" >> $OBJ/sshd_config fi -if [ ! -z "$TEST_SSH_SSHD_CONFOPTS" ]; then +if test -n "$TEST_SSH_SSHD_CONFOPTS" ; then trace "adding sshd_config option $TEST_SSH_SSHD_CONFOPTS" echo "$TEST_SSH_SSHD_CONFOPTS" >> $OBJ/sshd_config fi @@ -641,9 +529,6 @@ # server config for proxy connects cp $OBJ/sshd_config $OBJ/sshd_proxy -# allow group-writable directories in proxy-mode -echo 'StrictModes no' >> $OBJ/sshd_proxy - # create client config cat << EOF > $OBJ/ssh_config Host * @@ -654,7 +539,8 @@ GlobalKnownHostsFile $OBJ/known_hosts UserKnownHostsFile $OBJ/known_hosts PubkeyAuthentication yes - ChallengeResponseAuthentication no + KbdInteractiveAuthentication no + HostbasedAuthentication no PasswordAuthentication no BatchMode yes StrictHostKeyChecking yes @@ -668,43 +554,29 @@ rm -f $OBJ/known_hosts $OBJ/authorized_keys_$USER -SSH_SK_PROVIDER= -if ! config_defined ENABLE_SK; then - trace skipping sk-dummy -elif [ -f "${SRC}/misc/sk-dummy/obj/sk-dummy.so" ] ; then - SSH_SK_PROVIDER="${SRC}/misc/sk-dummy/obj/sk-dummy.so" -elif [ -f "${OBJ}/misc/sk-dummy/sk-dummy.so" ] ; then - SSH_SK_PROVIDER="${OBJ}/misc/sk-dummy/sk-dummy.so" -elif [ -f "${SRC}/misc/sk-dummy/sk-dummy.so" ] ; then - SSH_SK_PROVIDER="${SRC}/misc/sk-dummy/sk-dummy.so" -fi -export SSH_SK_PROVIDER - -if ! test -z "$SSH_SK_PROVIDER"; then - EXTRA_AGENT_ARGS='-P/*' # XXX want realpath(1)... - echo "SecurityKeyProvider $SSH_SK_PROVIDER" >> $OBJ/ssh_config - echo "SecurityKeyProvider $SSH_SK_PROVIDER" >> $OBJ/sshd_config - echo "SecurityKeyProvider $SSH_SK_PROVIDER" >> $OBJ/sshd_proxy -fi -export EXTRA_AGENT_ARGS - -maybe_filter_sk() { - if test -z "$SSH_SK_PROVIDER" ; then - grep -v ^sk - else - cat - fi -} +SSH_KEYTYPES=`$SSH -Q key-plain | grep -v "^x509v3-"` +SSH_HOSTKEY_TYPES=`$SSH -Q key-plain | grep -v "^x509v3-"` -SSH_KEYTYPES=`$SSH -Q key-plain | maybe_filter_sk` -SSH_HOSTKEY_TYPES=`$SSH -Q key-plain | maybe_filter_sk` +case $SCRIPT in +*/fips-*) + OPENSSL_FIPS=1 + #do not export OPENSSL_FIPS here + SSH_KEYTYPES="ssh-rsa" + SSH_HOSTKEY_TYPES="ssh-rsa" + SSHKEYGEN="$SSHKEYGEN -m PKCS8" + ;; +esac for t in ${SSH_KEYTYPES}; do # generate user key + if test -n "$OPENSSL_FIPS" ; then + rm -f $OBJ/$t + fi if [ ! -f $OBJ/$t ] || [ ${SSHKEYGEN_BIN} -nt $OBJ/$t ]; then trace "generating key type $t" rm -f $OBJ/$t - ${SSHKEYGEN} -q -N '' -t $t -f $OBJ/$t ||\ + keytype_compat $t + $SSHKEYGEN -q -N '' -t $t $keytype_val -f $OBJ/$t ||\ fail "ssh-keygen for $t failed" else trace "using cached key type $t" @@ -722,8 +594,13 @@ cat $OBJ/$t.pub ) >> $OBJ/known_hosts - # use key as host key, too - (umask 077; $SUDO cp $OBJ/$t $OBJ/host.$t) + if test ! -f $OBJ/host.$t || test $OBJ/$t -nt $OBJ/host.$t ; then + # use key as host key, too + cp $OBJ/$t $OBJ/host.$t + case $t in + *xmss*) rm -f $OBJ/host.$t.*;; # remove state + esac + fi echo HostKey $OBJ/host.$t >> $OBJ/sshd_config # don't use SUDO for proxy connect @@ -731,46 +608,57 @@ done chmod 644 $OBJ/authorized_keys_$USER + # Activate Twisted Conch tests if the binary is present -REGRESS_INTEROP_CONCH=no -if test -x "$CONCH" ; then - REGRESS_INTEROP_CONCH=yes -fi +REGRESS_INTEROP_CONCH=false + +# If PuTTY is present and we are running a PuTTY test, prepare keys and +# configuration +REGRESS_INTEROP_PUTTY=false -# If PuTTY is present, new enough and we are running a PuTTY test, prepare -# keys and configuration. -REGRESS_INTEROP_PUTTY=no -if test -x "$PUTTYGEN" -a -x "$PLINK" && - "$PUTTYGEN" --help 2>&1 | grep -- --new-passphrase >/dev/null; then - REGRESS_INTEROP_PUTTY=yes -fi case "$SCRIPT" in -*putty*) ;; -*) REGRESS_INTEROP_PUTTY=no ;; +*conch-*) + if test -x "$CONCH" ; then + REGRESS_INTEROP_CONCH=: + fi + ;; +*putty-*) + if test -x "$PUTTYGEN" -a -x "$PLINK" ; then + REGRESS_INTEROP_PUTTY=: + fi + ;; esac -if test "$REGRESS_INTEROP_PUTTY" = "yes" ; then - mkdir -p ${OBJ}/.putty - - # Add a PuTTY key to authorized_keys +if $REGRESS_INTEROP_PUTTY ; then rm -f ${OBJ}/putty.rsa2 - if ! "$PUTTYGEN" -t rsa -o ${OBJ}/putty.rsa2 \ + if ! $PUTTYGEN -t rsa -o ${OBJ}/putty.rsa2 \ --random-device=/dev/urandom \ --new-passphrase /dev/null < /dev/null > /dev/null; then echo "Your installed version of PuTTY is too old to support --new-passphrase, skipping test" >&2 exit 1 fi - "$PUTTYGEN" -O public-openssh ${OBJ}/putty.rsa2 \ +fi + +if $REGRESS_INTEROP_CONCH || $REGRESS_INTEROP_PUTTY; then + cp $OBJ/ssh-rsa $OBJ/ssh-rsa_pem + $SSHKEYGEN -p -N '' -m PEM -f $OBJ/ssh-rsa_pem >/dev/null +fi + +if $REGRESS_INTEROP_CONCH ; then + $SSHKEYGEN -y -f $OBJ/ssh-rsa_pem > $OBJ/ssh-rsa_pem.pub +fi + +if $REGRESS_INTEROP_PUTTY ; then + mkdir -p ${OBJ}/.putty + + # Add a PuTTY key to authorized_keys + $PUTTYGEN -O public-openssh ${OBJ}/putty.rsa2 \ >> $OBJ/authorized_keys_$USER - # Convert rsa2 host key to PuTTY format - cp $OBJ/ssh-rsa $OBJ/ssh-rsa_oldfmt - ${SSHKEYGEN} -p -N '' -m PEM -f $OBJ/ssh-rsa_oldfmt >/dev/null - ${SRC}/ssh2putty.sh 127.0.0.1 $PORT $OBJ/ssh-rsa_oldfmt > \ + ${SRC}/ssh2putty.sh 127.0.0.1 $PORT $OBJ/ssh-rsa_pem > \ ${OBJ}/.putty/sshhostkeys - ${SRC}/ssh2putty.sh 127.0.0.1 22 $OBJ/ssh-rsa_oldfmt >> \ + ${SRC}/ssh2putty.sh 127.0.0.1 22 $OBJ/ssh-rsa_pem >> \ ${OBJ}/.putty/sshhostkeys - rm -f $OBJ/ssh-rsa_oldfmt # Setup proxied session mkdir -p ${OBJ}/.putty/sessions @@ -779,7 +667,7 @@ echo "HostName=127.0.0.1" >> ${OBJ}/.putty/sessions/localhost_proxy echo "PortNumber=$PORT" >> ${OBJ}/.putty/sessions/localhost_proxy echo "ProxyMethod=5" >> ${OBJ}/.putty/sessions/localhost_proxy - echo "ProxyTelnetCommand=${OBJ}/sshd-log-wrapper.sh -i -f $OBJ/sshd_proxy" >> ${OBJ}/.putty/sessions/localhost_proxy + echo "ProxyTelnetCommand=sh ${SRC}/sshd-log-wrapper.sh ${TEST_SSHD_LOGFILE} ${SSHD} -i -f $OBJ/sshd_proxy" >> ${OBJ}/.putty/sessions/localhost_proxy echo "ProxyLocalhost=1" >> ${OBJ}/.putty/sessions/localhost_proxy PUTTYDIR=${OBJ}/.putty @@ -789,19 +677,21 @@ # create a proxy version of the client config ( cat $OBJ/ssh_config - echo proxycommand ${SUDO} env SSH_SK_HELPER=\"$SSH_SK_HELPER\" ${OBJ}/sshd-log-wrapper.sh -i -f $OBJ/sshd_proxy + echo proxycommand ${SUDO} sh ${SRC}/sshd-log-wrapper.sh ${TEST_SSHD_LOGFILE} ${SSHD} -i -f $OBJ/sshd_proxy ) > $OBJ/ssh_proxy +if test -n "$OPENSSL_FIPS" ; then + export OPENSSL_FIPS +fi + # check proxy config ${SSHD} -t -f $OBJ/sshd_proxy || fatal "sshd_proxy broken" start_sshd () { # start sshd - logfile="${TEST_SSH_LOGDIR}/sshd.`$OBJ/timestamp`.$$.log" - $SUDO ${SSHD} -f $OBJ/sshd_config "$@" -t || fatal "sshd_config broken" - $SUDO env SSH_SK_HELPER="$SSH_SK_HELPER" \ - ${SSHD} -f $OBJ/sshd_config "$@" -E$TEST_SSHD_LOGFILE + $SUDO $SSHD -f $OBJ/sshd_config ${1+"$@"} -t || fatal "sshd_config broken" + $SUDO $SSHD -f $OBJ/sshd_config ${1+"$@"} -E$TEST_SSHD_LOGFILE trace "wait for sshd" i=0; @@ -820,24 +710,6 @@ cleanup if [ "x$USE_VALGRIND" != "x" ]; then - # If there is an EXIT trap handler, invoke it now. - # Some tests set these to clean up processes such as ssh-agent. We - # need to wait for all valgrind processes to complete so we can check - # their logs, but since the EXIT traps are not invoked until - # test-exec.sh exits, waiting here will deadlock. - # This is not very portable but then neither is valgrind itself. - # As a bonus, dash (as used on the runners) has a "trap" that doesn't - # work in a pipeline (hence the temp file) or a subshell. - exithandler="" - trap >/tmp/trap.$$ && exithandler=$(cat /tmp/trap.$$ | \ - awk -F "'" '/EXIT$/{print $2}') - rm -f /tmp/trap.$$ - if [ "x${exithandler}" != "x" ]; then - verbose invoking EXIT trap handler early: ${exithandler} - eval "${exithandler}" - trap '' EXIT - fi - # wait for any running process to complete wait; sleep 1 VG_RESULTS=$(find $OBJ/valgrind-out -type f -print) @@ -863,7 +735,7 @@ if [ $RESULT -eq 0 ]; then verbose ok $tid - if [ "x$CACHE" != "x" ]; then + if test "x$CACHE" != "x" ; then touch "$CACHE" fi else diff -ruN openssh-9.4p1/regress/timestamp.c openssh-9.4p1+x509-14.2.1/regress/timestamp.c --- openssh-9.4p1/regress/timestamp.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/timestamp.c 1970-01-01 02:00:00.000000000 +0200 @@ -1,46 +0,0 @@ -/* - * Copyright (c) 2023 Darren Tucker - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -/* $OpenBSD: timestamp.c,v 1.1 2023/03/01 09:29:32 dtucker Exp $ */ - -/* - * Print a microsecond-granularity timestamp to stdout in an ISO8601-ish - * format, which we can then use as the first component of the log file - * so that they'll sort into chronological order. - */ - -#include - -#include -#include -#include - -int -main(void) -{ - struct timeval tv; - struct tm *tm; - char buf[1024]; - - if (gettimeofday(&tv, NULL) != 0) - exit(1); - if ((tm = localtime(&tv.tv_sec)) == NULL) - exit(2); - if (strftime(buf, sizeof buf, "%Y%m%dT%H%M%S", tm) <= 0) - exit(3); - printf("%s.%06d\n", buf, (int)tv.tv_usec); - exit(0); -} diff -ruN openssh-9.4p1/regress/unittests/authopt/Makefile openssh-9.4p1+x509-14.2.1/regress/unittests/authopt/Makefile --- openssh-9.4p1/regress/unittests/authopt/Makefile 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/unittests/authopt/Makefile 2023-08-20 10:07:00.000000000 +0300 @@ -12,8 +12,7 @@ SRCS+=ssherr.c uidswap.c cleanup.c xmalloc.c match.c krl.c fatal.c SRCS+=addr.c addrmatch.c bitmap.c SRCS+=ed25519.c hash.c -SRCS+=cipher-chachapoly.c chacha.c poly1305.c ssh-ecdsa-sk.c ssh-sk.c -SRCS+=ssh-ed25519-sk.c sk-usbhid.c +SRCS+=cipher-chachapoly.c chacha.c poly1305.c SRCS+=digest-openssl.c #SRCS+=digest-libc.c diff -ruN openssh-9.4p1/regress/unittests/authopt/tests.c openssh-9.4p1+x509-14.2.1/regress/unittests/authopt/tests.c --- openssh-9.4p1/regress/unittests/authopt/tests.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/unittests/authopt/tests.c 2023-08-20 10:07:01.000000000 +0300 @@ -1,23 +1,16 @@ /* $OpenBSD: tests.c,v 1.3 2021/12/14 21:25:27 deraadt Exp $ */ - /* * Regress test for keys options functions. * * Placed in the public domain */ -#include "includes.h" +#include "../test_helper/test_helper.h" -#include #include -#ifdef HAVE_STDINT_H -#include -#endif #include #include -#include "../test_helper/test_helper.h" - #include "sshkey.h" #include "authfile.h" #include "auth-options.h" @@ -144,7 +137,7 @@ ASSERT_PTR_EQ(opts, NULL); \ ASSERT_PTR_NE(errstr, NULL); \ TEST_DONE(); \ - } while (0) + } while (0) #define CHECK_SUCCESS_AND_CLEANUP() \ do { \ if (errstr != NULL) \ diff -ruN openssh-9.4p1/regress/unittests/bitmap/tests.c openssh-9.4p1+x509-14.2.1/regress/unittests/bitmap/tests.c --- openssh-9.4p1/regress/unittests/bitmap/tests.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/unittests/bitmap/tests.c 2023-08-20 10:07:01.000000000 +0300 @@ -5,22 +5,12 @@ * Placed in the public domain */ -#include "includes.h" +#include "../test_helper/test_helper.h" -#include #include -#ifdef HAVE_STDINT_H -#include -#endif #include #include -#ifdef WITH_OPENSSL -#include -#endif - -#include "../test_helper/test_helper.h" - #include "bitmap.h" #define NTESTS 131 diff -ruN openssh-9.4p1/regress/unittests/conversion/tests.c openssh-9.4p1+x509-14.2.1/regress/unittests/conversion/tests.c --- openssh-9.4p1/regress/unittests/conversion/tests.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/unittests/conversion/tests.c 2023-08-20 10:07:01.000000000 +0300 @@ -5,19 +5,14 @@ * Placed in the public domain */ -#include "includes.h" +#include "../test_helper/test_helper.h" -#include #include -#ifdef HAVE_STDINT_H -#include -#endif #include #include -#include "../test_helper/test_helper.h" - #include "misc.h" +#include "ssherr.h" void tests(void) @@ -25,28 +20,133 @@ char buf[1024]; TEST_START("conversion_convtime"); - ASSERT_INT_EQ(convtime("0"), 0); - ASSERT_INT_EQ(convtime("1"), 1); - ASSERT_INT_EQ(convtime("1S"), 1); + ASSERT_LONG_EQ(convtime("0"), 0); + ASSERT_LONG_EQ(convtime("1"), 1); + ASSERT_LONG_EQ(convtime("1S"), 1); /* from the examples in the comment above the function */ - ASSERT_INT_EQ(convtime("90m"), 5400); - ASSERT_INT_EQ(convtime("1h30m"), 5400); - ASSERT_INT_EQ(convtime("2d"), 172800); - ASSERT_INT_EQ(convtime("1w"), 604800); + ASSERT_LONG_EQ(convtime("90m"), 5400); + ASSERT_LONG_EQ(convtime("1h30m"), 5400); + ASSERT_LONG_EQ(convtime("2d"), 172800); + ASSERT_LONG_EQ(convtime("1w"), 604800); /* negative time is not allowed */ - ASSERT_INT_EQ(convtime("-7"), -1); - ASSERT_INT_EQ(convtime("-9d"), -1); - + ASSERT_LONG_EQ(convtime("-7"), -1); + ASSERT_LONG_EQ(convtime("-9d"), -1); + + /* reverse description / based on misc */ + ASSERT_LONG_EQ(convtime("1s1h"), 3601); + ASSERT_LONG_EQ(convtime("4m3h2d1w5"), 788645); + ASSERT_LONG_EQ(convtime("5s4m3h2d1w"), 788645); + /* overflow */ - snprintf(buf, sizeof buf, "%llu", (unsigned long long)INT_MAX); - ASSERT_INT_EQ(convtime(buf), INT_MAX); - snprintf(buf, sizeof buf, "%llu", (unsigned long long)INT_MAX + 1); - ASSERT_INT_EQ(convtime(buf), -1); + snprintf(buf, sizeof buf, "%llu", (unsigned long long)LONG_MAX); + ASSERT_LONG_EQ(convtime(buf), -1); + snprintf(buf, sizeof buf, "%llu", (unsigned long long)LONG_MAX + 1); + ASSERT_LONG_EQ(convtime(buf), -1); /* overflow with multiplier */ - snprintf(buf, sizeof buf, "%lluM", (unsigned long long)INT_MAX/60 + 1); - ASSERT_INT_EQ(convtime(buf), -1); - ASSERT_INT_EQ(convtime("1000000000000000000000w"), -1); + snprintf(buf, sizeof buf, "%lluM", (unsigned long long)LONG_MAX/60 + 1); + ASSERT_LONG_EQ(convtime(buf), -1); + ASSERT_LONG_EQ(convtime("1000000000000000000000w"), -1); + TEST_DONE(); + + TEST_START("misc_convtime"); /* moved here;) */ + ASSERT_LONG_EQ(convtime("1"), 1); + ASSERT_LONG_EQ(convtime("2s"), 2); + ASSERT_LONG_EQ(convtime("3m"), 180); + ASSERT_LONG_EQ(convtime("1m30"), 90); + ASSERT_LONG_EQ(convtime("1m30s"), 90); + ASSERT_LONG_EQ(convtime("1h1s"), 3601); + ASSERT_LONG_EQ(convtime("1h30m"), 90 * 60); + ASSERT_LONG_EQ(convtime("1d"), 24 * 60 * 60); + ASSERT_LONG_EQ(convtime("1w"), 7 * 24 * 60 * 60); + ASSERT_LONG_EQ(convtime("1w2d3h4m5"), 788645); + ASSERT_LONG_EQ(convtime("1w2d3h4m5s"), 788645); + /* any negative number or error returns -1 */ + ASSERT_LONG_EQ(convtime("-1"), -1); + ASSERT_LONG_EQ(convtime(""), -1); + ASSERT_LONG_EQ(convtime("trout"), -1); + ASSERT_LONG_EQ(convtime("-77"), -1); + TEST_DONE(); + + TEST_START("conversion_fmttime"); +{ char *res; + res = fmttime(13); + ASSERT_STRING_EQ(res, "13s"); + free(res); + res = fmttime((12)*60+13); + ASSERT_STRING_EQ(res, "12m13s"); + free(res); + res = fmttime(((11)*60+12)*60+13); + ASSERT_STRING_EQ(res, "11h12m13s"); + free(res); + res = fmttime((((5)*24+11)*60+12)*60+13); + ASSERT_STRING_EQ(res, "5d11h12m"); + free(res); + res = fmttime(((((4)*7+5)*24+11)*60+12)*60+13); + ASSERT_STRING_EQ(res, "4w5d11h"); + free(res); +} + TEST_DONE(); + +{ uint64_t t; + /* XXX timezones/DST make verification of this tricky */ + /* XXX maybe setenv TZ and tzset() to make it unambiguous? */ + TEST_START("misc_parse_absolute_time"); + ASSERT_INT_EQ(parse_absolute_time("20000101", &t), 0); + ASSERT_INT_EQ(parse_absolute_time("200001011223", &t), 0); + ASSERT_INT_EQ(parse_absolute_time("20000101122345", &t), 0); + + /* forced UTC TZ */ + ASSERT_INT_EQ(parse_absolute_time("20000101Z", &t), 0); + ASSERT_U64_EQ(t, 946684800); + ASSERT_INT_EQ(parse_absolute_time("200001011223Z", &t), 0); + ASSERT_U64_EQ(t, 946729380); + ASSERT_INT_EQ(parse_absolute_time("20000101122345Z", &t), 0); + ASSERT_U64_EQ(t, 946729425); + ASSERT_INT_EQ(parse_absolute_time("20000101UTC", &t), 0); + ASSERT_U64_EQ(t, 946684800); + ASSERT_INT_EQ(parse_absolute_time("200001011223UTC", &t), 0); + ASSERT_U64_EQ(t, 946729380); + ASSERT_INT_EQ(parse_absolute_time("20000101122345UTC", &t), 0); + ASSERT_U64_EQ(t, 946729425); + + /* Bad month */ + ASSERT_INT_EQ(parse_absolute_time("20001301", &t), + SSH_ERR_INVALID_FORMAT); + ASSERT_INT_EQ(parse_absolute_time("20000001", &t), + SSH_ERR_INVALID_FORMAT); + /* Incomplete */ + ASSERT_INT_EQ(parse_absolute_time("2", &t), + SSH_ERR_INVALID_FORMAT); + ASSERT_INT_EQ(parse_absolute_time("2000", &t), + SSH_ERR_INVALID_FORMAT); + ASSERT_INT_EQ(parse_absolute_time("20000", &t), + SSH_ERR_INVALID_FORMAT); + ASSERT_INT_EQ(parse_absolute_time("200001", &t), + SSH_ERR_INVALID_FORMAT); + ASSERT_INT_EQ(parse_absolute_time("2000010", &t), + SSH_ERR_INVALID_FORMAT); + ASSERT_INT_EQ(parse_absolute_time("200001010", &t), + SSH_ERR_INVALID_FORMAT); + /* Bad day, hour, minute, second */ + ASSERT_INT_EQ(parse_absolute_time("20000199", &t), + SSH_ERR_INVALID_FORMAT); + ASSERT_INT_EQ(parse_absolute_time("200001019900", &t), + SSH_ERR_INVALID_FORMAT); + ASSERT_INT_EQ(parse_absolute_time("200001010099", &t), + SSH_ERR_INVALID_FORMAT); + ASSERT_INT_EQ(parse_absolute_time("20000101000099", &t), + SSH_ERR_INVALID_FORMAT); + /* Invalid TZ specifier */ + ASSERT_INT_EQ(parse_absolute_time("20000101ZZ", &t), + SSH_ERR_INVALID_FORMAT); + ASSERT_INT_EQ(parse_absolute_time("20000101PDT", &t), + SSH_ERR_INVALID_FORMAT); + ASSERT_INT_EQ(parse_absolute_time("20000101U", &t), + SSH_ERR_INVALID_FORMAT); + ASSERT_INT_EQ(parse_absolute_time("20000101UTCUTC", &t), + SSH_ERR_INVALID_FORMAT); +} TEST_DONE(); } diff -ruN openssh-9.4p1/regress/unittests/hostkeys/Makefile openssh-9.4p1+x509-14.2.1/regress/unittests/hostkeys/Makefile --- openssh-9.4p1/regress/unittests/hostkeys/Makefile 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/unittests/hostkeys/Makefile 2023-08-20 10:07:00.000000000 +0300 @@ -10,8 +10,7 @@ SRCS+=ssherr.c uidswap.c cleanup.c xmalloc.c match.c krl.c fatal.c SRCS+=addr.c addrmatch.c bitmap.c hostfile.c SRCS+=ed25519.c hash.c -SRCS+=cipher-chachapoly.c chacha.c poly1305.c ssh-ecdsa-sk.c ssh-sk.c -SRCS+=ssh-ed25519-sk.c sk-usbhid.c +SRCS+=cipher-chachapoly.c chacha.c poly1305.c SRCS+=digest-openssl.c #SRCS+=digest-libc.c diff -ruN openssh-9.4p1/regress/unittests/hostkeys/testdata/rsa1_1.pub openssh-9.4p1+x509-14.2.1/regress/unittests/hostkeys/testdata/rsa1_1.pub --- openssh-9.4p1/regress/unittests/hostkeys/testdata/rsa1_1.pub 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/unittests/hostkeys/testdata/rsa1_1.pub 1970-01-01 02:00:00.000000000 +0200 @@ -1 +0,0 @@ -1024 65537 153895431603677073925890314548566704948446776958334195280085080329934839226701954473292358821568047724356487621573742372399387931887004184139835510820577359977148363519970774657801798872789118894962853659233045778161859413980935372685480527355016624825696983269800574755126132814333241868538220824608980319407 RSA1 #1 diff -ruN openssh-9.4p1/regress/unittests/hostkeys/testdata/rsa1_2.pub openssh-9.4p1+x509-14.2.1/regress/unittests/hostkeys/testdata/rsa1_2.pub --- openssh-9.4p1/regress/unittests/hostkeys/testdata/rsa1_2.pub 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/unittests/hostkeys/testdata/rsa1_2.pub 1970-01-01 02:00:00.000000000 +0200 @@ -1 +0,0 @@ -1024 65537 135970715082947442639683969597180728933388298633245835186618852623800675939308729462220235058285909679252157995530180587329132927339620517781785310829060832352381015614725360278571924286986474946772141568893116432268565829418506866604294073334978275702221949783314402806080929601995102334442541344606109853641 RSA1 #2 diff -ruN openssh-9.4p1/regress/unittests/hostkeys/testdata/rsa1_3.pub openssh-9.4p1+x509-14.2.1/regress/unittests/hostkeys/testdata/rsa1_3.pub --- openssh-9.4p1/regress/unittests/hostkeys/testdata/rsa1_3.pub 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/unittests/hostkeys/testdata/rsa1_3.pub 1970-01-01 02:00:00.000000000 +0200 @@ -1 +0,0 @@ -1024 65537 125895605498029643697051635076028105429632810811904702876152645261610759866299221305725069141163240694267669117205342283569102183636228981857946763978553664895308762890072813014496700601576921921752482059207749978374872713540759920335553799711267170948655579130584031555334229966603000896364091459595522912269 RSA1 #3 diff -ruN openssh-9.4p1/regress/unittests/hostkeys/testdata/rsa1_4.pub openssh-9.4p1+x509-14.2.1/regress/unittests/hostkeys/testdata/rsa1_4.pub --- openssh-9.4p1/regress/unittests/hostkeys/testdata/rsa1_4.pub 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/unittests/hostkeys/testdata/rsa1_4.pub 1970-01-01 02:00:00.000000000 +0200 @@ -1 +0,0 @@ -1024 65537 174143366122697048196335388217056770310345753698079464367148030836533360510864881734142526411160017107552815906024399248049666856133771656680462456979369587903909343046704480897527203474513676654933090991684252819423129896444427656841613263783484827101210734799449281639493127615902427443211183258155381810593 RSA1 #4 diff -ruN openssh-9.4p1/regress/unittests/hostkeys/testdata/rsa1_5.pub openssh-9.4p1+x509-14.2.1/regress/unittests/hostkeys/testdata/rsa1_5.pub --- openssh-9.4p1/regress/unittests/hostkeys/testdata/rsa1_5.pub 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/unittests/hostkeys/testdata/rsa1_5.pub 1970-01-01 02:00:00.000000000 +0200 @@ -1 +0,0 @@ -1024 65537 127931411493401587586867047972295564331543694182352197506125410692673654572057908999642645524647232712160516076508316152810117209181150078352725299319149726341058893406440426414316276977768958023952319602422835879783057966985348561111880658922724668687074412548487722084792283453716871417610020757212399252171 RSA1 #5 diff -ruN openssh-9.4p1/regress/unittests/hostkeys/testdata/rsa1_6.pub openssh-9.4p1+x509-14.2.1/regress/unittests/hostkeys/testdata/rsa1_6.pub --- openssh-9.4p1/regress/unittests/hostkeys/testdata/rsa1_6.pub 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/unittests/hostkeys/testdata/rsa1_6.pub 1970-01-01 02:00:00.000000000 +0200 @@ -1 +0,0 @@ -1024 65537 140883028436203600354693376066567741282115117509696517282419557936340193768851493584179972504103033755515036493433917203732876685813283050574208967197963391667532902202382549275760997891673884333346000558018002659506756213191532156293935482587878596032743105911487673274674568768638010598205190227631909167257 RSA1 #6 diff -ruN openssh-9.4p1/regress/unittests/hostkeys/test_iterate.c openssh-9.4p1+x509-14.2.1/regress/unittests/hostkeys/test_iterate.c --- openssh-9.4p1/regress/unittests/hostkeys/test_iterate.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/unittests/hostkeys/test_iterate.c 2023-08-20 10:07:01.000000000 +0300 @@ -5,18 +5,12 @@ * Placed in the public domain */ -#include "includes.h" +#include "../test_helper/test_helper.h" -#include #include -#ifdef HAVE_STDINT_H -#include -#endif #include #include -#include "../test_helper/test_helper.h" - #include "sshkey.h" #include "authfile.h" #include "hostfile.h" @@ -94,6 +88,11 @@ expected->no_parse_keytype == KEY_ECDSA) skip = 1; #endif /* OPENSSL_HAS_ECC */ +#ifndef OPENSSL_HAS_NISTP521 + if (expected->l.keytype == KEY_ECDSA && + expected->l.linenum == 9) + skip = 1; +#endif #ifndef WITH_OPENSSL if (expected->l.keytype == KEY_DSA || expected->no_parse_keytype == KEY_DSA || @@ -155,6 +154,11 @@ if (expected[i].l.keytype == KEY_ECDSA) continue; #endif /* OPENSSL_HAS_ECC */ +#ifndef OPENSSL_HAS_NISTP521 + if (expected[i].l.keytype == KEY_ECDSA && + expected[i].l.linenum == 9) + continue; +#endif #ifndef WITH_OPENSSL switch (expected[i].l.keytype) { case KEY_RSA: diff -ruN openssh-9.4p1/regress/unittests/kex/Makefile openssh-9.4p1+x509-14.2.1/regress/unittests/kex/Makefile --- openssh-9.4p1/regress/unittests/kex/Makefile 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/unittests/kex/Makefile 2023-08-20 10:07:00.000000000 +0300 @@ -10,8 +10,7 @@ SRCS+=ssherr.c uidswap.c cleanup.c xmalloc.c match.c krl.c fatal.c SRCS+=addr.c addrmatch.c bitmap.c packet.c dispatch.c canohost.c ssh_api.c SRCS+=compat.c ed25519.c hash.c -SRCS+=cipher-chachapoly.c chacha.c poly1305.c ssh-ecdsa-sk.c ssh-sk.c -SRCS+=ssh-ed25519-sk.c sk-usbhid.c +SRCS+=cipher-chachapoly.c chacha.c poly1305.c SRCS+= kex.c SRCS+= dh.c diff -ruN openssh-9.4p1/regress/unittests/kex/test_kex.c openssh-9.4p1+x509-14.2.1/regress/unittests/kex/test_kex.c --- openssh-9.4p1/regress/unittests/kex/test_kex.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/unittests/kex/test_kex.c 2023-08-20 10:07:01.000000000 +0300 @@ -5,18 +5,12 @@ * Placed in the public domain */ -#include "includes.h" +#include "../test_helper/test_helper.h" -#include #include -#ifdef HAVE_STDINT_H -#include -#endif #include #include -#include "../test_helper/test_helper.h" - #include "ssherr.h" #include "ssh_api.h" #include "sshbuf.h" @@ -140,21 +134,10 @@ ASSERT_INT_EQ(sshbuf_len(state), 0); sshbuf_free(state); ASSERT_PTR_NE(server2->kex, NULL); - /* XXX we need to set the callbacks */ -#ifdef WITH_OPENSSL - server2->kex->kex[KEX_DH_GRP1_SHA1] = kex_gen_server; - server2->kex->kex[KEX_DH_GRP14_SHA1] = kex_gen_server; - server2->kex->kex[KEX_DH_GEX_SHA1] = kexgex_server; - server2->kex->kex[KEX_DH_GEX_SHA256] = kexgex_server; -#ifdef OPENSSL_HAS_ECC - server2->kex->kex[KEX_ECDH_SHA2] = kex_gen_server; -#endif /* OPENSSL_HAS_ECC */ -#endif /* WITH_OPENSSL */ - server2->kex->kex[KEX_C25519_SHA256] = kex_gen_server; - server2->kex->kex[KEX_KEM_SNTRUP761X25519_SHA512] = kex_gen_server; - server2->kex->load_host_public_key = server->kex->load_host_public_key; - server2->kex->load_host_private_key = server->kex->load_host_private_key; - server2->kex->sign = server->kex->sign; + kex_set_callbacks_server(server2->kex); + server2->kex->find_host_public_key = server->kex->find_host_public_key; + server2->kex->find_host_private_key = server->kex->find_host_private_key; + server2->kex->xsign = server->kex->xsign; TEST_DONE(); TEST_START("rekeying server2"); @@ -184,25 +167,33 @@ do_kex_with_key(kex, KEY_ECDSA, 256); #endif /* OPENSSL_HAS_ECC */ #endif /* WITH_OPENSSL */ +#ifdef HAVE_EVP_SHA256 do_kex_with_key(kex, KEY_ED25519, 256); +#endif /*def HAVE_EVP_SHA256*/ } void kex_tests(void) { +#ifdef HAVE_EVP_SHA256 do_kex("curve25519-sha256@libssh.org"); +#endif /*def HAVE_EVP_SHA256*/ #ifdef WITH_OPENSSL #ifdef OPENSSL_HAS_ECC do_kex("ecdh-sha2-nistp256"); do_kex("ecdh-sha2-nistp384"); +#ifdef OPENSSL_HAS_NISTP521 do_kex("ecdh-sha2-nistp521"); +#endif #endif /* OPENSSL_HAS_ECC */ +#ifdef HAVE_EVP_SHA256 do_kex("diffie-hellman-group-exchange-sha256"); +#endif /*def HAVE_EVP_SHA256*/ +#ifdef ENABLE_KEX_SNTRUP761X25519 + do_kex("sntrup761x25519-sha512@openssh.com"); +#endif /*def ENABLE_KEX_SNTRUP761X25519*/ do_kex("diffie-hellman-group-exchange-sha1"); do_kex("diffie-hellman-group14-sha1"); do_kex("diffie-hellman-group1-sha1"); -# ifdef USE_SNTRUP761X25519 - do_kex("sntrup761x25519-sha512@openssh.com"); -# endif /* USE_SNTRUP761X25519 */ #endif /* WITH_OPENSSL */ } diff -ruN openssh-9.4p1/regress/unittests/kex/test_proposal.c openssh-9.4p1+x509-14.2.1/regress/unittests/kex/test_proposal.c --- openssh-9.4p1/regress/unittests/kex/test_proposal.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/unittests/kex/test_proposal.c 2023-08-20 10:07:01.000000000 +0300 @@ -1,41 +1,32 @@ -/* $OpenBSD: test_proposal.c,v 1.2 2023/03/06 12:15:47 dtucker Exp $ */ +/* $OpenBSD: test_proposal.c,v 1.1 2023/02/02 12:12:52 djm Exp $ */ /* * Regress test KEX * * Placed in the public domain */ -#include "includes.h" +#include "../test_helper/test_helper.h" -#include -#include #include -#ifdef HAVE_STDINT_H -#include -#endif #include #include -#include "../test_helper/test_helper.h" - -#include "cipher.h" #include "compat.h" #include "ssherr.h" #include "sshbuf.h" #include "kex.h" -#include "myproposal.h" #include "packet.h" #include "xmalloc.h" -void kex_proposal_tests(void); -void kex_proposal_populate_tests(void); +void kex_proposal(void); #define CURVE25519 "curve25519-sha256@libssh.org" #define DHGEX1 "diffie-hellman-group-exchange-sha1" #define DHGEX256 "diffie-hellman-group-exchange-sha256" #define KEXALGOS CURVE25519","DHGEX256","DHGEX1 + void -kex_proposal_tests(void) +kex_proposal(void) { size_t i; struct ssh ssh; @@ -54,24 +45,29 @@ }; TEST_START("compat_kex_proposal"); + ssh.compat.extra = 0; for (i = 0; i < sizeof(tests) / sizeof(*tests); i++) { - ssh.compat = tests[i].compat; + ssh.compat.datafellows = tests[i].compat; + /* match entire string */ result = compat_kex_proposal(&ssh, tests[i].in); ASSERT_STRING_EQ(result, tests[i].out); free(result); + /* match at end */ in = kex_names_cat("a", tests[i].in); out = kex_names_cat("a", tests[i].out); result = compat_kex_proposal(&ssh, in); ASSERT_STRING_EQ(result, out); free(result); free(in); free(out); + /* match at start */ in = kex_names_cat(tests[i].in, "a"); out = kex_names_cat(tests[i].out, "a"); result = compat_kex_proposal(&ssh, in); ASSERT_STRING_EQ(result, out); free(result); free(in); free(out); + /* match in middle */ xasprintf(&in, "a,%s,b", tests[i].in); if (*(tests[i].out) == '\0') @@ -84,41 +80,3 @@ } TEST_DONE(); } - -void -kex_proposal_populate_tests(void) -{ - char *prop[PROPOSAL_MAX], *kexalgs, *ciphers, *macs, *hkalgs; - const char *comp = compression_alg_list(0); - int i; - struct ssh ssh; - struct kex kex; - - kexalgs = kex_alg_list(','); - ciphers = cipher_alg_list(',', 0); - macs = mac_alg_list(','); - hkalgs = kex_alg_list(','); - - ssh.kex = &kex; - TEST_START("compat_kex_proposal_populate"); - for (i = 0; i <= 1; i++) { - kex.server = i; - for (ssh.compat = 0; ssh.compat < 0x40000000; ) { - kex_proposal_populate_entries(&ssh, prop, NULL, NULL, - NULL, NULL, NULL); - kex_proposal_free_entries(prop); - kex_proposal_populate_entries(&ssh, prop, kexalgs, - ciphers, macs, hkalgs, comp); - kex_proposal_free_entries(prop); - if (ssh.compat == 0) - ssh.compat = 1; - else - ssh.compat <<= 1; - } - } - - free(kexalgs); - free(ciphers); - free(macs); - free(hkalgs); -} diff -ruN openssh-9.4p1/regress/unittests/kex/tests.c openssh-9.4p1+x509-14.2.1/regress/unittests/kex/tests.c --- openssh-9.4p1/regress/unittests/kex/tests.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/unittests/kex/tests.c 2023-08-20 10:07:01.000000000 +0300 @@ -1,18 +1,21 @@ -/* $OpenBSD: tests.c,v 1.3 2023/03/06 12:15:47 dtucker Exp $ */ +/* $OpenBSD: tests.c,v 1.2 2023/02/02 12:12:52 djm Exp $ */ /* * Placed in the public domain */ #include "../test_helper/test_helper.h" +#include "ssh_api.h" void kex_tests(void); -void kex_proposal_tests(void); -void kex_proposal_populate_tests(void); +void kex_proposal(void); void tests(void) { + ssh_crypto_init(); + kex_tests(); - kex_proposal_tests(); - kex_proposal_populate_tests(); + kex_proposal(); + + ssh_crypto_fini(); } diff -ruN openssh-9.4p1/regress/unittests/Makefile openssh-9.4p1+x509-14.2.1/regress/unittests/Makefile --- openssh-9.4p1/regress/unittests/Makefile 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/unittests/Makefile 2023-08-20 10:07:00.000000000 +0300 @@ -1,7 +1,7 @@ -# $OpenBSD: Makefile,v 1.12 2020/06/19 04:34:21 djm Exp $ +# $OpenBSD: Makefile,v 1.11 2019/04/28 22:53:26 dtucker Exp $ REGRESS_FAIL_EARLY?= yes SUBDIR= test_helper sshbuf sshkey bitmap kex hostkeys utf8 match conversion -SUBDIR+=authopt misc sshsig +SUBDIR+=authopt misc .include diff -ruN openssh-9.4p1/regress/unittests/Makefile.inc openssh-9.4p1+x509-14.2.1/regress/unittests/Makefile.inc --- openssh-9.4p1/regress/unittests/Makefile.inc 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/unittests/Makefile.inc 2023-08-20 10:07:00.000000000 +0300 @@ -74,9 +74,6 @@ DPADD+= ${LIBCRYPTO} .endif -LDADD+= -lfido2 -lcbor -lusbhid -DPADD+= ${LIBFIDO2} ${LIBCBOR} ${LIBUSBHID} - UNITTEST_ARGS?= .if (${UNITTEST_VERBOSE:L} != "no") diff -ruN openssh-9.4p1/regress/unittests/match/tests.c openssh-9.4p1+x509-14.2.1/regress/unittests/match/tests.c --- openssh-9.4p1/regress/unittests/match/tests.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/unittests/match/tests.c 2023-08-20 10:07:01.000000000 +0300 @@ -5,18 +5,12 @@ * Placed in the public domain */ -#include "includes.h" +#include "../test_helper/test_helper.h" -#include #include -#ifdef HAVE_STDINT_H -#include -#endif #include #include -#include "../test_helper/test_helper.h" - #include "match.h" void diff -ruN openssh-9.4p1/regress/unittests/misc/Makefile openssh-9.4p1+x509-14.2.1/regress/unittests/misc/Makefile --- openssh-9.4p1/regress/unittests/misc/Makefile 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/unittests/misc/Makefile 2023-08-20 10:07:00.000000000 +0300 @@ -2,7 +2,6 @@ PROG=test_misc SRCS=tests.c -SRCS+= test_convtime.c SRCS+= test_expand.c SRCS+= test_parse.c SRCS+= test_argv.c diff -ruN openssh-9.4p1/regress/unittests/misc/test_argv.c openssh-9.4p1+x509-14.2.1/regress/unittests/misc/test_argv.c --- openssh-9.4p1/regress/unittests/misc/test_argv.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/unittests/misc/test_argv.c 2023-08-20 10:07:01.000000000 +0300 @@ -5,18 +5,12 @@ * Placed in the public domain. */ -#include "includes.h" +#include "../test_helper/test_helper.h" -#include #include -#ifdef HAVE_STDINT_H -#include -#endif #include #include -#include "../test_helper/test_helper.h" - #include "log.h" #include "misc.h" @@ -148,39 +142,6 @@ ASSERT_PTR_EQ(av[1], NULL); RESET_ARGV(); TEST_DONE(); - - TEST_START("comments"); - ASSERT_INT_EQ(argv_split("# gold", &ac, &av, 0), 0); - ASSERT_INT_EQ(ac, 2); - ASSERT_PTR_NE(av, NULL); - ASSERT_STRING_EQ(av[0], "#"); - ASSERT_STRING_EQ(av[1], "gold"); - ASSERT_PTR_EQ(av[2], NULL); - RESET_ARGV(); - ASSERT_INT_EQ(argv_split("# gold", &ac, &av, 1), 0); - ASSERT_INT_EQ(ac, 0); - ASSERT_PTR_NE(av, NULL); - ASSERT_PTR_EQ(av[0], NULL); - RESET_ARGV(); - ASSERT_INT_EQ(argv_split("leamas#gold", &ac, &av, 1), 0); - ASSERT_INT_EQ(ac, 1); - ASSERT_PTR_NE(av, NULL); - ASSERT_STRING_EQ(av[0], "leamas#gold"); - ASSERT_PTR_EQ(av[1], NULL); - RESET_ARGV(); - ASSERT_INT_EQ(argv_split("\"leamas # gold\"", &ac, &av, 1), 0); - ASSERT_INT_EQ(ac, 1); - ASSERT_PTR_NE(av, NULL); - ASSERT_STRING_EQ(av[0], "leamas # gold"); - ASSERT_PTR_EQ(av[1], NULL); - RESET_ARGV(); - ASSERT_INT_EQ(argv_split("\"leamas\"#gold", &ac, &av, 1), 0); - ASSERT_INT_EQ(ac, 1); - ASSERT_PTR_NE(av, NULL); - ASSERT_STRING_EQ(av[0], "leamas#gold"); - ASSERT_PTR_EQ(av[1], NULL); - RESET_ARGV(); - TEST_DONE(); /* XXX test char *argv_assemble(int argc, char **argv) */ } diff -ruN openssh-9.4p1/regress/unittests/misc/test_convtime.c openssh-9.4p1+x509-14.2.1/regress/unittests/misc/test_convtime.c --- openssh-9.4p1/regress/unittests/misc/test_convtime.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/unittests/misc/test_convtime.c 1970-01-01 02:00:00.000000000 +0200 @@ -1,121 +0,0 @@ -/* $OpenBSD: test_convtime.c,v 1.3 2022/08/11 01:57:50 djm Exp $ */ -/* - * Regress test for misc time conversion functions. - * - * Placed in the public domain. - */ - -#include "includes.h" - -#include -#include -#include -#ifdef HAVE_STDINT_H -#include -#endif -#include -#include - -#include "../test_helper/test_helper.h" - -#include "log.h" -#include "misc.h" -#include "ssherr.h" - -void test_convtime(void); - -void -test_convtime(void) -{ - char buf[1024]; - uint64_t t; - - TEST_START("misc_convtime"); - ASSERT_INT_EQ(convtime("0"), 0); - ASSERT_INT_EQ(convtime("1"), 1); - ASSERT_INT_EQ(convtime("2s"), 2); - ASSERT_INT_EQ(convtime("3m"), 180); - ASSERT_INT_EQ(convtime("1m30"), 90); - ASSERT_INT_EQ(convtime("1m30s"), 90); - ASSERT_INT_EQ(convtime("1h1s"), 3601); - ASSERT_INT_EQ(convtime("1h30m"), 90 * 60); - ASSERT_INT_EQ(convtime("1d"), 24 * 60 * 60); - ASSERT_INT_EQ(convtime("1w"), 7 * 24 * 60 * 60); - ASSERT_INT_EQ(convtime("1w2d3h4m5"), 788645); - ASSERT_INT_EQ(convtime("1w2d3h4m5s"), 788645); - /* any negative number or error returns -1 */ - ASSERT_INT_EQ(convtime("-1"), -1); - ASSERT_INT_EQ(convtime(""), -1); - ASSERT_INT_EQ(convtime("trout"), -1); - ASSERT_INT_EQ(convtime("-77"), -1); - /* boundary conditions */ - snprintf(buf, sizeof buf, "%llu", (long long unsigned)INT_MAX); - ASSERT_INT_EQ(convtime(buf), INT_MAX); - snprintf(buf, sizeof buf, "%llu", (long long unsigned)INT_MAX + 1); - ASSERT_INT_EQ(convtime(buf), -1); - ASSERT_INT_EQ(convtime("3550w5d3h14m7s"), 2147483647); -#if INT_MAX == 2147483647 - ASSERT_INT_EQ(convtime("3550w5d3h14m8s"), -1); -#endif - TEST_DONE(); - - /* XXX timezones/DST make verification of this tricky */ - /* XXX maybe setenv TZ and tzset() to make it unambiguous? */ - TEST_START("misc_parse_absolute_time"); - ASSERT_INT_EQ(parse_absolute_time("20000101", &t), 0); - ASSERT_INT_EQ(parse_absolute_time("200001011223", &t), 0); - ASSERT_INT_EQ(parse_absolute_time("20000101122345", &t), 0); - - /* forced UTC TZ */ - ASSERT_INT_EQ(parse_absolute_time("20000101Z", &t), 0); - ASSERT_U64_EQ(t, 946684800); - ASSERT_INT_EQ(parse_absolute_time("200001011223Z", &t), 0); - ASSERT_U64_EQ(t, 946729380); - ASSERT_INT_EQ(parse_absolute_time("20000101122345Z", &t), 0); - ASSERT_U64_EQ(t, 946729425); - ASSERT_INT_EQ(parse_absolute_time("20000101UTC", &t), 0); - ASSERT_U64_EQ(t, 946684800); - ASSERT_INT_EQ(parse_absolute_time("200001011223UTC", &t), 0); - ASSERT_U64_EQ(t, 946729380); - ASSERT_INT_EQ(parse_absolute_time("20000101122345UTC", &t), 0); - ASSERT_U64_EQ(t, 946729425); - - /* Bad month */ - ASSERT_INT_EQ(parse_absolute_time("20001301", &t), - SSH_ERR_INVALID_FORMAT); - ASSERT_INT_EQ(parse_absolute_time("20000001", &t), - SSH_ERR_INVALID_FORMAT); - /* Incomplete */ - ASSERT_INT_EQ(parse_absolute_time("2", &t), - SSH_ERR_INVALID_FORMAT); - ASSERT_INT_EQ(parse_absolute_time("2000", &t), - SSH_ERR_INVALID_FORMAT); - ASSERT_INT_EQ(parse_absolute_time("20000", &t), - SSH_ERR_INVALID_FORMAT); - ASSERT_INT_EQ(parse_absolute_time("200001", &t), - SSH_ERR_INVALID_FORMAT); - ASSERT_INT_EQ(parse_absolute_time("2000010", &t), - SSH_ERR_INVALID_FORMAT); - ASSERT_INT_EQ(parse_absolute_time("200001010", &t), - SSH_ERR_INVALID_FORMAT); - /* Bad day, hour, minute, second */ - ASSERT_INT_EQ(parse_absolute_time("20000199", &t), - SSH_ERR_INVALID_FORMAT); - ASSERT_INT_EQ(parse_absolute_time("200001019900", &t), - SSH_ERR_INVALID_FORMAT); - ASSERT_INT_EQ(parse_absolute_time("200001010099", &t), - SSH_ERR_INVALID_FORMAT); - ASSERT_INT_EQ(parse_absolute_time("20000101000099", &t), - SSH_ERR_INVALID_FORMAT); - /* Invalid TZ specifier */ - ASSERT_INT_EQ(parse_absolute_time("20000101ZZ", &t), - SSH_ERR_INVALID_FORMAT); - ASSERT_INT_EQ(parse_absolute_time("20000101PDT", &t), - SSH_ERR_INVALID_FORMAT); - ASSERT_INT_EQ(parse_absolute_time("20000101U", &t), - SSH_ERR_INVALID_FORMAT); - ASSERT_INT_EQ(parse_absolute_time("20000101UTCUTC", &t), - SSH_ERR_INVALID_FORMAT); - - TEST_DONE(); -} diff -ruN openssh-9.4p1/regress/unittests/misc/test_expand.c openssh-9.4p1+x509-14.2.1/regress/unittests/misc/test_expand.c --- openssh-9.4p1/regress/unittests/misc/test_expand.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/unittests/misc/test_expand.c 2023-08-20 10:07:01.000000000 +0300 @@ -5,18 +5,12 @@ * Placed in the public domain. */ -#include "includes.h" +#include "../test_helper/test_helper.h" -#include #include -#ifdef HAVE_STDINT_H -#include -#endif #include #include -#include "../test_helper/test_helper.h" - #include "log.h" #include "misc.h" @@ -72,18 +66,27 @@ log_init("test_misc", SYSLOG_LEVEL_INFO, SYSLOG_FACILITY_AUTH, 1); TEST_DONE(); +#define ASSERT_RET_EQ(v) do { \ + ASSERT_STRING_EQ(ret, (v)); \ + free(ret); \ +} while(0) TEST_START("percent_expand"); - ASSERT_STRING_EQ(percent_expand("%%", "%h", "foo", NULL), "%"); - ASSERT_STRING_EQ(percent_expand("%h", "h", "foo", NULL), "foo"); - ASSERT_STRING_EQ(percent_expand("%h ", "h", "foo", NULL), "foo "); - ASSERT_STRING_EQ(percent_expand(" %h", "h", "foo", NULL), " foo"); - ASSERT_STRING_EQ(percent_expand(" %h ", "h", "foo", NULL), " foo "); - ASSERT_STRING_EQ(percent_expand(" %a%b ", "a", "foo", "b", "bar", NULL), - " foobar "); + ret = percent_expand("%%", "%h", "foo", NULL); + ASSERT_RET_EQ("%"); + ret = percent_expand("%h", "h", "foo", NULL); + ASSERT_RET_EQ("foo"); + ret = percent_expand("%h ", "h", "foo", NULL); + ASSERT_RET_EQ("foo "); + ret = percent_expand(" %h", "h", "foo", NULL); + ASSERT_RET_EQ(" foo"); + ret = percent_expand(" %h ", "h", "foo", NULL); + ASSERT_RET_EQ(" foo "); + ret = percent_expand(" %a%b ", "a", "foo", "b", "bar", NULL); + ASSERT_RET_EQ(" foobar "); TEST_DONE(); TEST_START("percent_dollar_expand"); - ASSERT_STRING_EQ(percent_dollar_expand("%h${FOO}", "h", "foo", NULL), - "foobar"); + ret = percent_dollar_expand("%h${FOO}", "h", "foo", NULL); + ASSERT_RET_EQ("foobar"); TEST_DONE(); } diff -ruN openssh-9.4p1/regress/unittests/misc/test_hpdelim.c openssh-9.4p1+x509-14.2.1/regress/unittests/misc/test_hpdelim.c --- openssh-9.4p1/regress/unittests/misc/test_hpdelim.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/unittests/misc/test_hpdelim.c 2023-08-20 10:07:01.000000000 +0300 @@ -5,18 +5,14 @@ * Placed in the public domain. */ -#include "includes.h" +#include "../test_helper/test_helper.h" #include + #include -#ifdef HAVE_STDINT_H -#include -#endif #include #include -#include "../test_helper/test_helper.h" - #include "log.h" #include "misc.h" #include "xmalloc.h" @@ -78,5 +74,4 @@ ASSERT_PTR_EQ(cp, NULL); DONE_STRING(); TEST_DONE(); - } diff -ruN openssh-9.4p1/regress/unittests/misc/test_parse.c openssh-9.4p1+x509-14.2.1/regress/unittests/misc/test_parse.c --- openssh-9.4p1/regress/unittests/misc/test_parse.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/unittests/misc/test_parse.c 2023-08-20 10:07:01.000000000 +0300 @@ -5,18 +5,12 @@ * Placed in the public domain. */ -#include "includes.h" +#include "../test_helper/test_helper.h" -#include #include -#ifdef HAVE_STDINT_H -#include -#endif #include #include -#include "../test_helper/test_helper.h" - #include "log.h" #include "misc.h" diff -ruN openssh-9.4p1/regress/unittests/misc/test_ptimeout.c openssh-9.4p1+x509-14.2.1/regress/unittests/misc/test_ptimeout.c --- openssh-9.4p1/regress/unittests/misc/test_ptimeout.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/unittests/misc/test_ptimeout.c 2023-08-20 10:07:01.000000000 +0300 @@ -5,23 +5,16 @@ * Placed in the public domain. */ -#include "includes.h" +#include "../test_helper/test_helper.h" #include + #include -#ifdef HAVE_STDINT_H -# include -#endif #include #include -#ifdef HAVE_POLL_H -# include -#endif -#include -#include "../test_helper/test_helper.h" +#include -#include "log.h" #include "misc.h" void test_ptimeout(void); @@ -53,7 +46,7 @@ ASSERT_INT_EQ(ptimeout_get_ms(&pt), 50123); ts = ptimeout_get_tsp(&pt); ASSERT_PTR_NE(ts, NULL); - ASSERT_LONG_EQ(ts->tv_nsec, 123 * 1000000); + ASSERT_LONG_EQ(ts->tv_nsec, 123 * 1000000L); ASSERT_LONG_EQ(ts->tv_sec, 50); TEST_DONE(); diff -ruN openssh-9.4p1/regress/unittests/misc/tests.c openssh-9.4p1+x509-14.2.1/regress/unittests/misc/tests.c --- openssh-9.4p1/regress/unittests/misc/tests.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/unittests/misc/tests.c 2023-08-20 10:07:01.000000000 +0300 @@ -5,23 +5,9 @@ * Placed in the public domain. */ -#include "includes.h" - -#include -#include -#ifdef HAVE_STDINT_H -#include -#endif -#include -#include - #include "../test_helper/test_helper.h" -#include "log.h" -#include "misc.h" - void test_parse(void); -void test_convtime(void); void test_expand(void); void test_argv(void); void test_strdelim(void); @@ -32,10 +18,10 @@ tests(void) { test_parse(); - test_convtime(); test_expand(); test_argv(); - test_strdelim(); + if (getenv("UNITTEST_MISC_STRDELIM") != NULL) + test_strdelim(); test_hpdelim(); test_ptimeout(); } diff -ruN openssh-9.4p1/regress/unittests/misc/test_strdelim.c openssh-9.4p1+x509-14.2.1/regress/unittests/misc/test_strdelim.c --- openssh-9.4p1/regress/unittests/misc/test_strdelim.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/unittests/misc/test_strdelim.c 2023-08-20 10:07:01.000000000 +0300 @@ -5,18 +5,12 @@ * Placed in the public domain. */ -#include "includes.h" +#include "../test_helper/test_helper.h" -#include #include -#ifdef HAVE_STDINT_H -#include -#endif #include #include -#include "../test_helper/test_helper.h" - #include "log.h" #include "misc.h" #include "xmalloc.h" @@ -192,10 +186,11 @@ TEST_START("oops quote"); START_STRING("\"blob\\\""); cp = strdelim(&str); - ASSERT_STRING_EQ(cp, "blob\\"); /* XXX wrong */ + ASSERT_PTR_EQ(cp, NULL); /* XXX wrong */ + ASSERT_STRING_EQ(str, "blob\""); cp = strdelim(&str); - ASSERT_STRING_EQ(cp, ""); + ASSERT_PTR_EQ(cp, NULL); + ASSERT_STRING_EQ(str, ""); DONE_STRING(); TEST_DONE(); - } diff -ruN openssh-9.4p1/regress/unittests/sshbuf/Makefile openssh-9.4p1+x509-14.2.1/regress/unittests/sshbuf/Makefile --- openssh-9.4p1/regress/unittests/sshbuf/Makefile 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/unittests/sshbuf/Makefile 2023-08-20 10:07:00.000000000 +0300 @@ -1,6 +1,6 @@ # $OpenBSD: Makefile,v 1.10 2021/01/09 12:24:31 dtucker Exp $ -# $OpenBSD: Makefile,v 1.8 2020/01/26 00:09:50 djm Exp $ +.include PROG=test_sshbuf SRCS=tests.c diff -ruN openssh-9.4p1/regress/unittests/sshbuf/test_sshbuf.c openssh-9.4p1+x509-14.2.1/regress/unittests/sshbuf/test_sshbuf.c --- openssh-9.4p1/regress/unittests/sshbuf/test_sshbuf.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/unittests/sshbuf/test_sshbuf.c 2023-08-20 10:07:01.000000000 +0300 @@ -6,27 +6,17 @@ */ #define SSHBUF_INTERNAL 1 /* access internals for testing */ -#include "includes.h" +#include "../test_helper/test_helper.h" -#include #include -#ifdef HAVE_STDINT_H -# include -#endif #include #include -#include "../test_helper/test_helper.h" - #include "ssherr.h" #include "sshbuf.h" void sshbuf_tests(void); -#ifndef roundup -#define roundup(x, y) ((((x)+((y)-1))/(y))*(y)) -#endif - void sshbuf_tests(void) { @@ -202,7 +192,7 @@ TEST_START("resize full buffer"); r = sshbuf_set_max_size(p1, 1000); ASSERT_INT_EQ(r, SSH_ERR_NO_BUFFER_SPACE); - sz = roundup(1223 + SSHBUF_SIZE_INC * 3, SSHBUF_SIZE_INC); + sz = ROUNDUP(1223 + SSHBUF_SIZE_INC * 3, SSHBUF_SIZE_INC); ASSERT_INT_EQ(sshbuf_set_max_size(p1, sz), 0); ASSERT_SIZE_T_EQ(sshbuf_max_size(p1), sz); ASSERT_SIZE_T_EQ(sshbuf_avail(p1), sz - 1223); diff -ruN openssh-9.4p1/regress/unittests/sshbuf/test_sshbuf_fixed.c openssh-9.4p1+x509-14.2.1/regress/unittests/sshbuf/test_sshbuf_fixed.c --- openssh-9.4p1/regress/unittests/sshbuf/test_sshbuf_fixed.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/unittests/sshbuf/test_sshbuf_fixed.c 2023-08-20 10:07:01.000000000 +0300 @@ -6,18 +6,12 @@ */ #define SSHBUF_INTERNAL 1 /* access internals for testing */ -#include "includes.h" +#include "../test_helper/test_helper.h" -#include #include -#ifdef HAVE_STDINT_H -# include -#endif #include #include -#include "../test_helper/test_helper.h" - #include "sshbuf.h" #include "ssherr.h" @@ -122,4 +116,5 @@ ASSERT_PTR_EQ(p3, NULL); sshbuf_free(p2); sshbuf_free(p1); + TEST_DONE(); } diff -ruN openssh-9.4p1/regress/unittests/sshbuf/test_sshbuf_fuzz.c openssh-9.4p1+x509-14.2.1/regress/unittests/sshbuf/test_sshbuf_fuzz.c --- openssh-9.4p1/regress/unittests/sshbuf/test_sshbuf_fuzz.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/unittests/sshbuf/test_sshbuf_fuzz.c 2023-08-20 10:07:01.000000000 +0300 @@ -5,18 +5,12 @@ * Placed in the public domain */ -#include "includes.h" +#include "../test_helper/test_helper.h" -#include #include -#ifdef HAVE_STDINT_H -# include -#endif #include #include -#include "../test_helper/test_helper.h" - #include "ssherr.h" #include "sshbuf.h" diff -ruN openssh-9.4p1/regress/unittests/sshbuf/test_sshbuf_getput_basic.c openssh-9.4p1+x509-14.2.1/regress/unittests/sshbuf/test_sshbuf_getput_basic.c --- openssh-9.4p1/regress/unittests/sshbuf/test_sshbuf_getput_basic.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/unittests/sshbuf/test_sshbuf_getput_basic.c 2023-08-20 10:07:01.000000000 +0300 @@ -5,17 +5,12 @@ * Placed in the public domain */ -#include "includes.h" +#include "../test_helper/test_helper.h" -#include #include -#ifdef HAVE_STDINT_H -# include -#endif #include #include -#include "../test_helper/test_helper.h" #include "ssherr.h" #include "sshbuf.h" @@ -56,19 +51,19 @@ TEST_DONE(); TEST_START("POKE_U64"); - bzero(d2, sizeof(d2)); + memset(d2, 0, sizeof(d2)); POKE_U64(d2, 0x1122334455667788ULL); ASSERT_MEM_EQ(d2, x, 8); TEST_DONE(); - + TEST_START("POKE_U32"); - bzero(d2, sizeof(d2)); + memset(d2, 0, sizeof(d2)); POKE_U32(d2, 0x11223344); ASSERT_MEM_EQ(d2, x, 4); TEST_DONE(); - + TEST_START("POKE_U16"); - bzero(d2, sizeof(d2)); + memset(d2, 0, sizeof(d2)); POKE_U16(d2, 0x1122); ASSERT_MEM_EQ(d2, x, 2); TEST_DONE(); @@ -224,7 +219,7 @@ ASSERT_SIZE_T_EQ(sshbuf_len(p1), 0); sshbuf_free(p1); TEST_DONE(); - + TEST_START("sshbuf_put_u32"); p1 = sshbuf_new(); ASSERT_PTR_NE(p1, NULL); @@ -253,7 +248,7 @@ ASSERT_SIZE_T_EQ(sshbuf_len(p1), 0); sshbuf_free(p1); TEST_DONE(); - + TEST_START("sshbuf_put_u16"); p1 = sshbuf_new(); ASSERT_PTR_NE(p1, NULL); @@ -575,6 +570,7 @@ s2 = sshbuf_dtob16(p1); ASSERT_PTR_NE(s2, NULL); ASSERT_STRING_EQ(s2, "00000000000000000000"); + free(s2); sshbuf_free(p1); TEST_DONE(); @@ -609,6 +605,7 @@ s2 = sshbuf_dtob16(p1); ASSERT_PTR_NE(s2, NULL); ASSERT_STRING_EQ(s2, "00000000000000000000"); + free(s2); sshbuf_free(p1); TEST_DONE(); @@ -643,6 +640,7 @@ s2 = sshbuf_dtob16(p1); ASSERT_PTR_NE(s2, NULL); ASSERT_STRING_EQ(s2, "00000000000000000000"); + free(s2); sshbuf_free(p1); TEST_DONE(); @@ -673,6 +671,7 @@ s2 = sshbuf_dtob16(p1); ASSERT_PTR_NE(s2, NULL); ASSERT_STRING_EQ(s2, "00000000000000000000"); + free(s2); sshbuf_free(p1); TEST_DONE(); @@ -707,6 +706,7 @@ s2 = sshbuf_dtob16(p1); ASSERT_PTR_NE(s2, NULL); ASSERT_STRING_EQ(s2, "00000000000000000000"); + free(s2); sshbuf_free(p1); TEST_DONE(); } diff -ruN openssh-9.4p1/regress/unittests/sshbuf/test_sshbuf_getput_crypto.c openssh-9.4p1+x509-14.2.1/regress/unittests/sshbuf/test_sshbuf_getput_crypto.c --- openssh-9.4p1/regress/unittests/sshbuf/test_sshbuf_getput_crypto.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/unittests/sshbuf/test_sshbuf_getput_crypto.c 2023-08-20 10:07:01.000000000 +0300 @@ -5,28 +5,48 @@ * Placed in the public domain */ -#include "includes.h" +#define OPENSSL_SUPPRESS_DEPRECATED /* TODO implement OpenSSL 3.1 API */ + +#include "../test_helper/test_helper.h" #ifdef WITH_OPENSSL -#include #include -#ifdef HAVE_STDINT_H -# include -#endif #include #include -#include -#include -#ifdef OPENSSL_HAS_NISTP256 -# include -#endif - -#include "../test_helper/test_helper.h" +#include "evp-compat.h" #include "ssherr.h" #include "sshbuf.h" + +#ifndef HAVE_EC_POINT_GET_AFFINE_COORDINATES /* OpenSSL < 1.1.1 */ +#ifdef OPENSSL_HAS_ECC +/* Functions are available even in 0.9.7* but EC is not activated + * as NIST curves are not supported yet. + */ +/* Functions are available even in 0.9.7* but EC is not activated + * as NIST curves are not supported yet. + */ +static inline int +EC_POINT_get_affine_coordinates( + const EC_GROUP *group, const EC_POINT *p, + BIGNUM *x, BIGNUM *y, BN_CTX *ctx +) { + return EC_POINT_get_affine_coordinates_GFp(group, p, x, y, ctx); +} + +static inline int +EC_POINT_set_affine_coordinates( + const EC_GROUP *group, EC_POINT *p, + const BIGNUM *x, const BIGNUM *y, BN_CTX *ctx +) { + return EC_POINT_set_affine_coordinates_GFp(group, p, x, y, ctx); +} +#endif /*def OPENSSL_HAS_ECC*/ +#endif /*ndef HAVE_EC_POINT_GET_AFFINE_COORDINATES*/ + + void sshbuf_getput_crypto_tests(void); void @@ -230,7 +250,7 @@ ASSERT_PTR_NE(ecp, NULL); MKBN(ec256_x, bn_x); MKBN(ec256_y, bn_y); - ASSERT_INT_EQ(EC_POINT_set_affine_coordinates_GFp( + ASSERT_INT_EQ(EC_POINT_set_affine_coordinates( EC_KEY_get0_group(eck), ecp, bn_x, bn_y, NULL), 1); ASSERT_INT_EQ(EC_KEY_set_public_key(eck, ecp), 1); BN_free(bn_x); @@ -259,7 +279,7 @@ bn_y = BN_new(); ASSERT_PTR_NE(bn_x, NULL); ASSERT_PTR_NE(bn_y, NULL); - ASSERT_INT_EQ(EC_POINT_get_affine_coordinates_GFp( + ASSERT_INT_EQ(EC_POINT_get_affine_coordinates( EC_KEY_get0_group(eck), EC_KEY_get0_public_key(eck), bn_x, bn_y, NULL), 1); MKBN(ec256_x, bn); diff -ruN openssh-9.4p1/regress/unittests/sshbuf/test_sshbuf_getput_fuzz.c openssh-9.4p1+x509-14.2.1/regress/unittests/sshbuf/test_sshbuf_getput_fuzz.c --- openssh-9.4p1/regress/unittests/sshbuf/test_sshbuf_getput_fuzz.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/unittests/sshbuf/test_sshbuf_getput_fuzz.c 2023-08-20 10:07:01.000000000 +0300 @@ -5,27 +5,19 @@ * Placed in the public domain */ -#include "includes.h" +#define OPENSSL_SUPPRESS_DEPRECATED /* TODO implement OpenSSL 3.1 API */ + +#include "../test_helper/test_helper.h" -#include #include -#ifdef HAVE_STDINT_H -# include -#endif #include #include -#ifdef WITH_OPENSSL -#include -#include -#ifdef OPENSSL_HAS_NISTP256 -# include -#endif -#endif - -#include "../test_helper/test_helper.h" #include "ssherr.h" #include "sshbuf.h" +#ifdef WITH_OPENSSL +#include /* for NID_X9_62_prime256v1 */ +#endif /* WITH_OPENSSL */ void sshbuf_getput_fuzz_tests(void); @@ -54,7 +46,7 @@ sshbuf_get_u32(p1, &u32); sshbuf_get_u64(p1, &u64); if (sshbuf_get_string(p1, &s, &l) == 0) { - bzero(s, l); + memset(s, 0, l); free(s); } #ifdef WITH_OPENSSL diff -ruN openssh-9.4p1/regress/unittests/sshbuf/test_sshbuf_misc.c openssh-9.4p1+x509-14.2.1/regress/unittests/sshbuf/test_sshbuf_misc.c --- openssh-9.4p1/regress/unittests/sshbuf/test_sshbuf_misc.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/unittests/sshbuf/test_sshbuf_misc.c 2023-08-20 10:07:01.000000000 +0300 @@ -5,18 +5,12 @@ * Placed in the public domain */ -#include "includes.h" +#include "../test_helper/test_helper.h" -#include #include -#ifdef HAVE_STDINT_H -# include -#endif #include #include -#include "../test_helper/test_helper.h" - #include "sshbuf.h" #include "ssherr.h" @@ -100,7 +94,7 @@ p1 = sshbuf_new(); ASSERT_PTR_NE(p1, NULL); ASSERT_INT_EQ(sshbuf_reserve(p1, 8192, NULL), 0); - bzero(sshbuf_mutable_ptr(p1), 8192); + memset(sshbuf_mutable_ptr(p1), 0, 8192); p = sshbuf_dtob64_string(p1, 0); ASSERT_PTR_NE(p, NULL); ASSERT_SIZE_T_EQ(strlen(p), ((8191 + 2) / 3) * 4); @@ -182,6 +176,7 @@ ASSERT_INT_EQ(sshbuf_cmp(p1, 1000, "silence", 7), SSH_ERR_MESSAGE_INCOMPLETE); ASSERT_INT_EQ(sshbuf_cmp(p1, 0, msg, sizeof(msg) - 1), 0); + sshbuf_free(p1); TEST_DONE(); TEST_START("sshbuf_find"); @@ -212,6 +207,7 @@ SSH_ERR_MESSAGE_INCOMPLETE); ASSERT_INT_EQ(sshbuf_find(p1, 0, msg + 1, sizeof(msg) - 2, &sz), 0); ASSERT_SIZE_T_EQ(sz, 1); + sshbuf_free(p1); TEST_DONE(); } diff -ruN openssh-9.4p1/regress/unittests/sshkey/common.c openssh-9.4p1+x509-14.2.1/regress/unittests/sshkey/common.c --- openssh-9.4p1/regress/unittests/sshkey/common.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/unittests/sshkey/common.c 2023-08-20 10:07:01.000000000 +0300 @@ -5,33 +5,15 @@ * Placed in the public domain */ -#include "includes.h" +#include "../test_helper/test_helper.h" -#include #include #include #include -#ifdef HAVE_STDINT_H -#include -#endif #include #include #include -#ifdef WITH_OPENSSL -#include -#include -#include -#include -#ifdef OPENSSL_HAS_NISTP256 -# include -#endif /* OPENSSL_HAS_NISTP256 */ -#endif /* WITH_OPENSSL */ - -#include "openbsd-compat/openssl-compat.h" - -#include "../test_helper/test_helper.h" - #include "ssherr.h" #include "authfile.h" #include "sshkey.h" @@ -82,82 +64,4 @@ sshbuf_free(buf); return ret; } - -const BIGNUM * -rsa_n(struct sshkey *k) -{ - const BIGNUM *n = NULL; - - ASSERT_PTR_NE(k, NULL); - ASSERT_PTR_NE(k->rsa, NULL); - RSA_get0_key(k->rsa, &n, NULL, NULL); - return n; -} - -const BIGNUM * -rsa_e(struct sshkey *k) -{ - const BIGNUM *e = NULL; - - ASSERT_PTR_NE(k, NULL); - ASSERT_PTR_NE(k->rsa, NULL); - RSA_get0_key(k->rsa, NULL, &e, NULL); - return e; -} - -const BIGNUM * -rsa_p(struct sshkey *k) -{ - const BIGNUM *p = NULL; - - ASSERT_PTR_NE(k, NULL); - ASSERT_PTR_NE(k->rsa, NULL); - RSA_get0_factors(k->rsa, &p, NULL); - return p; -} - -const BIGNUM * -rsa_q(struct sshkey *k) -{ - const BIGNUM *q = NULL; - - ASSERT_PTR_NE(k, NULL); - ASSERT_PTR_NE(k->rsa, NULL); - RSA_get0_factors(k->rsa, NULL, &q); - return q; -} - -const BIGNUM * -dsa_g(struct sshkey *k) -{ - const BIGNUM *g = NULL; - - ASSERT_PTR_NE(k, NULL); - ASSERT_PTR_NE(k->dsa, NULL); - DSA_get0_pqg(k->dsa, NULL, NULL, &g); - return g; -} - -const BIGNUM * -dsa_pub_key(struct sshkey *k) -{ - const BIGNUM *pub_key = NULL; - - ASSERT_PTR_NE(k, NULL); - ASSERT_PTR_NE(k->dsa, NULL); - DSA_get0_key(k->dsa, &pub_key, NULL); - return pub_key; -} - -const BIGNUM * -dsa_priv_key(struct sshkey *k) -{ - const BIGNUM *priv_key = NULL; - - ASSERT_PTR_NE(k, NULL); - ASSERT_PTR_NE(k->dsa, NULL); - DSA_get0_key(k->dsa, NULL, &priv_key); - return priv_key; -} #endif /* WITH_OPENSSL */ - diff -ruN openssh-9.4p1/regress/unittests/sshkey/common.h openssh-9.4p1+x509-14.2.1/regress/unittests/sshkey/common.h --- openssh-9.4p1/regress/unittests/sshkey/common.h 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/unittests/sshkey/common.h 2023-08-20 10:07:00.000000000 +0300 @@ -14,12 +14,3 @@ /* Load a bignum from a file */ BIGNUM *load_bignum(const char *name); -/* Accessors for key components */ -const BIGNUM *rsa_n(struct sshkey *k); -const BIGNUM *rsa_e(struct sshkey *k); -const BIGNUM *rsa_p(struct sshkey *k); -const BIGNUM *rsa_q(struct sshkey *k); -const BIGNUM *dsa_g(struct sshkey *k); -const BIGNUM *dsa_pub_key(struct sshkey *k); -const BIGNUM *dsa_priv_key(struct sshkey *k); - diff -ruN openssh-9.4p1/regress/unittests/sshkey/Makefile openssh-9.4p1+x509-14.2.1/regress/unittests/sshkey/Makefile --- openssh-9.4p1/regress/unittests/sshkey/Makefile 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/unittests/sshkey/Makefile 2023-08-20 10:07:00.000000000 +0300 @@ -10,8 +10,7 @@ SRCS+=ssherr.c uidswap.c cleanup.c xmalloc.c match.c krl.c fatal.c SRCS+=addr.c addrmatch.c bitmap.c SRCS+=ed25519.c hash.c -SRCS+=cipher-chachapoly.c chacha.c poly1305.c ssh-ecdsa-sk.c ssh-sk.c -SRCS+=ssh-ed25519-sk.c sk-usbhid.c +SRCS+=cipher-chachapoly.c chacha.c poly1305.c SRCS+=digest-openssl.c #SRCS+=digest-libc.c diff -ruN openssh-9.4p1/regress/unittests/sshkey/mktestdata.sh openssh-9.4p1+x509-14.2.1/regress/unittests/sshkey/mktestdata.sh --- openssh-9.4p1/regress/unittests/sshkey/mktestdata.sh 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/unittests/sshkey/mktestdata.sh 2023-08-20 10:07:00.000000000 +0300 @@ -70,15 +70,6 @@ cd testdata -if [ -f ../../../misc/sk-dummy/sk-dummy.so ] ; then - SK_DUMMY=../../../misc/sk-dummy/sk-dummy.so -elif [ -f ../../../misc/sk-dummy/obj/sk-dummy.so ] ; then - SK_DUMMY=../../../misc/sk-dummy/obj/sk-dummy.so -else - echo "Can't find sk-dummy.so" 1>&2 - exit 1 -fi - rm -f rsa_1 dsa_1 ecdsa_1 ed25519_1 rm -f rsa_2 dsa_2 ecdsa_2 ed25519_2 rm -f rsa_n dsa_n ecdsa_n # new-format keys @@ -90,35 +81,24 @@ ssh-keygen -t dsa -b 1024 -C "DSA test key #1" -N "" -f dsa_1 -m PEM ssh-keygen -t ecdsa -b 256 -C "ECDSA test key #1" -N "" -f ecdsa_1 -m PEM ssh-keygen -t ed25519 -C "ED25519 test key #1" -N "" -f ed25519_1 -ssh-keygen -w "$SK_DUMMY" -t ecdsa-sk -C "ECDSA-SK test key #1" \ - -N "" -f ecdsa_sk1 -ssh-keygen -w "$SK_DUMMY" -t ed25519-sk -C "ED25519-SK test key #1" \ - -N "" -f ed25519_sk1 - ssh-keygen -t rsa -b 2048 -C "RSA test key #2" -N "" -f rsa_2 -m PEM ssh-keygen -t dsa -b 1024 -C "DSA test key #2" -N "" -f dsa_2 -m PEM ssh-keygen -t ecdsa -b 521 -C "ECDSA test key #2" -N "" -f ecdsa_2 -m PEM ssh-keygen -t ed25519 -C "ED25519 test key #2" -N "" -f ed25519_2 -ssh-keygen -w "$SK_DUMMY" -t ecdsa-sk -C "ECDSA-SK test key #2" \ - -N "" -f ecdsa_sk2 -ssh-keygen -w "$SK_DUMMY" -t ed25519-sk -C "ED25519-SK test key #2" \ - -N "" -f ed25519_sk2 cp rsa_1 rsa_n cp dsa_1 dsa_n cp ecdsa_1 ecdsa_n -ssh-keygen -pf rsa_n -N "" -ssh-keygen -pf dsa_n -N "" -ssh-keygen -pf ecdsa_n -N "" +ssh-keygen -pf rsa_n -m OpenSSH -N "" +ssh-keygen -pf dsa_n -m OpenSSH -N "" +ssh-keygen -pf ecdsa_n -m OpenSSH -N "" cp rsa_1 rsa_1_pw cp dsa_1 dsa_1_pw cp ecdsa_1 ecdsa_1_pw cp ed25519_1 ed25519_1_pw -cp ecdsa_sk1 ecdsa_sk1_pw -cp ed25519_sk1 ed25519_sk1_pw cp rsa_1 rsa_n_pw cp dsa_1 dsa_n_pw cp ecdsa_1 ecdsa_n_pw @@ -127,11 +107,9 @@ ssh-keygen -pf dsa_1_pw -m PEM -N "$PW" ssh-keygen -pf ecdsa_1_pw -m PEM -N "$PW" ssh-keygen -pf ed25519_1_pw -N "$PW" -ssh-keygen -pf ecdsa_sk1_pw -m PEM -N "$PW" -ssh-keygen -pf ed25519_sk1_pw -N "$PW" -ssh-keygen -pf rsa_n_pw -N "$PW" -ssh-keygen -pf dsa_n_pw -N "$PW" -ssh-keygen -pf ecdsa_n_pw -N "$PW" +ssh-keygen -pf rsa_n_pw -m OpenSSH -N "$PW" +ssh-keygen -pf dsa_n_pw -m OpenSSH -N "$PW" +ssh-keygen -pf ecdsa_n_pw -m OpenSSH -N "$PW" rsa_params rsa_1 rsa_1.param rsa_params rsa_2 rsa_2.param @@ -139,7 +117,7 @@ dsa_params dsa_1 dsa_1.param ecdsa_params ecdsa_1 ecdsa_1.param ecdsa_params ecdsa_2 ecdsa_2.param -# XXX ed25519, *sk params +# XXX ed25519 params ssh-keygen -s rsa_2 -I hugo -n user1,user2 \ -Oforce-command=/bin/ls -Ono-port-forwarding -Osource-address=10.0.0.0/8 \ @@ -153,13 +131,6 @@ ssh-keygen -s rsa_2 -I hugo -n user1,user2 \ -Oforce-command=/bin/ls -Ono-port-forwarding -Osource-address=10.0.0.0/8 \ -V 19990101:20110101 -z 4 ed25519_1.pub -ssh-keygen -s rsa_2 -I hugo -n user1,user2 \ - -Oforce-command=/bin/ls -Ono-port-forwarding -Osource-address=10.0.0.0/8 \ - -V 19990101:20110101 -z 4 ecdsa_sk1.pub -ssh-keygen -s rsa_2 -I hugo -n user1,user2 \ - -Oforce-command=/bin/ls -Ono-port-forwarding -Osource-address=10.0.0.0/8 \ - -V 19990101:20110101 -z 4 ed25519_sk1.pub - # Make a few RSA variant signature too. cp rsa_1 rsa_1_sha1 @@ -181,42 +152,28 @@ -V 19990101:20110101 -z 7 ecdsa_1.pub ssh-keygen -s ed25519_1 -I julius -n host1,host2 -h \ -V 19990101:20110101 -z 8 ed25519_1.pub -ssh-keygen -s ecdsa_1 -I julius -n host1,host2 -h \ - -V 19990101:20110101 -z 7 ecdsa_sk1.pub -ssh-keygen -s ed25519_1 -I julius -n host1,host2 -h \ - -V 19990101:20110101 -z 8 ed25519_sk1.pub ssh-keygen -lf rsa_1 | awk '{print $2}' > rsa_1.fp ssh-keygen -lf dsa_1 | awk '{print $2}' > dsa_1.fp ssh-keygen -lf ecdsa_1 | awk '{print $2}' > ecdsa_1.fp ssh-keygen -lf ed25519_1 | awk '{print $2}' > ed25519_1.fp -ssh-keygen -lf ecdsa_sk1 | awk '{print $2}' > ecdsa_sk1.fp -ssh-keygen -lf ed25519_sk1 | awk '{print $2}' > ed25519_sk1.fp ssh-keygen -lf rsa_2 | awk '{print $2}' > rsa_2.fp ssh-keygen -lf dsa_2 | awk '{print $2}' > dsa_2.fp ssh-keygen -lf ecdsa_2 | awk '{print $2}' > ecdsa_2.fp ssh-keygen -lf ed25519_2 | awk '{print $2}' > ed25519_2.fp -ssh-keygen -lf ecdsa_sk2 | awk '{print $2}' > ecdsa_sk2.fp -ssh-keygen -lf ed25519_sk2 | awk '{print $2}' > ed25519_sk2.fp ssh-keygen -lf rsa_1-cert.pub | awk '{print $2}' > rsa_1-cert.fp ssh-keygen -lf dsa_1-cert.pub | awk '{print $2}' > dsa_1-cert.fp ssh-keygen -lf ecdsa_1-cert.pub | awk '{print $2}' > ecdsa_1-cert.fp ssh-keygen -lf ed25519_1-cert.pub | awk '{print $2}' > ed25519_1-cert.fp -ssh-keygen -lf ecdsa_sk1-cert.pub | awk '{print $2}' > ecdsa_sk1-cert.fp -ssh-keygen -lf ed25519_sk1-cert.pub | awk '{print $2}' > ed25519_sk1-cert.fp ssh-keygen -Bf rsa_1 | awk '{print $2}' > rsa_1.fp.bb ssh-keygen -Bf dsa_1 | awk '{print $2}' > dsa_1.fp.bb ssh-keygen -Bf ecdsa_1 | awk '{print $2}' > ecdsa_1.fp.bb ssh-keygen -Bf ed25519_1 | awk '{print $2}' > ed25519_1.fp.bb -ssh-keygen -Bf ecdsa_sk1 | awk '{print $2}' > ecdsa_sk1.fp.bb -ssh-keygen -Bf ed25519_sk1 | awk '{print $2}' > ed25519_sk1.fp.bb ssh-keygen -Bf rsa_2 | awk '{print $2}' > rsa_2.fp.bb ssh-keygen -Bf dsa_2 | awk '{print $2}' > dsa_2.fp.bb ssh-keygen -Bf ecdsa_2 | awk '{print $2}' > ecdsa_2.fp.bb ssh-keygen -Bf ed25519_2 | awk '{print $2}' > ed25519_2.fp.bb -ssh-keygen -Bf ecdsa_sk2 | awk '{print $2}' > ecdsa_sk2.fp.bb -ssh-keygen -Bf ed25519_sk2 | awk '{print $2}' > ed25519_sk2.fp.bb echo "$PW" > pw diff -ruN openssh-9.4p1/regress/unittests/sshkey/testdata/ecdsa_sk1 openssh-9.4p1+x509-14.2.1/regress/unittests/sshkey/testdata/ecdsa_sk1 --- openssh-9.4p1/regress/unittests/sshkey/testdata/ecdsa_sk1 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/unittests/sshkey/testdata/ecdsa_sk1 1970-01-01 02:00:00.000000000 +0200 @@ -1,13 +0,0 @@ ------BEGIN OPENSSH PRIVATE KEY----- -b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAfwAAACJzay1lY2 -RzYS1zaGEyLW5pc3RwMjU2QG9wZW5zc2guY29tAAAACG5pc3RwMjU2AAAAQQRnVT5Cji1D -Ge2+q2X0vATh6LYnODV+DJrshJorr5GnipW29RfuaDXs0WB6XBej9dOLazVRDjQrtV19Qg -O6cfkFAAAABHNzaDoAAAGQuPdnP7j3Zz8AAAAic2stZWNkc2Etc2hhMi1uaXN0cDI1NkBv -cGVuc3NoLmNvbQAAAAhuaXN0cDI1NgAAAEEEZ1U+Qo4tQxntvqtl9LwE4ei2Jzg1fgya7I -SaK6+Rp4qVtvUX7mg17NFgelwXo/XTi2s1UQ40K7VdfUIDunH5BQAAAARzc2g6AQAAAOMt -LS0tLUJFR0lOIEVDIFBSSVZBVEUgS0VZLS0tLS0KTUhjQ0FRRUVJRURmVFB4YzA0alN5Zk -Z5NlhoV1pTVlpzcnU5ZFlaSVpTOWhjeVFhcDlVT29Bb0dDQ3FHU000OQpBd0VIb1VRRFFn -QUVaMVUrUW80dFF4bnR2cXRsOUx3RTRlaTJKemcxZmd5YTdJU2FLNitScDRxVnR2VVg3bW -cxCjdORmdlbHdYby9YVGkyczFVUTQwSzdWZGZVSUR1bkg1QlE9PQotLS0tLUVORCBFQyBQ -UklWQVRFIEtFWS0tLS0tCgAAAAAAAAAURUNEU0EtU0sgdGVzdCBrZXkgIzEBAgMEBQ== ------END OPENSSH PRIVATE KEY----- diff -ruN openssh-9.4p1/regress/unittests/sshkey/testdata/ecdsa_sk1-cert.fp openssh-9.4p1+x509-14.2.1/regress/unittests/sshkey/testdata/ecdsa_sk1-cert.fp --- openssh-9.4p1/regress/unittests/sshkey/testdata/ecdsa_sk1-cert.fp 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/unittests/sshkey/testdata/ecdsa_sk1-cert.fp 1970-01-01 02:00:00.000000000 +0200 @@ -1 +0,0 @@ -SHA256:Go7HO0CVPYG+BSDSk9ZUJBKGSrtBExp6obTa9iqzIUo diff -ruN openssh-9.4p1/regress/unittests/sshkey/testdata/ecdsa_sk1-cert.pub openssh-9.4p1+x509-14.2.1/regress/unittests/sshkey/testdata/ecdsa_sk1-cert.pub --- openssh-9.4p1/regress/unittests/sshkey/testdata/ecdsa_sk1-cert.pub 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/unittests/sshkey/testdata/ecdsa_sk1-cert.pub 1970-01-01 02:00:00.000000000 +0200 @@ -1 +0,0 @@ -sk-ecdsa-sha2-nistp256-cert-v01@openssh.com AAAAK3NrLWVjZHNhLXNoYTItbmlzdHAyNTYtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgE012YoSBE9hEC2FRzblcSx784JNo2A4g611A7I75YMMAAAAIbmlzdHAyNTYAAABBBGdVPkKOLUMZ7b6rZfS8BOHotic4NX4MmuyEmiuvkaeKlbb1F+5oNezRYHpcF6P104trNVEONCu1XX1CA7px+QUAAAAEc3NoOgAAAAAAAAAHAAAAAgAAAAZqdWxpdXMAAAASAAAABWhvc3QxAAAABWhvc3QyAAAAADaLg2AAAAAATR3h4AAAAAAAAAAAAAAAAAAAAGgAAAATZWNkc2Etc2hhMi1uaXN0cDI1NgAAAAhuaXN0cDI1NgAAAEEEAlTtPiWUHubBeCys4Xp0QF91dYARpkyqtCnzg10HRS+ZDgkMrSUvPPG+Ge8iqtnB951MBxDq9FqDFIkhQBYXDAAAAGQAAAATZWNkc2Etc2hhMi1uaXN0cDI1NgAAAEkAAAAhALY+eXRJjVGnMk38Sm5S+H5CloNq757ypsoxt+WYoadtAAAAIA42/mAhUfLij1GY7wl+OFrI+icB/t4tGiEUZmhx6Foo ECDSA-SK test key #1 diff -ruN openssh-9.4p1/regress/unittests/sshkey/testdata/ecdsa_sk1.fp openssh-9.4p1+x509-14.2.1/regress/unittests/sshkey/testdata/ecdsa_sk1.fp --- openssh-9.4p1/regress/unittests/sshkey/testdata/ecdsa_sk1.fp 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/unittests/sshkey/testdata/ecdsa_sk1.fp 1970-01-01 02:00:00.000000000 +0200 @@ -1 +0,0 @@ -SHA256:Go7HO0CVPYG+BSDSk9ZUJBKGSrtBExp6obTa9iqzIUo diff -ruN openssh-9.4p1/regress/unittests/sshkey/testdata/ecdsa_sk1.fp.bb openssh-9.4p1+x509-14.2.1/regress/unittests/sshkey/testdata/ecdsa_sk1.fp.bb --- openssh-9.4p1/regress/unittests/sshkey/testdata/ecdsa_sk1.fp.bb 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/unittests/sshkey/testdata/ecdsa_sk1.fp.bb 1970-01-01 02:00:00.000000000 +0200 @@ -1 +0,0 @@ -xovem-sacac-dageg-vovoc-symyz-bozal-cibiv-cyvat-vylyn-romib-hoxax diff -ruN openssh-9.4p1/regress/unittests/sshkey/testdata/ecdsa_sk1.pub openssh-9.4p1+x509-14.2.1/regress/unittests/sshkey/testdata/ecdsa_sk1.pub --- openssh-9.4p1/regress/unittests/sshkey/testdata/ecdsa_sk1.pub 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/unittests/sshkey/testdata/ecdsa_sk1.pub 1970-01-01 02:00:00.000000000 +0200 @@ -1 +0,0 @@ -sk-ecdsa-sha2-nistp256@openssh.com AAAAInNrLWVjZHNhLXNoYTItbmlzdHAyNTZAb3BlbnNzaC5jb20AAAAIbmlzdHAyNTYAAABBBGdVPkKOLUMZ7b6rZfS8BOHotic4NX4MmuyEmiuvkaeKlbb1F+5oNezRYHpcF6P104trNVEONCu1XX1CA7px+QUAAAAEc3NoOg== ECDSA-SK test key #1 diff -ruN openssh-9.4p1/regress/unittests/sshkey/testdata/ecdsa_sk1_pw openssh-9.4p1+x509-14.2.1/regress/unittests/sshkey/testdata/ecdsa_sk1_pw --- openssh-9.4p1/regress/unittests/sshkey/testdata/ecdsa_sk1_pw 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/unittests/sshkey/testdata/ecdsa_sk1_pw 1970-01-01 02:00:00.000000000 +0200 @@ -1,14 +0,0 @@ ------BEGIN OPENSSH PRIVATE KEY----- -b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jdHIAAAAGYmNyeXB0AAAAGAAAABB6vcJVx2 -cPc7yYRROup8VnAAAAEAAAAAEAAAB/AAAAInNrLWVjZHNhLXNoYTItbmlzdHAyNTZAb3Bl -bnNzaC5jb20AAAAIbmlzdHAyNTYAAABBBGdVPkKOLUMZ7b6rZfS8BOHotic4NX4MmuyEmi -uvkaeKlbb1F+5oNezRYHpcF6P104trNVEONCu1XX1CA7px+QUAAAAEc3NoOgAAAZBrvCxe -xFz0bvzXwaPhrUHBeNCoZy/wNKDx0kxlxUPuA+lgOvy5l3lT3yxxd0qj5PQB+NTcuz8AAE -1f7aSWQNZSifox3COsBGoHV9C8i+glcxiBKheAZD+EBnRGjG8kbcaLhuYDW/I39qNe8lHW -YSDjmvsT55Hy0IAtVRAXizDoXKNdFPTZisC67WyOSJ3ED7Fy4bfT4ApbvhoFTwjikZBEhy -LOad1sbJa4eT19TsskYfQdnJf8sjAmCMOZY4ZV0FiNW5XZOp8nIal1oyULPfzTAm6oaeFN -0ImCSU3U8h4wUQ8q/3XvBWtTKycZaoou0AwPoP0QN95Ywte7FHezNPb/n8KD7k0S6h9XAX -UcBeCe5NHyov/0ZzA2p737hzm3w+MXGOboTQMu8WFXeGh4m7QH2o8ZJdgBhM5JF17uii+Q -ppGoPWHf33MXwB3wxWmKZ0ua0f9AVLkQ2DfFszUoBJE/kcHRd4kj4Q4FWXeMBN0GoH8gdE -gRWIlxn2/FAOce/BFPzzdP87H0jwz7SdcuVO1L ------END OPENSSH PRIVATE KEY----- diff -ruN openssh-9.4p1/regress/unittests/sshkey/testdata/ecdsa_sk2 openssh-9.4p1+x509-14.2.1/regress/unittests/sshkey/testdata/ecdsa_sk2 --- openssh-9.4p1/regress/unittests/sshkey/testdata/ecdsa_sk2 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/unittests/sshkey/testdata/ecdsa_sk2 1970-01-01 02:00:00.000000000 +0200 @@ -1,13 +0,0 @@ ------BEGIN OPENSSH PRIVATE KEY----- -b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAfwAAACJzay1lY2 -RzYS1zaGEyLW5pc3RwMjU2QG9wZW5zc2guY29tAAAACG5pc3RwMjU2AAAAQQSTl+SR6rTg -lOZmcQkCtJ3Pd+lWinezo/gHk4oZdZcTQsmEYs766BlWGuB2Bz3qQRLa6cXsP+4K9kAjAJ -7zdoFUAAAABHNzaDoAAAGQ1qllJtapZSYAAAAic2stZWNkc2Etc2hhMi1uaXN0cDI1NkBv -cGVuc3NoLmNvbQAAAAhuaXN0cDI1NgAAAEEEk5fkkeq04JTmZnEJArSdz3fpVop3s6P4B5 -OKGXWXE0LJhGLO+ugZVhrgdgc96kES2unF7D/uCvZAIwCe83aBVAAAAARzc2g6AQAAAOMt -LS0tLUJFR0lOIEVDIFBSSVZBVEUgS0VZLS0tLS0KTUhjQ0FRRUVJSkxwVkxnSTVvdkRlOW -VMWmZodCs5WWlMaitnam0rTXhHTXg5NndiRWw0Wm9Bb0dDQ3FHU000OQpBd0VIb1VRRFFn -QUVrNWZra2VxMDRKVG1abkVKQXJTZHozZnBWb3AzczZQNEI1T0tHWFdYRTBMSmhHTE8rdW -daClZocmdkZ2M5NmtFUzJ1bkY3RC91Q3ZaQUl3Q2U4M2FCVkE9PQotLS0tLUVORCBFQyBQ -UklWQVRFIEtFWS0tLS0tCgAAAAAAAAAURUNEU0EtU0sgdGVzdCBrZXkgIzIBAgMEBQ== ------END OPENSSH PRIVATE KEY----- diff -ruN openssh-9.4p1/regress/unittests/sshkey/testdata/ecdsa_sk2.fp openssh-9.4p1+x509-14.2.1/regress/unittests/sshkey/testdata/ecdsa_sk2.fp --- openssh-9.4p1/regress/unittests/sshkey/testdata/ecdsa_sk2.fp 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/unittests/sshkey/testdata/ecdsa_sk2.fp 1970-01-01 02:00:00.000000000 +0200 @@ -1 +0,0 @@ -SHA256:pz8VkgtRY3r50F4zSuzRlmq9c6vPTpJXLKKOgkyUcKE diff -ruN openssh-9.4p1/regress/unittests/sshkey/testdata/ecdsa_sk2.fp.bb openssh-9.4p1+x509-14.2.1/regress/unittests/sshkey/testdata/ecdsa_sk2.fp.bb --- openssh-9.4p1/regress/unittests/sshkey/testdata/ecdsa_sk2.fp.bb 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/unittests/sshkey/testdata/ecdsa_sk2.fp.bb 1970-01-01 02:00:00.000000000 +0200 @@ -1 +0,0 @@ -xobel-gavur-gorym-pedop-rarob-bunek-gucer-lofeg-syhaf-fylur-zoxix diff -ruN openssh-9.4p1/regress/unittests/sshkey/testdata/ecdsa_sk2.pub openssh-9.4p1+x509-14.2.1/regress/unittests/sshkey/testdata/ecdsa_sk2.pub --- openssh-9.4p1/regress/unittests/sshkey/testdata/ecdsa_sk2.pub 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/unittests/sshkey/testdata/ecdsa_sk2.pub 1970-01-01 02:00:00.000000000 +0200 @@ -1 +0,0 @@ -sk-ecdsa-sha2-nistp256@openssh.com AAAAInNrLWVjZHNhLXNoYTItbmlzdHAyNTZAb3BlbnNzaC5jb20AAAAIbmlzdHAyNTYAAABBBJOX5JHqtOCU5mZxCQK0nc936VaKd7Oj+AeTihl1lxNCyYRizvroGVYa4HYHPepBEtrpxew/7gr2QCMAnvN2gVQAAAAEc3NoOg== ECDSA-SK test key #2 diff -ruN openssh-9.4p1/regress/unittests/sshkey/testdata/ed25519_sk1 openssh-9.4p1+x509-14.2.1/regress/unittests/sshkey/testdata/ed25519_sk1 --- openssh-9.4p1/regress/unittests/sshkey/testdata/ed25519_sk1 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/unittests/sshkey/testdata/ed25519_sk1 1970-01-01 02:00:00.000000000 +0200 @@ -1,8 +0,0 @@ ------BEGIN OPENSSH PRIVATE KEY----- -b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAASgAAABpzay1zc2 -gtZWQyNTUxOUBvcGVuc3NoLmNvbQAAACAhaP5OS1PPOt7uumAvXlDtte9EHbqIT1EZEJ2y -2v3XMwAAAARzc2g6AAAAuBocY6UaHGOlAAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY2 -9tAAAAICFo/k5LU8863u66YC9eUO2170QduohPURkQnbLa/dczAAAABHNzaDoBAAAAQJYq -lGHhFoA25/q8X/rdTqDAb7dhqs4ehhd/w8x99CwiIWj+TktTzzre7rpgL15Q7bXvRB26iE -9RGRCdstr91zMAAAAAAAAAFkVEMjU1MTktU0sgdGVzdCBrZXkgIzEBAgM= ------END OPENSSH PRIVATE KEY----- diff -ruN openssh-9.4p1/regress/unittests/sshkey/testdata/ed25519_sk1-cert.fp openssh-9.4p1+x509-14.2.1/regress/unittests/sshkey/testdata/ed25519_sk1-cert.fp --- openssh-9.4p1/regress/unittests/sshkey/testdata/ed25519_sk1-cert.fp 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/unittests/sshkey/testdata/ed25519_sk1-cert.fp 1970-01-01 02:00:00.000000000 +0200 @@ -1 +0,0 @@ -SHA256:6WZVJ44bqhAWLVP4Ns0TDkoSQSsZo/h2K+mEvOaNFbw diff -ruN openssh-9.4p1/regress/unittests/sshkey/testdata/ed25519_sk1-cert.pub openssh-9.4p1+x509-14.2.1/regress/unittests/sshkey/testdata/ed25519_sk1-cert.pub --- openssh-9.4p1/regress/unittests/sshkey/testdata/ed25519_sk1-cert.pub 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/unittests/sshkey/testdata/ed25519_sk1-cert.pub 1970-01-01 02:00:00.000000000 +0200 @@ -1 +0,0 @@ -sk-ssh-ed25519-cert-v01@openssh.com AAAAI3NrLXNzaC1lZDI1NTE5LWNlcnQtdjAxQG9wZW5zc2guY29tAAAAIJr7CuMntQKvHoUshx374fJLFEkyxKsEOBA1H6hk5scoAAAAICFo/k5LU8863u66YC9eUO2170QduohPURkQnbLa/dczAAAABHNzaDoAAAAAAAAACAAAAAIAAAAGanVsaXVzAAAAEgAAAAVob3N0MQAAAAVob3N0MgAAAAA2i4NgAAAAAE0d4eAAAAAAAAAAAAAAAAAAAAAzAAAAC3NzaC1lZDI1NTE5AAAAIOo/0xneV3iM2qWEo5RUwvUYa2bjff292T5vvuXRomGQAAAAUwAAAAtzc2gtZWQyNTUxOQAAAECgsRGLDh1SI3m66MRp9D2iLP4wabQ0OrDgGidk7LsVn2XZHV5jBZN1RtNfe6PBMeVzfRtGUzOg18sO7H7uU+EC ED25519-SK test key #1 diff -ruN openssh-9.4p1/regress/unittests/sshkey/testdata/ed25519_sk1.fp openssh-9.4p1+x509-14.2.1/regress/unittests/sshkey/testdata/ed25519_sk1.fp --- openssh-9.4p1/regress/unittests/sshkey/testdata/ed25519_sk1.fp 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/unittests/sshkey/testdata/ed25519_sk1.fp 1970-01-01 02:00:00.000000000 +0200 @@ -1 +0,0 @@ -SHA256:6WZVJ44bqhAWLVP4Ns0TDkoSQSsZo/h2K+mEvOaNFbw diff -ruN openssh-9.4p1/regress/unittests/sshkey/testdata/ed25519_sk1.fp.bb openssh-9.4p1+x509-14.2.1/regress/unittests/sshkey/testdata/ed25519_sk1.fp.bb --- openssh-9.4p1/regress/unittests/sshkey/testdata/ed25519_sk1.fp.bb 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/unittests/sshkey/testdata/ed25519_sk1.fp.bb 1970-01-01 02:00:00.000000000 +0200 @@ -1 +0,0 @@ -xucac-vusip-tydoz-dudad-nerif-raran-tezun-cogyd-pamoh-bahef-ruxix diff -ruN openssh-9.4p1/regress/unittests/sshkey/testdata/ed25519_sk1.pub openssh-9.4p1+x509-14.2.1/regress/unittests/sshkey/testdata/ed25519_sk1.pub --- openssh-9.4p1/regress/unittests/sshkey/testdata/ed25519_sk1.pub 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/unittests/sshkey/testdata/ed25519_sk1.pub 1970-01-01 02:00:00.000000000 +0200 @@ -1 +0,0 @@ -sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAICFo/k5LU8863u66YC9eUO2170QduohPURkQnbLa/dczAAAABHNzaDo= ED25519-SK test key #1 diff -ruN openssh-9.4p1/regress/unittests/sshkey/testdata/ed25519_sk1_pw openssh-9.4p1+x509-14.2.1/regress/unittests/sshkey/testdata/ed25519_sk1_pw --- openssh-9.4p1/regress/unittests/sshkey/testdata/ed25519_sk1_pw 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/unittests/sshkey/testdata/ed25519_sk1_pw 1970-01-01 02:00:00.000000000 +0200 @@ -1,9 +0,0 @@ ------BEGIN OPENSSH PRIVATE KEY----- -b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jdHIAAAAGYmNyeXB0AAAAGAAAABDr5R9Yf/ -ucEh0Ns6c34tcIAAAAEAAAAAEAAABKAAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29t -AAAAICFo/k5LU8863u66YC9eUO2170QduohPURkQnbLa/dczAAAABHNzaDoAAADA2T6owx -OSgKz4DvLnS3UJ/renbuew5mbkIWB1/y8xd3y5Usm08iUCAlKxep9dVRQvmyoTrc/7rHOM -DkokNw+WgKambnlYT/9QfqViZ9iCBtbdmhLM6ksUCgQefvquRyXoJxlWstjXUll6Ru+ZbT -H//Ss8C1bYtAiXR68OQ+rhDrvQxA9P8J1sGIlkuV3h8YXddSpyBW2Sn0LTHHBXYZo86cXZ -G4Lnc8aGYm65eqdHgkfRmht3eS8DTdzEBfBNH5Ml ------END OPENSSH PRIVATE KEY----- diff -ruN openssh-9.4p1/regress/unittests/sshkey/testdata/ed25519_sk2 openssh-9.4p1+x509-14.2.1/regress/unittests/sshkey/testdata/ed25519_sk2 --- openssh-9.4p1/regress/unittests/sshkey/testdata/ed25519_sk2 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/unittests/sshkey/testdata/ed25519_sk2 1970-01-01 02:00:00.000000000 +0200 @@ -1,8 +0,0 @@ ------BEGIN OPENSSH PRIVATE KEY----- -b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAASgAAABpzay1zc2 -gtZWQyNTUxOUBvcGVuc3NoLmNvbQAAACAV8fu1Sc31QLK2R/zGPdN3ve5xuFvDc7mEAWxb -aI+YcwAAAARzc2g6AAAAuJCMX5uQjF+bAAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY2 -9tAAAAIBXx+7VJzfVAsrZH/MY903e97nG4W8NzuYQBbFtoj5hzAAAABHNzaDoBAAAAQObE -PajcKI1W30EKOhBb6u+Fgx464kf7EjnqDSg4l7gAFfH7tUnN9UCytkf8xj3Td73ucbhbw3 -O5hAFsW2iPmHMAAAAAAAAAFkVEMjU1MTktU0sgdGVzdCBrZXkgIzIBAgM= ------END OPENSSH PRIVATE KEY----- diff -ruN openssh-9.4p1/regress/unittests/sshkey/testdata/ed25519_sk2.fp openssh-9.4p1+x509-14.2.1/regress/unittests/sshkey/testdata/ed25519_sk2.fp --- openssh-9.4p1/regress/unittests/sshkey/testdata/ed25519_sk2.fp 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/unittests/sshkey/testdata/ed25519_sk2.fp 1970-01-01 02:00:00.000000000 +0200 @@ -1 +0,0 @@ -SHA256:b9BVPS5vuU4yu/FgweojLLg6zbfmBBoWLUgibdxxsoo diff -ruN openssh-9.4p1/regress/unittests/sshkey/testdata/ed25519_sk2.fp.bb openssh-9.4p1+x509-14.2.1/regress/unittests/sshkey/testdata/ed25519_sk2.fp.bb --- openssh-9.4p1/regress/unittests/sshkey/testdata/ed25519_sk2.fp.bb 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/unittests/sshkey/testdata/ed25519_sk2.fp.bb 1970-01-01 02:00:00.000000000 +0200 @@ -1 +0,0 @@ -xemac-tizim-dihep-supar-zupib-cukak-pasis-febeg-dyguv-hutec-dyxox diff -ruN openssh-9.4p1/regress/unittests/sshkey/testdata/ed25519_sk2.pub openssh-9.4p1+x509-14.2.1/regress/unittests/sshkey/testdata/ed25519_sk2.pub --- openssh-9.4p1/regress/unittests/sshkey/testdata/ed25519_sk2.pub 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/unittests/sshkey/testdata/ed25519_sk2.pub 1970-01-01 02:00:00.000000000 +0200 @@ -1 +0,0 @@ -sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIBXx+7VJzfVAsrZH/MY903e97nG4W8NzuYQBbFtoj5hzAAAABHNzaDo= ED25519-SK test key #2 diff -ruN openssh-9.4p1/regress/unittests/sshkey/test_file.c openssh-9.4p1+x509-14.2.1/regress/unittests/sshkey/test_file.c --- openssh-9.4p1/regress/unittests/sshkey/test_file.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/unittests/sshkey/test_file.c 2023-08-20 10:07:01.000000000 +0300 @@ -5,31 +5,21 @@ * Placed in the public domain */ -#include "includes.h" +#define OPENSSL_SUPPRESS_DEPRECATED /* TODO implement OpenSSL 3.1 API */ + +#include "../test_helper/test_helper.h" -#include #include #include #include -#ifdef HAVE_STDINT_H -#include -#endif #include #include #include #ifdef WITH_OPENSSL -#include -#include -#include -#include -#ifdef OPENSSL_HAS_NISTP256 -# include -#endif /* OPENSSL_HAS_NISTP256 */ +#include "evp-compat.h" #endif /* WITH_OPENSSL */ -#include "../test_helper/test_helper.h" - #include "ssherr.h" #include "authfile.h" #include "sshkey.h" @@ -38,6 +28,42 @@ #include "common.h" + +/* TODO: rewrite direct RSA tests */ +#ifndef HAVE_RSA_GET0_KEY +/* opaque RSA key structure */ +static inline void +RSA_get0_key(const RSA *rsa, const BIGNUM **n, const BIGNUM **e, const BIGNUM **d) { + if (n != NULL) *n = rsa->n; + if (e != NULL) *e = rsa->e; + if (d != NULL) *d = rsa->d; +} + +static inline void +RSA_get0_factors(const RSA *rsa, const BIGNUM **p, const BIGNUM **q) { + if (p != NULL) *p = rsa->p; + if (q != NULL) *q = rsa->q; +} +#endif /*ndef HAVE_RSA_GET0_KEY*/ + +/* TODO: rewrite direct DSA tests */ +#ifndef HAVE_DSA_GET0_KEY +/* opaque DSA key structure */ +static inline void +DSA_get0_key(const DSA *dsa, const BIGNUM **pub_key, const BIGNUM **priv_key) { + if (pub_key != NULL) *pub_key = dsa->pub_key; + if (priv_key != NULL) *priv_key = dsa->priv_key; +} + +static inline void +DSA_get0_pqg(const DSA *dsa, const BIGNUM **p, const BIGNUM **q, const BIGNUM **g) { + if (p != NULL) *p = dsa->p; + if (q != NULL) *q = dsa->q; + if (g != NULL) *g = dsa->g; +} +#endif /*ndef HAVE_DSA_GET0_KEY*/ + + void sshkey_file_tests(void); void @@ -54,7 +80,6 @@ pw = load_text_file("pw"); TEST_DONE(); - #ifdef WITH_OPENSSL TEST_START("parse RSA from private"); buf = load_file("rsa_1"); @@ -64,9 +89,20 @@ a = load_bignum("rsa_1.param.n"); b = load_bignum("rsa_1.param.p"); c = load_bignum("rsa_1.param.q"); - ASSERT_BIGNUM_EQ(rsa_n(k1), a); - ASSERT_BIGNUM_EQ(rsa_p(k1), b); - ASSERT_BIGNUM_EQ(rsa_q(k1), c); +{ + const BIGNUM *n = NULL, *p = NULL, *q = NULL; + RSA *rsa = EVP_PKEY_get1_RSA(k1->pk); + + ASSERT_PTR_NE(rsa, NULL); + RSA_get0_key(rsa, &n, NULL, NULL); + RSA_get0_factors(rsa, &p, &q); + + ASSERT_BIGNUM_EQ(n, a); + ASSERT_BIGNUM_EQ(p, b); + ASSERT_BIGNUM_EQ(q, c); + + RSA_free(rsa); +} BN_free(a); BN_free(b); BN_free(c); @@ -118,6 +154,7 @@ sshkey_free(k2); TEST_DONE(); +#ifdef HAVE_EVP_SHA256 TEST_START("load RSA cert with SHA512 signature"); ASSERT_INT_EQ(sshkey_load_cert(test_data_file("rsa_1_sha512"), &k2), 0); ASSERT_PTR_NE(k2, NULL); @@ -126,6 +163,7 @@ ASSERT_STRING_EQ(k2->cert->signature_type, "rsa-sha2-512"); sshkey_free(k2); TEST_DONE(); +#endif /*def HAVE_EVP_SHA256*/ TEST_START("load RSA cert"); ASSERT_INT_EQ(sshkey_load_cert(test_data_file("rsa_1"), &k2), 0); @@ -135,6 +173,7 @@ ASSERT_INT_EQ(sshkey_equal_public(k1, k2), 1); TEST_DONE(); +#ifdef HAVE_EVP_SHA256 TEST_START("RSA key hex fingerprint"); buf = load_text_file("rsa_1.fp"); cp = sshkey_fingerprint(k1, SSH_DIGEST_SHA256, SSH_FP_BASE64); @@ -143,7 +182,9 @@ sshbuf_free(buf); free(cp); TEST_DONE(); +#endif /*def HAVE_EVP_SHA256*/ +#ifdef HAVE_EVP_SHA256 TEST_START("RSA cert hex fingerprint"); buf = load_text_file("rsa_1-cert.fp"); cp = sshkey_fingerprint(k2, SSH_DIGEST_SHA256, SSH_FP_BASE64); @@ -153,6 +194,7 @@ free(cp); sshkey_free(k2); TEST_DONE(); +#endif /*def HAVE_EVP_SHA256*/ TEST_START("RSA key bubblebabble fingerprint"); buf = load_text_file("rsa_1.fp.bb"); @@ -173,9 +215,20 @@ a = load_bignum("dsa_1.param.g"); b = load_bignum("dsa_1.param.priv"); c = load_bignum("dsa_1.param.pub"); - ASSERT_BIGNUM_EQ(dsa_g(k1), a); - ASSERT_BIGNUM_EQ(dsa_priv_key(k1), b); - ASSERT_BIGNUM_EQ(dsa_pub_key(k1), c); +{ + const BIGNUM *g = NULL, *pub_key = NULL, *priv_key = NULL; + DSA *dsa = EVP_PKEY_get1_DSA(k1->pk); + + ASSERT_PTR_NE(dsa, NULL); + DSA_get0_pqg(dsa, NULL, NULL, &g); + DSA_get0_key(dsa, &pub_key, &priv_key); + + ASSERT_BIGNUM_EQ(g, a); + ASSERT_BIGNUM_EQ(priv_key, b); + ASSERT_BIGNUM_EQ(pub_key, c); + + DSA_free(dsa); +} BN_free(a); BN_free(b); BN_free(c); @@ -226,6 +279,7 @@ ASSERT_INT_EQ(sshkey_equal_public(k1, k2), 1); TEST_DONE(); +#ifdef HAVE_EVP_SHA256 TEST_START("DSA key hex fingerprint"); buf = load_text_file("dsa_1.fp"); cp = sshkey_fingerprint(k1, SSH_DIGEST_SHA256, SSH_FP_BASE64); @@ -234,7 +288,9 @@ sshbuf_free(buf); free(cp); TEST_DONE(); +#endif /*def HAVE_EVP_SHA256*/ +#ifdef HAVE_EVP_SHA256 TEST_START("DSA cert hex fingerprint"); buf = load_text_file("dsa_1-cert.fp"); cp = sshkey_fingerprint(k2, SSH_DIGEST_SHA256, SSH_FP_BASE64); @@ -244,6 +300,7 @@ free(cp); sshkey_free(k2); TEST_DONE(); +#endif /*def HAVE_EVP_SHA256*/ TEST_START("DSA key bubblebabble fingerprint"); buf = load_text_file("dsa_1.fp.bb"); @@ -266,19 +323,28 @@ ASSERT_STRING_EQ((const char *)sshbuf_ptr(buf), OBJ_nid2sn(k1->ecdsa_nid)); sshbuf_free(buf); -#ifndef OPENSSL_IS_BORINGSSL /* lacks EC_POINT_point2bn() */ a = load_bignum("ecdsa_1.param.priv"); b = load_bignum("ecdsa_1.param.pub"); - c = EC_POINT_point2bn(EC_KEY_get0_group(k1->ecdsa), - EC_KEY_get0_public_key(k1->ecdsa), POINT_CONVERSION_UNCOMPRESSED, - NULL, NULL); +{ + const EC_GROUP *ec_group; + const EC_POINT *ec_pub; + const BIGNUM *ec_priv; + EC_KEY *ec = EVP_PKEY_get1_EC_KEY(k1->pk); + + ASSERT_PTR_NE(ec, NULL); + ec_group = EC_KEY_get0_group(ec); + ec_pub = EC_KEY_get0_public_key(ec); + ec_priv = EC_KEY_get0_private_key(ec); + + c = EC_POINT_point2bn(ec_group, ec_pub, POINT_CONVERSION_UNCOMPRESSED, NULL, NULL); ASSERT_PTR_NE(c, NULL); - ASSERT_BIGNUM_EQ(EC_KEY_get0_private_key(k1->ecdsa), a); + ASSERT_BIGNUM_EQ(ec_priv, a); ASSERT_BIGNUM_EQ(b, c); + EC_KEY_free(ec); +} BN_free(a); BN_free(b); BN_free(c); -#endif /* OPENSSL_IS_BORINGSSL */ TEST_DONE(); TEST_START("parse ECDSA from private w/ passphrase"); @@ -326,6 +392,7 @@ ASSERT_INT_EQ(sshkey_equal_public(k1, k2), 1); TEST_DONE(); +#ifdef HAVE_EVP_SHA256 TEST_START("ECDSA key hex fingerprint"); buf = load_text_file("ecdsa_1.fp"); cp = sshkey_fingerprint(k1, SSH_DIGEST_SHA256, SSH_FP_BASE64); @@ -334,7 +401,9 @@ sshbuf_free(buf); free(cp); TEST_DONE(); +#endif /*def HAVE_EVP_SHA256*/ +#ifdef HAVE_EVP_SHA256 TEST_START("ECDSA cert hex fingerprint"); buf = load_text_file("ecdsa_1-cert.fp"); cp = sshkey_fingerprint(k2, SSH_DIGEST_SHA256, SSH_FP_BASE64); @@ -344,6 +413,7 @@ free(cp); sshkey_free(k2); TEST_DONE(); +#endif /*def HAVE_EVP_SHA256*/ TEST_START("ECDSA key bubblebabble fingerprint"); buf = load_text_file("ecdsa_1.fp.bb"); @@ -393,6 +463,7 @@ ASSERT_INT_EQ(sshkey_equal_public(k1, k2), 1); TEST_DONE(); +#ifdef HAVE_EVP_SHA256 TEST_START("Ed25519 key hex fingerprint"); buf = load_text_file("ed25519_1.fp"); cp = sshkey_fingerprint(k1, SSH_DIGEST_SHA256, SSH_FP_BASE64); @@ -401,7 +472,9 @@ sshbuf_free(buf); free(cp); TEST_DONE(); +#endif /*def HAVE_EVP_SHA256*/ +#ifdef HAVE_EVP_SHA256 TEST_START("Ed25519 cert hex fingerprint"); buf = load_text_file("ed25519_1-cert.fp"); cp = sshkey_fingerprint(k2, SSH_DIGEST_SHA256, SSH_FP_BASE64); @@ -411,6 +484,7 @@ free(cp); sshkey_free(k2); TEST_DONE(); +#endif /*def HAVE_EVP_SHA256*/ TEST_START("Ed25519 key bubblebabble fingerprint"); buf = load_text_file("ed25519_1.fp.bb"); @@ -423,139 +497,6 @@ sshkey_free(k1); -#ifdef ENABLE_SK -#if defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC) - TEST_START("parse ECDSA-SK from private"); - buf = load_file("ecdsa_sk1"); - ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0); - sshbuf_free(buf); - ASSERT_PTR_NE(k1, NULL); - ASSERT_INT_EQ(k1->type, KEY_ECDSA_SK); - TEST_DONE(); - - TEST_START("parse ECDSA-SK from private w/ passphrase"); - buf = load_file("ecdsa_sk1_pw"); - ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, - (const char *)sshbuf_ptr(pw), &k2, NULL), 0); - sshbuf_free(buf); - ASSERT_PTR_NE(k2, NULL); - ASSERT_INT_EQ(sshkey_equal(k1, k2), 1); - sshkey_free(k2); - TEST_DONE(); - - TEST_START("load ECDSA-SK from public"); - ASSERT_INT_EQ(sshkey_load_public(test_data_file("ecdsa_sk1.pub"), &k2, - NULL), 0); - ASSERT_PTR_NE(k2, NULL); - ASSERT_INT_EQ(sshkey_equal(k1, k2), 1); - sshkey_free(k2); - TEST_DONE(); - - TEST_START("load ECDSA-SK cert"); - ASSERT_INT_EQ(sshkey_load_cert(test_data_file("ecdsa_sk1"), &k2), 0); - ASSERT_PTR_NE(k2, NULL); - ASSERT_INT_EQ(k2->type, KEY_ECDSA_SK_CERT); - ASSERT_INT_EQ(sshkey_equal(k1, k2), 0); - ASSERT_INT_EQ(sshkey_equal_public(k1, k2), 1); - TEST_DONE(); - - TEST_START("ECDSA-SK key hex fingerprint"); - buf = load_text_file("ecdsa_sk1.fp"); - cp = sshkey_fingerprint(k1, SSH_DIGEST_SHA256, SSH_FP_BASE64); - ASSERT_PTR_NE(cp, NULL); - ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf)); - sshbuf_free(buf); - free(cp); - TEST_DONE(); - - TEST_START("ECDSA-SK cert hex fingerprint"); - buf = load_text_file("ecdsa_sk1-cert.fp"); - cp = sshkey_fingerprint(k2, SSH_DIGEST_SHA256, SSH_FP_BASE64); - ASSERT_PTR_NE(cp, NULL); - ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf)); - sshbuf_free(buf); - free(cp); - sshkey_free(k2); - TEST_DONE(); - - TEST_START("ECDSA-SK key bubblebabble fingerprint"); - buf = load_text_file("ecdsa_sk1.fp.bb"); - cp = sshkey_fingerprint(k1, SSH_DIGEST_SHA1, SSH_FP_BUBBLEBABBLE); - ASSERT_PTR_NE(cp, NULL); - ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf)); - sshbuf_free(buf); - free(cp); - TEST_DONE(); - - sshkey_free(k1); -#endif - - TEST_START("parse Ed25519-SK from private"); - buf = load_file("ed25519_sk1"); - ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0); - sshbuf_free(buf); - ASSERT_PTR_NE(k1, NULL); - ASSERT_INT_EQ(k1->type, KEY_ED25519_SK); - /* XXX check key contents */ - TEST_DONE(); - - TEST_START("parse Ed25519-SK from private w/ passphrase"); - buf = load_file("ed25519_sk1_pw"); - ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, - (const char *)sshbuf_ptr(pw), &k2, NULL), 0); - sshbuf_free(buf); - ASSERT_PTR_NE(k2, NULL); - ASSERT_INT_EQ(sshkey_equal(k1, k2), 1); - sshkey_free(k2); - TEST_DONE(); - - TEST_START("load Ed25519-SK from public"); - ASSERT_INT_EQ(sshkey_load_public(test_data_file("ed25519_sk1.pub"), - &k2, NULL), 0); - ASSERT_PTR_NE(k2, NULL); - ASSERT_INT_EQ(sshkey_equal(k1, k2), 1); - sshkey_free(k2); - TEST_DONE(); - - TEST_START("load Ed25519-SK cert"); - ASSERT_INT_EQ(sshkey_load_cert(test_data_file("ed25519_sk1"), &k2), 0); - ASSERT_PTR_NE(k2, NULL); - ASSERT_INT_EQ(k2->type, KEY_ED25519_SK_CERT); - ASSERT_INT_EQ(sshkey_equal(k1, k2), 0); - ASSERT_INT_EQ(sshkey_equal_public(k1, k2), 1); - TEST_DONE(); - - TEST_START("Ed25519-SK key hex fingerprint"); - buf = load_text_file("ed25519_sk1.fp"); - cp = sshkey_fingerprint(k1, SSH_DIGEST_SHA256, SSH_FP_BASE64); - ASSERT_PTR_NE(cp, NULL); - ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf)); - sshbuf_free(buf); - free(cp); - TEST_DONE(); - - TEST_START("Ed25519-SK cert hex fingerprint"); - buf = load_text_file("ed25519_sk1-cert.fp"); - cp = sshkey_fingerprint(k2, SSH_DIGEST_SHA256, SSH_FP_BASE64); - ASSERT_PTR_NE(cp, NULL); - ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf)); - sshbuf_free(buf); - free(cp); - sshkey_free(k2); - TEST_DONE(); - - TEST_START("Ed25519-SK key bubblebabble fingerprint"); - buf = load_text_file("ed25519_sk1.fp.bb"); - cp = sshkey_fingerprint(k1, SSH_DIGEST_SHA1, SSH_FP_BUBBLEBABBLE); - ASSERT_PTR_NE(cp, NULL); - ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf)); - sshbuf_free(buf); - free(cp); - TEST_DONE(); - - sshkey_free(k1); -#endif /* ENABLE_SK */ - sshbuf_free(pw); } diff -ruN openssh-9.4p1/regress/unittests/sshkey/test_fuzz.c openssh-9.4p1+x509-14.2.1/regress/unittests/sshkey/test_fuzz.c --- openssh-9.4p1/regress/unittests/sshkey/test_fuzz.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/unittests/sshkey/test_fuzz.c 2023-08-20 10:07:01.000000000 +0300 @@ -5,34 +5,19 @@ * Placed in the public domain */ -#include "includes.h" +#include "../test_helper/test_helper.h" -#include #include #include #include -#ifdef HAVE_STDINT_H -#include -#endif #include #include #include -#ifdef WITH_OPENSSL -#include -#include -#include -#include -#ifdef OPENSSL_HAS_NISTP256 -# include -#endif -#endif - -#include "../test_helper/test_helper.h" - #include "ssherr.h" #include "authfile.h" #include "sshkey.h" +#include "compat.h" #include "sshbuf.h" #include "common.h" @@ -82,25 +67,27 @@ size_t l; u_int fuzzers = FUZZ_1_BIT_FLIP | FUZZ_1_BYTE_FLIP | FUZZ_2_BYTE_FLIP | FUZZ_TRUNCATE_START | FUZZ_TRUNCATE_END; + ssh_compat ctx_compat = { 0, 0 }; + ssh_sign_ctx sctx = { sig_alg, k, &ctx_compat, NULL, NULL }; + ssh_verify_ctx vctx = { NULL, k, &ctx_compat }; if (test_is_fast()) fuzzers &= ~FUZZ_2_BYTE_FLIP; if (test_is_slow()) fuzzers |= FUZZ_2_BIT_FLIP; - ASSERT_INT_EQ(sshkey_sign(k, &sig, &l, c, sizeof(c), - sig_alg, NULL, NULL, 0), 0); + ASSERT_INT_EQ(sshkey_sign(&sctx, &sig, &l, c, sizeof(c)), 0); ASSERT_SIZE_T_GT(l, 0); fuzz = fuzz_begin(fuzzers, sig, l); - ASSERT_INT_EQ(sshkey_verify(k, sig, l, c, sizeof(c), NULL, 0, NULL), 0); + ASSERT_INT_EQ(sshkey_verify(&vctx, sig, l, c, sizeof(c)), 0); free(sig); TEST_ONERROR(onerror, fuzz); for(; !fuzz_done(fuzz); fuzz_next(fuzz)) { /* Ensure 1-bit difference at least */ if (fuzz_matches_original(fuzz)) continue; - ASSERT_INT_NE(sshkey_verify(k, fuzz_ptr(fuzz), fuzz_len(fuzz), - c, sizeof(c), NULL, 0, NULL), 0); + ASSERT_INT_NE(sshkey_verify(&vctx, fuzz_ptr(fuzz), fuzz_len(fuzz), + c, sizeof(c)), 0); } fuzz_cleanup(fuzz); } @@ -342,6 +329,7 @@ sshkey_free(k1); TEST_DONE(); +#ifdef HAVE_EVP_SHA256 TEST_START("fuzz RSA SHA256 sig"); buf = load_file("rsa_1"); ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0); @@ -349,7 +337,9 @@ sig_fuzz(k1, "rsa-sha2-256"); sshkey_free(k1); TEST_DONE(); +#endif /*def HAVE_EVP_SHA256*/ +#ifdef HAVE_EVP_SHA256 TEST_START("fuzz RSA SHA512 sig"); buf = load_file("rsa_1"); ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0); @@ -357,6 +347,7 @@ sig_fuzz(k1, "rsa-sha2-512"); sshkey_free(k1); TEST_DONE(); +#endif /*def HAVE_EVP_SHA256*/ TEST_START("fuzz DSA sig"); buf = load_file("dsa_1"); diff -ruN openssh-9.4p1/regress/unittests/sshkey/tests.c openssh-9.4p1+x509-14.2.1/regress/unittests/sshkey/tests.c --- openssh-9.4p1/regress/unittests/sshkey/tests.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/unittests/sshkey/tests.c 2023-08-20 10:07:01.000000000 +0300 @@ -5,9 +5,8 @@ * Placed in the public domain */ -#include "includes.h" - #include "../test_helper/test_helper.h" +#include "ssh_api.h" void sshkey_tests(void); void sshkey_file_tests(void); @@ -16,7 +15,11 @@ void tests(void) { + ssh_crypto_init(); + sshkey_tests(); sshkey_file_tests(); sshkey_fuzz_tests(); + + ssh_crypto_fini(); } diff -ruN openssh-9.4p1/regress/unittests/sshkey/test_sshkey.c openssh-9.4p1+x509-14.2.1/regress/unittests/sshkey/test_sshkey.c --- openssh-9.4p1/regress/unittests/sshkey/test_sshkey.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/unittests/sshkey/test_sshkey.c 2023-08-20 10:07:01.000000000 +0300 @@ -5,36 +5,62 @@ * Placed in the public domain */ -#include "includes.h" +#define SSHBUF_INTERNAL 1 /* access internals for testing */ +#define OPENSSL_SUPPRESS_DEPRECATED /* TODO implement OpenSSL 3.1 API */ + +#include "../test_helper/test_helper.h" -#include #include -#ifdef HAVE_STDINT_H -#include -#endif #include #include -#ifdef WITH_OPENSSL -#include -#include -#include -#if defined(OPENSSL_HAS_ECC) && defined(OPENSSL_HAS_NISTP256) -# include -#endif -#endif - -#include "../test_helper/test_helper.h" +#include "evp-compat.h" #include "ssherr.h" #include "sshbuf.h" -#define SSHBUF_INTERNAL 1 /* access internals for testing */ #include "sshkey.h" +#include "compat.h" #include "authfile.h" #include "common.h" #include "ssh2.h" + +/* TODO: rewrite or remove direct RSA tests */ +#ifndef HAVE_RSA_GET0_KEY +/* opaque RSA key structure */ +static inline void +RSA_get0_key(const RSA *rsa, const BIGNUM **n, const BIGNUM **e, const BIGNUM **d) { + if (n != NULL) *n = rsa->n; + if (e != NULL) *e = rsa->e; + if (d != NULL) *d = rsa->d; +} + +static inline void +RSA_get0_factors(const RSA *rsa, const BIGNUM **p, const BIGNUM **q) { + if (p != NULL) *p = rsa->p; + if (q != NULL) *q = rsa->q; +} +#endif /*ndef HAVE_RSA_GET0_KEY*/ + +/* TODO: rewrite or remove direct DSA tests */ +#ifndef HAVE_DSA_GET0_KEY +/* opaque DSA key structure */ +static inline void +DSA_get0_key(const DSA *dsa, const BIGNUM **pub_key, const BIGNUM **priv_key) { + if (pub_key != NULL) *pub_key = dsa->pub_key; + if (priv_key != NULL) *priv_key = dsa->priv_key; +} + +static inline void +DSA_get0_pqg(const DSA *dsa, const BIGNUM **p, const BIGNUM **q, const BIGNUM **g) { + if (p != NULL) *p = dsa->p; + if (q != NULL) *q = dsa->q; + if (g != NULL) *g = dsa->g; +} +#endif /*ndef HAVE_DSA_GET0_KEY*/ + + void sshkey_tests(void); static void @@ -101,8 +127,12 @@ ASSERT_INT_EQ(sshbuf_put_stringb(b, exts), 0); /* extensions */ ASSERT_INT_EQ(sshbuf_put_string(b, NULL, 0), 0); /* reserved */ ASSERT_INT_EQ(sshbuf_put_stringb(b, ca_buf), 0); /* signature key */ - ASSERT_INT_EQ(sshkey_sign(sign_key, &sigblob, &siglen, - sshbuf_ptr(b), sshbuf_len(b), sig_alg, NULL, NULL, 0), 0); +{ ssh_compat ctx_compat = { 0, 0 }; + ssh_sign_ctx ctx = { sig_alg, sign_key, &ctx_compat, NULL, NULL }; + + ASSERT_INT_EQ(sshkey_sign(&ctx, &sigblob, &siglen, + sshbuf_ptr(b), sshbuf_len(b)), 0); +} ASSERT_INT_EQ(sshbuf_put_string(b, sigblob, siglen), 0); /* signature */ free(sigblob); @@ -120,16 +150,19 @@ { size_t len; u_char *sig; + ssh_compat ctx_compat = { 0, 0 }; + ssh_sign_ctx sctx = { sig_alg, k, &ctx_compat, NULL, NULL }; + ssh_verify_ctx vctx = { NULL, k, &ctx_compat }; + ssh_verify_ctx vctxbad = { NULL, bad, &ctx_compat }; - ASSERT_INT_EQ(sshkey_sign(k, &sig, &len, d, l, sig_alg, - NULL, NULL, 0), 0); + ASSERT_INT_EQ(sshkey_sign(&sctx, &sig, &len, d, l), 0); ASSERT_SIZE_T_GT(len, 8); ASSERT_PTR_NE(sig, NULL); - ASSERT_INT_EQ(sshkey_verify(k, sig, len, d, l, NULL, 0, NULL), 0); - ASSERT_INT_NE(sshkey_verify(bad, sig, len, d, l, NULL, 0, NULL), 0); + ASSERT_INT_EQ(sshkey_verify(&vctx, sig, len, d, l), 0); + ASSERT_INT_NE(sshkey_verify(&vctxbad, sig, len, d, l), 0); /* Fuzz test is more comprehensive, this is just a smoke test */ sig[len - 5] ^= 0x10; - ASSERT_INT_NE(sshkey_verify(k, sig, len, d, l, NULL, 0, NULL), 0); + ASSERT_INT_NE(sshkey_verify(&vctx, sig, len, d, l), 0); free(sig); } @@ -204,14 +237,14 @@ TEST_START("new/free KEY_RSA"); k1 = sshkey_new(KEY_RSA); ASSERT_PTR_NE(k1, NULL); - ASSERT_PTR_NE(k1->rsa, NULL); + ASSERT_PTR_EQ(k1->pk, NULL); sshkey_free(k1); TEST_DONE(); TEST_START("new/free KEY_DSA"); k1 = sshkey_new(KEY_DSA); ASSERT_PTR_NE(k1, NULL); - ASSERT_PTR_NE(k1->dsa, NULL); + ASSERT_PTR_EQ(k1->pk, NULL); sshkey_free(k1); TEST_DONE(); @@ -219,7 +252,7 @@ TEST_START("new/free KEY_ECDSA"); k1 = sshkey_new(KEY_ECDSA); ASSERT_PTR_NE(k1, NULL); - ASSERT_PTR_EQ(k1->ecdsa, NULL); /* Can't allocate without NID */ + ASSERT_PTR_EQ(k1->pk, NULL); sshkey_free(k1); TEST_DONE(); #endif @@ -266,28 +299,62 @@ SSH_ERR_KEY_LENGTH); ASSERT_INT_EQ(sshkey_generate(KEY_RSA, 1024, &kr), 0); ASSERT_PTR_NE(kr, NULL); - ASSERT_PTR_NE(kr->rsa, NULL); - ASSERT_PTR_NE(rsa_n(kr), NULL); - ASSERT_PTR_NE(rsa_e(kr), NULL); - ASSERT_PTR_NE(rsa_p(kr), NULL); - ASSERT_INT_EQ(BN_num_bits(rsa_n(kr)), 1024); + ASSERT_PTR_NE(kr->pk, NULL); +{ + const BIGNUM *n = NULL, *e = NULL, *p = NULL; + RSA *rsa = EVP_PKEY_get1_RSA(kr->pk); + + ASSERT_PTR_NE(rsa, NULL); + RSA_get0_key(rsa, &n, &e, NULL); + RSA_get0_factors(rsa, &p, NULL); + + ASSERT_PTR_NE(n, NULL); + ASSERT_PTR_NE(e, NULL); + ASSERT_PTR_NE(p, NULL); + ASSERT_INT_EQ(BN_num_bits(n), 1024); + + RSA_free(rsa); +} TEST_DONE(); TEST_START("generate KEY_DSA"); ASSERT_INT_EQ(sshkey_generate(KEY_DSA, 1024, &kd), 0); ASSERT_PTR_NE(kd, NULL); - ASSERT_PTR_NE(kd->dsa, NULL); - ASSERT_PTR_NE(dsa_g(kd), NULL); - ASSERT_PTR_NE(dsa_priv_key(kd), NULL); + ASSERT_PTR_NE(kd->pk, NULL); +{ + const BIGNUM *g = NULL, *priv_key = NULL; + DSA *dsa = EVP_PKEY_get1_DSA(kd->pk); + + ASSERT_PTR_NE(dsa, NULL); + DSA_get0_pqg(dsa, NULL, NULL, &g); + DSA_get0_key(dsa, NULL, &priv_key); + + ASSERT_PTR_NE(g, NULL); + ASSERT_PTR_NE(priv_key, NULL); + + DSA_free(dsa); +} TEST_DONE(); #ifdef OPENSSL_HAS_ECC TEST_START("generate KEY_ECDSA"); ASSERT_INT_EQ(sshkey_generate(KEY_ECDSA, 256, &ke), 0); ASSERT_PTR_NE(ke, NULL); - ASSERT_PTR_NE(ke->ecdsa, NULL); - ASSERT_PTR_NE(EC_KEY_get0_public_key(ke->ecdsa), NULL); - ASSERT_PTR_NE(EC_KEY_get0_private_key(ke->ecdsa), NULL); + ASSERT_PTR_NE(ke->pk, NULL); +{ + const EC_POINT *ec_pub; + const BIGNUM *ec_priv; + EC_KEY *ec = EVP_PKEY_get1_EC_KEY(ke->pk); + + ASSERT_PTR_NE(ec, NULL); + ec_pub = EC_KEY_get0_public_key(ec); + ec_priv = EC_KEY_get0_private_key(ec); + + ASSERT_PTR_NE(ec_pub, NULL); + ASSERT_PTR_NE(ec_priv, NULL); + + EC_KEY_free(ec); +} TEST_DONE(); #endif /* OPENSSL_HAS_ECC */ #endif /* WITH_OPENSSL */ @@ -306,10 +373,21 @@ ASSERT_PTR_NE(k1, NULL); ASSERT_PTR_NE(kr, k1); ASSERT_INT_EQ(k1->type, KEY_RSA); - ASSERT_PTR_NE(k1->rsa, NULL); - ASSERT_PTR_NE(rsa_n(k1), NULL); - ASSERT_PTR_NE(rsa_e(k1), NULL); - ASSERT_PTR_EQ(rsa_p(k1), NULL); + ASSERT_PTR_NE(k1->pk, NULL); +{ + const BIGNUM *n = NULL, *e = NULL, *p = NULL; + RSA *rsa = EVP_PKEY_get1_RSA(k1->pk); + + ASSERT_PTR_NE(rsa, NULL); + RSA_get0_key(rsa, &n, &e, NULL); + RSA_get0_factors(rsa, &p, NULL); + + ASSERT_PTR_NE(n, NULL); + ASSERT_PTR_NE(e, NULL); + ASSERT_PTR_EQ(p, NULL); + + RSA_free(rsa); +} TEST_DONE(); TEST_START("equal KEY_RSA/demoted KEY_RSA"); @@ -322,9 +400,20 @@ ASSERT_PTR_NE(k1, NULL); ASSERT_PTR_NE(kd, k1); ASSERT_INT_EQ(k1->type, KEY_DSA); - ASSERT_PTR_NE(k1->dsa, NULL); - ASSERT_PTR_NE(dsa_g(k1), NULL); - ASSERT_PTR_EQ(dsa_priv_key(k1), NULL); + ASSERT_PTR_NE(k1->pk, NULL); +{ + const BIGNUM *g = NULL, *priv_key = NULL; + DSA *dsa = EVP_PKEY_get1_DSA(k1->pk); + + ASSERT_PTR_NE(dsa, NULL); + DSA_get0_pqg(dsa, NULL, NULL, &g); + DSA_get0_key(dsa, NULL, &priv_key); + + ASSERT_PTR_NE(g, NULL); + ASSERT_PTR_EQ(priv_key, NULL); + + DSA_free(dsa); +} TEST_DONE(); TEST_START("equal KEY_DSA/demoted KEY_DSA"); @@ -338,10 +427,22 @@ ASSERT_PTR_NE(k1, NULL); ASSERT_PTR_NE(ke, k1); ASSERT_INT_EQ(k1->type, KEY_ECDSA); - ASSERT_PTR_NE(k1->ecdsa, NULL); + ASSERT_PTR_NE(k1->pk, NULL); +{ + const EC_POINT *ec_pub; + const BIGNUM *ec_priv; + EC_KEY *ec = EVP_PKEY_get1_EC_KEY(k1->pk); + + ASSERT_PTR_NE(ec, NULL); + ec_pub = EC_KEY_get0_public_key(ec); + ec_priv = EC_KEY_get0_private_key(ec); + ASSERT_INT_EQ(k1->ecdsa_nid, ke->ecdsa_nid); - ASSERT_PTR_NE(EC_KEY_get0_public_key(ke->ecdsa), NULL); - ASSERT_PTR_EQ(EC_KEY_get0_private_key(k1->ecdsa), NULL); + ASSERT_PTR_NE(ec_pub, NULL); + ASSERT_PTR_EQ(ec_priv, NULL); + + EC_KEY_free(ec); +} TEST_DONE(); TEST_START("equal KEY_ECDSA/demoted KEY_ECDSA"); @@ -461,6 +562,7 @@ sshkey_free(k2); TEST_DONE(); +#ifdef HAVE_EVP_SHA256 TEST_START("sign and verify RSA-SHA256"); k1 = get_private("rsa_1"); ASSERT_INT_EQ(sshkey_load_public(test_data_file("rsa_2.pub"), &k2, @@ -469,7 +571,9 @@ sshkey_free(k1); sshkey_free(k2); TEST_DONE(); +#endif /*def HAVE_EVP_SHA256*/ +#ifdef HAVE_EVP_SHA256 TEST_START("sign and verify RSA-SHA512"); k1 = get_private("rsa_1"); ASSERT_INT_EQ(sshkey_load_public(test_data_file("rsa_2.pub"), &k2, @@ -478,6 +582,7 @@ sshkey_free(k1); sshkey_free(k2); TEST_DONE(); +#endif /*def HAVE_EVP_SHA256*/ TEST_START("sign and verify DSA"); k1 = get_private("dsa_1"); @@ -488,16 +593,17 @@ sshkey_free(k2); TEST_DONE(); -#ifdef OPENSSL_HAS_ECC +#ifdef OPENSSL_HAS_NISTP521 /* implies OPENSSL_HAS_ECC */ TEST_START("sign and verify ECDSA"); k1 = get_private("ecdsa_1"); + /*k2 is ecdsa-sha2-nistp521!*/ ASSERT_INT_EQ(sshkey_load_public(test_data_file("ecdsa_2.pub"), &k2, NULL), 0); signature_tests(k1, k2, NULL); sshkey_free(k1); sshkey_free(k2); TEST_DONE(); -#endif /* OPENSSL_HAS_ECC */ +#endif /* OPENSSL_HAS_NISTP521 */ #endif /* WITH_OPENSSL */ TEST_START("sign and verify ED25519"); diff -ruN openssh-9.4p1/regress/unittests/sshsig/Makefile openssh-9.4p1+x509-14.2.1/regress/unittests/sshsig/Makefile --- openssh-9.4p1/regress/unittests/sshsig/Makefile 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/unittests/sshsig/Makefile 1970-01-01 02:00:00.000000000 +0200 @@ -1,25 +0,0 @@ -# $OpenBSD: Makefile,v 1.3 2023/01/15 23:35:10 djm Exp $ - -PROG=test_sshsig -SRCS=tests.c - -# From usr.bin/ssh -SRCS+=sshbuf-getput-basic.c sshbuf-getput-crypto.c sshbuf-misc.c sshbuf.c -SRCS+=sshbuf-io.c atomicio.c sshkey.c authfile.c cipher.c log.c ssh-rsa.c -SRCS+=ssh-dss.c ssh-ecdsa.c ssh-ed25519.c mac.c umac.c umac128.c hmac.c misc.c -SRCS+=ssherr.c uidswap.c cleanup.c xmalloc.c match.c krl.c fatal.c -SRCS+=addr.c addrmatch.c bitmap.c sshsig.c -SRCS+=ed25519.c hash.c -SRCS+=cipher-chachapoly.c chacha.c poly1305.c ssh-ecdsa-sk.c ssh-sk.c -SRCS+=ssh-ed25519-sk.c sk-usbhid.c - -SRCS+=digest-openssl.c -#SRCS+=digest-libc.c -SRCS+=utf8.c - -REGRESS_TARGETS=run-regress-${PROG} - -run-regress-${PROG}: ${PROG} - env ${TEST_ENV} ./${PROG} ${UNITTEST_ARGS} -d ${.CURDIR}/testdata - -.include diff -ruN openssh-9.4p1/regress/unittests/sshsig/mktestdata.sh openssh-9.4p1+x509-14.2.1/regress/unittests/sshsig/mktestdata.sh --- openssh-9.4p1/regress/unittests/sshsig/mktestdata.sh 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/unittests/sshsig/mktestdata.sh 1970-01-01 02:00:00.000000000 +0200 @@ -1,42 +0,0 @@ -#!/bin/sh -# $OpenBSD: mktestdata.sh,v 1.1 2020/06/19 04:32:09 djm Exp $ - -NAMESPACE=unittest - -set -ex - -cd testdata - -if [ -f ../../../misc/sk-dummy/sk-dummy.so ] ; then - SK_DUMMY=../../../misc/sk-dummy/sk-dummy.so -elif [ -f ../../../misc/sk-dummy/obj/sk-dummy.so ] ; then - SK_DUMMY=../../../misc/sk-dummy/obj/sk-dummy.so -else - echo "Can't find sk-dummy.so" 1>&2 - exit 1 -fi - -rm -f signed-data namespace -rm -f rsa dsa ecdsa ed25519 ecdsa_sk ed25519_sk -rm -f rsa.sig dsa.sig ecdsa.sig ed25519.sig ecdsa_sk.sig ed25519_sk.sig - -printf "This is a test, this is only a test" > signed-data -printf "$NAMESPACE" > namespace - -ssh-keygen -t rsa -C "RSA test" -N "" -f rsa -m PEM -ssh-keygen -t dsa -C "DSA test" -N "" -f dsa -m PEM -ssh-keygen -t ecdsa -C "ECDSA test" -N "" -f ecdsa -m PEM -ssh-keygen -t ed25519 -C "ED25519 test key" -N "" -f ed25519 -ssh-keygen -w "$SK_DUMMY" -t ecdsa-sk -C "ECDSA-SK test key" \ - -N "" -f ecdsa_sk -ssh-keygen -w "$SK_DUMMY" -t ed25519-sk -C "ED25519-SK test key" \ - -N "" -f ed25519_sk - -ssh-keygen -Y sign -f rsa -n $NAMESPACE - < signed-data > rsa.sig -ssh-keygen -Y sign -f dsa -n $NAMESPACE - < signed-data > dsa.sig -ssh-keygen -Y sign -f ecdsa -n $NAMESPACE - < signed-data > ecdsa.sig -ssh-keygen -Y sign -f ed25519 -n $NAMESPACE - < signed-data > ed25519.sig -ssh-keygen -w "$SK_DUMMY" \ - -Y sign -f ecdsa_sk -n $NAMESPACE - < signed-data > ecdsa_sk.sig -ssh-keygen -w "$SK_DUMMY" \ - -Y sign -f ed25519_sk -n $NAMESPACE - < signed-data > ed25519_sk.sig diff -ruN openssh-9.4p1/regress/unittests/sshsig/testdata/dsa openssh-9.4p1+x509-14.2.1/regress/unittests/sshsig/testdata/dsa --- openssh-9.4p1/regress/unittests/sshsig/testdata/dsa 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/unittests/sshsig/testdata/dsa 1970-01-01 02:00:00.000000000 +0200 @@ -1,12 +0,0 @@ ------BEGIN DSA PRIVATE KEY----- -MIIBuwIBAAKBgQCXpndQdz2mQVnk+lYOF3nxDT+h6SiJmUvBFhnFWBv8tG4pTOkb -EwGufLEzGpzjTj+3bjVau7LFt37AFrqs4Num272BWNsYNIjOlGPgq7Xjv32FN00x -JYh1DoRs1cGGnvohlsWEamGGhTHD1a9ipctPEBV+NrxtZMrl+pO/ZZg8vQIVAKJB -P3iNYSpSuW74+q4WxLCuK8O3AoGAQldE+BIuxlvoG1IFiWesx0CU+H2KO0SEZc9A -SX/qjOabh0Fb78ofTlEf9gWHFfat8SvSJQIOPMVlb76Lio8AAMT8Eaa/qQKKYmQL -dNq4MLhhjxx5KLGt6J2JyFPExCv+qnHYHD59ngtLwKyqGjpSC8LPLktdXn8W/Aad -Ly1K7+MCgYBsMHBczhSeUh8w7i20CVg4OlNTmfJRVU2tO6OpMxZ/quitRm3hLKSN -u4xRkvHJwi4LhQtv1SXvLI5gs5P3gCG8tsIAiyCqLinHha63iBdJpqhnV/x/j7dB -yJr3xJbnmLdWLkkCtNk1Ir1/CuEz+ufAyLGdKWksEAu1UUlb501BkwIVAILIa3Rg -0h7J9lQpHJphvF3K0M1T ------END DSA PRIVATE KEY----- diff -ruN openssh-9.4p1/regress/unittests/sshsig/testdata/dsa.pub openssh-9.4p1+x509-14.2.1/regress/unittests/sshsig/testdata/dsa.pub --- openssh-9.4p1/regress/unittests/sshsig/testdata/dsa.pub 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/unittests/sshsig/testdata/dsa.pub 1970-01-01 02:00:00.000000000 +0200 @@ -1 +0,0 @@ -ssh-dss AAAAB3NzaC1kc3MAAACBAJemd1B3PaZBWeT6Vg4XefENP6HpKImZS8EWGcVYG/y0bilM6RsTAa58sTManONOP7duNVq7ssW3fsAWuqzg26bbvYFY2xg0iM6UY+CrteO/fYU3TTEliHUOhGzVwYae+iGWxYRqYYaFMcPVr2Kly08QFX42vG1kyuX6k79lmDy9AAAAFQCiQT94jWEqUrlu+PquFsSwrivDtwAAAIBCV0T4Ei7GW+gbUgWJZ6zHQJT4fYo7RIRlz0BJf+qM5puHQVvvyh9OUR/2BYcV9q3xK9IlAg48xWVvvouKjwAAxPwRpr+pAopiZAt02rgwuGGPHHkosa3onYnIU8TEK/6qcdgcPn2eC0vArKoaOlILws8uS11efxb8Bp0vLUrv4wAAAIBsMHBczhSeUh8w7i20CVg4OlNTmfJRVU2tO6OpMxZ/quitRm3hLKSNu4xRkvHJwi4LhQtv1SXvLI5gs5P3gCG8tsIAiyCqLinHha63iBdJpqhnV/x/j7dByJr3xJbnmLdWLkkCtNk1Ir1/CuEz+ufAyLGdKWksEAu1UUlb501Bkw== DSA test diff -ruN openssh-9.4p1/regress/unittests/sshsig/testdata/dsa.sig openssh-9.4p1+x509-14.2.1/regress/unittests/sshsig/testdata/dsa.sig --- openssh-9.4p1/regress/unittests/sshsig/testdata/dsa.sig 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/unittests/sshsig/testdata/dsa.sig 1970-01-01 02:00:00.000000000 +0200 @@ -1,13 +0,0 @@ ------BEGIN SSH SIGNATURE----- -U1NIU0lHAAAAAQAAAbEAAAAHc3NoLWRzcwAAAIEAl6Z3UHc9pkFZ5PpWDhd58Q0/oekoiZ -lLwRYZxVgb/LRuKUzpGxMBrnyxMxqc404/t241Wruyxbd+wBa6rODbptu9gVjbGDSIzpRj -4Ku14799hTdNMSWIdQ6EbNXBhp76IZbFhGphhoUxw9WvYqXLTxAVfja8bWTK5fqTv2WYPL -0AAAAVAKJBP3iNYSpSuW74+q4WxLCuK8O3AAAAgEJXRPgSLsZb6BtSBYlnrMdAlPh9ijtE -hGXPQEl/6ozmm4dBW+/KH05RH/YFhxX2rfEr0iUCDjzFZW++i4qPAADE/BGmv6kCimJkC3 -TauDC4YY8ceSixreidichTxMQr/qpx2Bw+fZ4LS8Csqho6UgvCzy5LXV5/FvwGnS8tSu/j -AAAAgGwwcFzOFJ5SHzDuLbQJWDg6U1OZ8lFVTa07o6kzFn+q6K1GbeEspI27jFGS8cnCLg -uFC2/VJe8sjmCzk/eAIby2wgCLIKouKceFrreIF0mmqGdX/H+Pt0HImvfElueYt1YuSQK0 -2TUivX8K4TP658DIsZ0paSwQC7VRSVvnTUGTAAAACHVuaXR0ZXN0AAAAAAAAAAZzaGE1MT -IAAAA3AAAAB3NzaC1kc3MAAAAodi5lr0pqBpO76OY4N1CtfR85BCgZ95qfVjP/e9lToj0q -lwjSJJXUjw== ------END SSH SIGNATURE----- diff -ruN openssh-9.4p1/regress/unittests/sshsig/testdata/ecdsa openssh-9.4p1+x509-14.2.1/regress/unittests/sshsig/testdata/ecdsa --- openssh-9.4p1/regress/unittests/sshsig/testdata/ecdsa 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/unittests/sshsig/testdata/ecdsa 1970-01-01 02:00:00.000000000 +0200 @@ -1,5 +0,0 @@ ------BEGIN EC PRIVATE KEY----- -MHcCAQEEIFg0ZCSEB5LNeLsXYL25g3kqEWsqh52DR+yNOjyQJqyZoAoGCCqGSM49 -AwEHoUQDQgAE3sud88FV0N8FPspZSV7LWqj6uPPLRZiSsenNuEYAteWPyDgrZsWb -LzXBuUJucepaCNuW/QWgHBRbrjWj3ERm3A== ------END EC PRIVATE KEY----- diff -ruN openssh-9.4p1/regress/unittests/sshsig/testdata/ecdsa.pub openssh-9.4p1+x509-14.2.1/regress/unittests/sshsig/testdata/ecdsa.pub --- openssh-9.4p1/regress/unittests/sshsig/testdata/ecdsa.pub 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/unittests/sshsig/testdata/ecdsa.pub 1970-01-01 02:00:00.000000000 +0200 @@ -1 +0,0 @@ -ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBN7LnfPBVdDfBT7KWUley1qo+rjzy0WYkrHpzbhGALXlj8g4K2bFmy81wblCbnHqWgjblv0FoBwUW641o9xEZtw= ECDSA test diff -ruN openssh-9.4p1/regress/unittests/sshsig/testdata/ecdsa.sig openssh-9.4p1+x509-14.2.1/regress/unittests/sshsig/testdata/ecdsa.sig --- openssh-9.4p1/regress/unittests/sshsig/testdata/ecdsa.sig 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/unittests/sshsig/testdata/ecdsa.sig 1970-01-01 02:00:00.000000000 +0200 @@ -1,7 +0,0 @@ ------BEGIN SSH SIGNATURE----- -U1NIU0lHAAAAAQAAAGgAAAATZWNkc2Etc2hhMi1uaXN0cDI1NgAAAAhuaXN0cDI1NgAAAE -EE3sud88FV0N8FPspZSV7LWqj6uPPLRZiSsenNuEYAteWPyDgrZsWbLzXBuUJucepaCNuW -/QWgHBRbrjWj3ERm3AAAAAh1bml0dGVzdAAAAAAAAAAGc2hhNTEyAAAAZQAAABNlY2RzYS -1zaGEyLW5pc3RwMjU2AAAASgAAACEAycVNsTlE+XEZYyYiDxWZlliruf/pPMhEEMR/XLdQ -a4MAAAAhALQt+5gES7L3uKGptHB6UZQMuZ2WyI0C6FJs4v6AtMIU ------END SSH SIGNATURE----- diff -ruN openssh-9.4p1/regress/unittests/sshsig/testdata/ecdsa_sk openssh-9.4p1+x509-14.2.1/regress/unittests/sshsig/testdata/ecdsa_sk --- openssh-9.4p1/regress/unittests/sshsig/testdata/ecdsa_sk 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/unittests/sshsig/testdata/ecdsa_sk 1970-01-01 02:00:00.000000000 +0200 @@ -1,13 +0,0 @@ ------BEGIN OPENSSH PRIVATE KEY----- -b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAfwAAACJzay1lY2 -RzYS1zaGEyLW5pc3RwMjU2QG9wZW5zc2guY29tAAAACG5pc3RwMjU2AAAAQQSg1WuY0XE+ -VexOsrJsFYuxyVoe6eQ/oXmyz2pEHKZw9moyWehv+Fs7oZWFp3JVmOtybKQ6dvfUZYauQE -/Ov4PAAAAABHNzaDoAAAGI6iV41+oleNcAAAAic2stZWNkc2Etc2hhMi1uaXN0cDI1NkBv -cGVuc3NoLmNvbQAAAAhuaXN0cDI1NgAAAEEEoNVrmNFxPlXsTrKybBWLsclaHunkP6F5ss -9qRBymcPZqMlnob/hbO6GVhadyVZjrcmykOnb31GWGrkBPzr+DwAAAAARzc2g6AQAAAOMt -LS0tLUJFR0lOIEVDIFBSSVZBVEUgS0VZLS0tLS0KTUhjQ0FRRUVJQm9oeW54M2tpTFVEeS -t5UjU3WXBXSU5KektnU1p6WnV2VTljYXFla3JGcW9Bb0dDQ3FHU000OQpBd0VIb1VRRFFn -QUVvTlZybU5GeFBsWHNUckt5YkJXTHNjbGFIdW5rUDZGNXNzOXFSQnltY1BacU1sbm9iL2 -hiCk82R1ZoYWR5VlpqcmNteWtPbmIzMUdXR3JrQlB6citEd0E9PQotLS0tLUVORCBFQyBQ -UklWQVRFIEtFWS0tLS0tCgAAAAAAAAARRUNEU0EtU0sgdGVzdCBrZXk= ------END OPENSSH PRIVATE KEY----- diff -ruN openssh-9.4p1/regress/unittests/sshsig/testdata/ecdsa_sk.pub openssh-9.4p1+x509-14.2.1/regress/unittests/sshsig/testdata/ecdsa_sk.pub --- openssh-9.4p1/regress/unittests/sshsig/testdata/ecdsa_sk.pub 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/unittests/sshsig/testdata/ecdsa_sk.pub 1970-01-01 02:00:00.000000000 +0200 @@ -1 +0,0 @@ -sk-ecdsa-sha2-nistp256@openssh.com AAAAInNrLWVjZHNhLXNoYTItbmlzdHAyNTZAb3BlbnNzaC5jb20AAAAIbmlzdHAyNTYAAABBBKDVa5jRcT5V7E6ysmwVi7HJWh7p5D+hebLPakQcpnD2ajJZ6G/4WzuhlYWnclWY63JspDp299Rlhq5AT86/g8AAAAAEc3NoOg== ECDSA-SK test key diff -ruN openssh-9.4p1/regress/unittests/sshsig/testdata/ecdsa_sk.sig openssh-9.4p1+x509-14.2.1/regress/unittests/sshsig/testdata/ecdsa_sk.sig --- openssh-9.4p1/regress/unittests/sshsig/testdata/ecdsa_sk.sig 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/unittests/sshsig/testdata/ecdsa_sk.sig 1970-01-01 02:00:00.000000000 +0200 @@ -1,8 +0,0 @@ ------BEGIN SSH SIGNATURE----- -U1NIU0lHAAAAAQAAAH8AAAAic2stZWNkc2Etc2hhMi1uaXN0cDI1NkBvcGVuc3NoLmNvbQ -AAAAhuaXN0cDI1NgAAAEEEoNVrmNFxPlXsTrKybBWLsclaHunkP6F5ss9qRBymcPZqMlno -b/hbO6GVhadyVZjrcmykOnb31GWGrkBPzr+DwAAAAARzc2g6AAAACHVuaXR0ZXN0AAAAAA -AAAAZzaGE1MTIAAAB3AAAAInNrLWVjZHNhLXNoYTItbmlzdHAyNTZAb3BlbnNzaC5jb20A -AABIAAAAIHohGwyy8iKT3zwd1TYA9V/Ioo7h/3zCJUtyq/Qigt/HAAAAIGzidTwq7D/kFa -7Xjcp/KkdbIs4MfQpfAW/0OciajlpzARI0Vng= ------END SSH SIGNATURE----- diff -ruN openssh-9.4p1/regress/unittests/sshsig/testdata/ecdsa_sk_webauthn.pub openssh-9.4p1+x509-14.2.1/regress/unittests/sshsig/testdata/ecdsa_sk_webauthn.pub --- openssh-9.4p1/regress/unittests/sshsig/testdata/ecdsa_sk_webauthn.pub 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/unittests/sshsig/testdata/ecdsa_sk_webauthn.pub 1970-01-01 02:00:00.000000000 +0200 @@ -1 +0,0 @@ -sk-ecdsa-sha2-nistp256@openssh.com AAAAInNrLWVjZHNhLXNoYTItbmlzdHAyNTZAb3BlbnNzaC5jb20AAAAIbmlzdHAyNTYAAABBBBRGwDjs4HhJFcn4tJ5Gr72KcmRmCS1OirETxaXvnsNApgoOLF1a/7rxldfSMHm73eT1nhHe97W8qicPPEAKDJQAAAALbWluZHJvdC5vcmc= diff -ruN openssh-9.4p1/regress/unittests/sshsig/testdata/ecdsa_sk_webauthn.sig openssh-9.4p1+x509-14.2.1/regress/unittests/sshsig/testdata/ecdsa_sk_webauthn.sig --- openssh-9.4p1/regress/unittests/sshsig/testdata/ecdsa_sk_webauthn.sig 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/unittests/sshsig/testdata/ecdsa_sk_webauthn.sig 1970-01-01 02:00:00.000000000 +0200 @@ -1,13 +0,0 @@ ------BEGIN SSH SIGNATURE----- -U1NIU0lHAAAAAQAAAIYAAAAic2stZWNkc2Etc2hhMi1uaXN0cDI1NkBvcGVuc3NoLmNvbQ -AAAAhuaXN0cDI1NgAAAEEEFEbAOOzgeEkVyfi0nkavvYpyZGYJLU6KsRPFpe+ew0CmCg4s -XVr/uvGV19Iwebvd5PWeEd73tbyqJw88QAoMlAAAAAttaW5kcm90Lm9yZwAAAAh1bml0dG -VzdAAAAAAAAAAGc2hhNTEyAAABhwAAACt3ZWJhdXRobi1zay1lY2RzYS1zaGEyLW5pc3Rw -MjU2QG9wZW5zc2guY29tAAAASQAAACBj2oMT9tb5wRXe6mdmf4/lgAO8wrgr95ouozwNg4 -itnQAAACEAtU9g5wz3HchUiLfLD6plr9T4TiJ32lVCrATSjpiy0SMBAAADHwAAABdodHRw -czovL3d3dy5taW5kcm90Lm9yZwAAAON7InR5cGUiOiJ3ZWJhdXRobi5nZXQiLCJjaGFsbG -VuZ2UiOiJVMU5JVTBsSEFBQUFDSFZ1YVhSMFpYTjBBQUFBQUFBQUFBWnphR0UxTVRJQUFB -QkFMTHU4WmdjU3h0Nk1zRlV6dWlaZ0c2R3dNZEo5ZDd4ZUU3WW9SSXcwZzlpSEpfd3NGRD -cxbzRXbHllenZGV0VqYnFRMHFDN0Z3R3Bqa2pVUVAtTmQ2dyIsIm9yaWdpbiI6Imh0dHBz -Oi8vd3d3Lm1pbmRyb3Qub3JnIiwiY3Jvc3NPcmlnaW4iOmZhbHNlfQAAAAA= ------END SSH SIGNATURE----- diff -ruN openssh-9.4p1/regress/unittests/sshsig/testdata/ed25519 openssh-9.4p1+x509-14.2.1/regress/unittests/sshsig/testdata/ed25519 --- openssh-9.4p1/regress/unittests/sshsig/testdata/ed25519 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/unittests/sshsig/testdata/ed25519 1970-01-01 02:00:00.000000000 +0200 @@ -1,7 +0,0 @@ ------BEGIN OPENSSH PRIVATE KEY----- -b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW -QyNTUxOQAAACCJYs0iDdw0Fe/FTzY1b78I4H/j+R6mz2AmLtwTjHYwBAAAAJjpGas/6Rmr -PwAAAAtzc2gtZWQyNTUxOQAAACCJYs0iDdw0Fe/FTzY1b78I4H/j+R6mz2AmLtwTjHYwBA -AAAEDpSKRA1QKW6kYiQftGRWh+H0fNekzYLG6c3bzseoCpEolizSIN3DQV78VPNjVvvwjg -f+P5HqbPYCYu3BOMdjAEAAAAEEVEMjU1MTkgdGVzdCBrZXkBAgMEBQ== ------END OPENSSH PRIVATE KEY----- diff -ruN openssh-9.4p1/regress/unittests/sshsig/testdata/ed25519.pub openssh-9.4p1+x509-14.2.1/regress/unittests/sshsig/testdata/ed25519.pub --- openssh-9.4p1/regress/unittests/sshsig/testdata/ed25519.pub 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/unittests/sshsig/testdata/ed25519.pub 1970-01-01 02:00:00.000000000 +0200 @@ -1 +0,0 @@ -ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIlizSIN3DQV78VPNjVvvwjgf+P5HqbPYCYu3BOMdjAE ED25519 test key diff -ruN openssh-9.4p1/regress/unittests/sshsig/testdata/ed25519.sig openssh-9.4p1+x509-14.2.1/regress/unittests/sshsig/testdata/ed25519.sig --- openssh-9.4p1/regress/unittests/sshsig/testdata/ed25519.sig 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/unittests/sshsig/testdata/ed25519.sig 1970-01-01 02:00:00.000000000 +0200 @@ -1,6 +0,0 @@ ------BEGIN SSH SIGNATURE----- -U1NIU0lHAAAAAQAAADMAAAALc3NoLWVkMjU1MTkAAAAgiWLNIg3cNBXvxU82NW+/COB/4/ -keps9gJi7cE4x2MAQAAAAIdW5pdHRlc3QAAAAAAAAABnNoYTUxMgAAAFMAAAALc3NoLWVk -MjU1MTkAAABAihQsbUzuNEFflk5Tw1+H9aLS7tZQk0RG8KW1DtOmDYYnWe3D3UKiG3fcJa -DNg4vBWp1j1gLRiBMOF+gwYNegDg== ------END SSH SIGNATURE----- diff -ruN openssh-9.4p1/regress/unittests/sshsig/testdata/ed25519_sk openssh-9.4p1+x509-14.2.1/regress/unittests/sshsig/testdata/ed25519_sk --- openssh-9.4p1/regress/unittests/sshsig/testdata/ed25519_sk 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/unittests/sshsig/testdata/ed25519_sk 1970-01-01 02:00:00.000000000 +0200 @@ -1,8 +0,0 @@ ------BEGIN OPENSSH PRIVATE KEY----- -b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAASgAAABpzay1zc2 -gtZWQyNTUxOUBvcGVuc3NoLmNvbQAAACCbGg2F0GK7nOm4pQmAyCuGEjnhvs5q0TtjPbdN -//+yxwAAAARzc2g6AAAAuBw56jAcOeowAAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY2 -9tAAAAIJsaDYXQYruc6bilCYDIK4YSOeG+zmrRO2M9t03//7LHAAAABHNzaDoBAAAAQFXc -6dCwWewIk1EBofAouGZApW8+s0XekXenxtb78+x0mxoNhdBiu5zpuKUJgMgrhhI54b7Oat -E7Yz23Tf//sscAAAAAAAAAE0VEMjU1MTktU0sgdGVzdCBrZXkBAgMEBQY= ------END OPENSSH PRIVATE KEY----- diff -ruN openssh-9.4p1/regress/unittests/sshsig/testdata/ed25519_sk.pub openssh-9.4p1+x509-14.2.1/regress/unittests/sshsig/testdata/ed25519_sk.pub --- openssh-9.4p1/regress/unittests/sshsig/testdata/ed25519_sk.pub 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/unittests/sshsig/testdata/ed25519_sk.pub 1970-01-01 02:00:00.000000000 +0200 @@ -1 +0,0 @@ -sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIJsaDYXQYruc6bilCYDIK4YSOeG+zmrRO2M9t03//7LHAAAABHNzaDo= ED25519-SK test key diff -ruN openssh-9.4p1/regress/unittests/sshsig/testdata/ed25519_sk.sig openssh-9.4p1+x509-14.2.1/regress/unittests/sshsig/testdata/ed25519_sk.sig --- openssh-9.4p1/regress/unittests/sshsig/testdata/ed25519_sk.sig 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/unittests/sshsig/testdata/ed25519_sk.sig 1970-01-01 02:00:00.000000000 +0200 @@ -1,7 +0,0 @@ ------BEGIN SSH SIGNATURE----- -U1NIU0lHAAAAAQAAAEoAAAAac2stc3NoLWVkMjU1MTlAb3BlbnNzaC5jb20AAAAgmxoNhd -Biu5zpuKUJgMgrhhI54b7OatE7Yz23Tf//sscAAAAEc3NoOgAAAAh1bml0dGVzdAAAAAAA -AAAGc2hhNTEyAAAAZwAAABpzay1zc2gtZWQyNTUxOUBvcGVuc3NoLmNvbQAAAEAi+7eTjW -/+LQ2M+sCD+KFtH1n7VFFJon/SZFsxODyV8cWTlFKj617Ys1Ur5TV6uaEXQhck8rBA2oQI -HTPANLIPARI0Vng= ------END SSH SIGNATURE----- diff -ruN openssh-9.4p1/regress/unittests/sshsig/testdata/namespace openssh-9.4p1+x509-14.2.1/regress/unittests/sshsig/testdata/namespace --- openssh-9.4p1/regress/unittests/sshsig/testdata/namespace 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/unittests/sshsig/testdata/namespace 1970-01-01 02:00:00.000000000 +0200 @@ -1 +0,0 @@ -unittest \ No newline at end of file diff -ruN openssh-9.4p1/regress/unittests/sshsig/testdata/rsa openssh-9.4p1+x509-14.2.1/regress/unittests/sshsig/testdata/rsa --- openssh-9.4p1/regress/unittests/sshsig/testdata/rsa 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/unittests/sshsig/testdata/rsa 1970-01-01 02:00:00.000000000 +0200 @@ -1,39 +0,0 @@ ------BEGIN RSA PRIVATE KEY----- -MIIG4wIBAAKCAYEA386lmjRHtJpyj87BrS+ssMmtvc/1SPN0gXTPs9jZ1hYAq98P -ca3/RYVM4HaSu6COztQJ2ZnZD3Te/XeBnIU2mfuvQEl+DiwisGeNglVyRCi7787f -PFFfcxzZfDa7EB2qY8S3oaSGZK8QqzuGwmGAImjlQXz6J+HCd/eD/58GoCSSirIE -CFWCAt+uNrOC/EmgAzsbfcfaIbbVzA40tlgU3hO2J42kddz8CisDTtDKQABFcOaQ -ZycSfn7HDP+WgXLXXBUI9wVM1Tif1f+9MX08xIsvCvGzo7yLgbbTFLSGr5SkA+tO -rYuoA7V8fge0id/3pnVtG1Ui3I7vejeAwf0HZqtFeBEnOwkIJFmZeMtFeOVf+4ki -4h1rDqAvSscNvMtLp6OXpbAATATAuEWEkIQBl1rngnEe0iC9iU9itKMW6qJ4FtIb -4ACH1EoU1x8vqrFecg2hvqfk5CZBJIbV28JFuGjac3OxBZ17Fqb8ljomUir1GrET -2z66NMgb5TjDD7BVAgMBAAECggGACfjDGCPMLhfTkuS7bGP7ZcUWoKZrX1y5jCsQ -NgsraYaBcSb3ITGHdimCS139G68DreN0rOVV7oJejRyOAdNNo367SDn+C9ObmBCF -FZGJDdBiz0SAXceiYRaf+hDWNNmdheR16hXShxnlvDtivbZqZx4VWN2gp7Y/W+kD -UJhdSzVV8igMVfK5YDdnI7jL1UHSh1JS3z/QUEA9NmJLpvQ1uc9XBlwhP78g27Me -6pwS5tccQPOE65OqF0i+xa19nzbmnC940Y34yZeI/UE+PYaO2+asapvOfu/sboBH -Yb5BuWXVEkSeRWI23SpuZbmfNTtVgiRoRqOvqM4G88LkhYjZ6xpDggxQwJiShiiD -oWCucs0v3pX8H8/LbGs8l50SGI5nzUqAdZ7/QQucU/GuDiQtampntkLEDgf9KIw/ -SDrtCw1E9fnCWj4Z71IYfepY9bVY6QUEcfTdnDcYSY1Z5tVpzeMHVLeo0lbNVZv9 -2qmPnjjP/IvWbjjwu/PHpUWkUs0BAoHBAPx4YwPXWYgWnesMKXkjAHyO5KA4EyBr -+rcEmOZkZDibC8PKYzIK2ztptuthahVovW20R/QJhJkO5teGZMeGPFq+floCeC5P -la9CEYGYcTrzgSe1QM9IGMr1vGI1KIWck7VkJ0bkKoY40uIJSVZxnyG9pEpcwYSp -tnOqA/f5YZUFctWvXUz46OfiLKstXLrcrGIU7YRmLv2rW9twnpJYTzE98g3KpVJ2 -TI1pyvrDTdGeAQUTGCAjpviY6XR5d020vQKBwQDi76wsGLQ3XLI+OAE95Ljo0Mcl -+KdJPVVQPq/VcjKgZQndFloflMRrmgNHme9gmsHOrf8DLZvEDbtT+gbmWslMFZQ9 -om1kR404gfuGmfIYdBdOwWjuBLsZs3pfqDB4Xa3NkxljwOMYTp035n0r2UMFaSy3 -gvpW7fsdPOGAJsqNhSw/JNHcokHeBm7VbV0aD7tSyIghmARb5c98fmrSPbiEo8mP -ITIZlgbfZCq2KuXY4q16R3QvlpuSwitVobLR/3kCgcEAueH5JM7dQHFGe9RMhL/c -j9i1Q7GFg4183lsoKBkqIPMmylSsjB+qIihHYS4r6O9g6PCfOXH4iqiKFY0BjlWr -AjTW2naO/aniz1KZiQ0v8PNv2Eh/Gx4+AtDCjpwM5bLOnfLLaEp9dK1JttqXgGnP -fAwgdg+s+3votWgr29tkmU+VqPagfxeUg4Xm1XFkoL/wu5Yk+iIx3trXms1kMuOK -CvtMyBK3fetTmZqWs+Iv3XGz1oSkcqVNPiN3XyY/TJsRAoG/Q17jvjOXTNg4EkCO -HdHJE1Tnyl4HS7bpnOj/Sl6cqQFV7Ey2dKm1pjwSvS714bgP0UvWaRshIxLwif2w -DrLlD7FYUPPnhd24Dw6HnW4WcSwFv1uryv2cjgS6T6ueuB0Xe/AvmW2p/Y1ZHz9N -6baWLwUKQXCg4S3FXui0CVd6yoi+mgBUTSveYguG29WbziDde7YMs+xtXtravhrJ -m6C3Jql5LQSt2uqvH6KdC3ewxLKGzcZot7f+d5MtSj6216ECgcEA9PGmWeUkhVuW -Xz2c9iBeHwCtmDso7gVwxNnHqdqirB4f1nDCGbrJS7hz5Ss7/wfzekP2W5if2P6U -JPUdfykAQgALNn1twAtj1a+UAp31ZWu8JK/Qzt4hLJPBxzMo7MenJq189JmYmDnm -6D5d9vDLCW15gCZua89GZa8K8V50lYyeHBOHAyzNTfNlnMBkHyP645+nqpuEWzIT -3mCe2OAbl60o8VvvVUlAQyQ/ObLq37HHEoDu0U/YAnP157cxpa84 ------END RSA PRIVATE KEY----- diff -ruN openssh-9.4p1/regress/unittests/sshsig/testdata/rsa.pub openssh-9.4p1+x509-14.2.1/regress/unittests/sshsig/testdata/rsa.pub --- openssh-9.4p1/regress/unittests/sshsig/testdata/rsa.pub 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/unittests/sshsig/testdata/rsa.pub 1970-01-01 02:00:00.000000000 +0200 @@ -1 +0,0 @@ -ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDfzqWaNEe0mnKPzsGtL6ywya29z/VI83SBdM+z2NnWFgCr3w9xrf9FhUzgdpK7oI7O1AnZmdkPdN79d4GchTaZ+69ASX4OLCKwZ42CVXJEKLvvzt88UV9zHNl8NrsQHapjxLehpIZkrxCrO4bCYYAiaOVBfPon4cJ394P/nwagJJKKsgQIVYIC3642s4L8SaADOxt9x9ohttXMDjS2WBTeE7YnjaR13PwKKwNO0MpAAEVw5pBnJxJ+fscM/5aBctdcFQj3BUzVOJ/V/70xfTzEiy8K8bOjvIuBttMUtIavlKQD606ti6gDtXx+B7SJ3/emdW0bVSLcju96N4DB/Qdmq0V4ESc7CQgkWZl4y0V45V/7iSLiHWsOoC9Kxw28y0uno5elsABMBMC4RYSQhAGXWueCcR7SIL2JT2K0oxbqongW0hvgAIfUShTXHy+qsV5yDaG+p+TkJkEkhtXbwkW4aNpzc7EFnXsWpvyWOiZSKvUasRPbPro0yBvlOMMPsFU= RSA test diff -ruN openssh-9.4p1/regress/unittests/sshsig/testdata/rsa.sig openssh-9.4p1+x509-14.2.1/regress/unittests/sshsig/testdata/rsa.sig --- openssh-9.4p1/regress/unittests/sshsig/testdata/rsa.sig 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/unittests/sshsig/testdata/rsa.sig 1970-01-01 02:00:00.000000000 +0200 @@ -1,19 +0,0 @@ ------BEGIN SSH SIGNATURE----- -U1NIU0lHAAAAAQAAAZcAAAAHc3NoLXJzYQAAAAMBAAEAAAGBAN/OpZo0R7Saco/Owa0vrL -DJrb3P9UjzdIF0z7PY2dYWAKvfD3Gt/0WFTOB2krugjs7UCdmZ2Q903v13gZyFNpn7r0BJ -fg4sIrBnjYJVckQou+/O3zxRX3Mc2Xw2uxAdqmPEt6GkhmSvEKs7hsJhgCJo5UF8+ifhwn -f3g/+fBqAkkoqyBAhVggLfrjazgvxJoAM7G33H2iG21cwONLZYFN4TtieNpHXc/AorA07Q -ykAARXDmkGcnEn5+xwz/loFy11wVCPcFTNU4n9X/vTF9PMSLLwrxs6O8i4G20xS0hq+UpA -PrTq2LqAO1fH4HtInf96Z1bRtVItyO73o3gMH9B2arRXgRJzsJCCRZmXjLRXjlX/uJIuId -aw6gL0rHDbzLS6ejl6WwAEwEwLhFhJCEAZda54JxHtIgvYlPYrSjFuqieBbSG+AAh9RKFN -cfL6qxXnINob6n5OQmQSSG1dvCRbho2nNzsQWdexam/JY6JlIq9RqxE9s+ujTIG+U4ww+w -VQAAAAh1bml0dGVzdAAAAAAAAAAGc2hhNTEyAAABlAAAAAxyc2Etc2hhMi01MTIAAAGACi -nEpBrQxZi0yOrrT6h98JFfZh0XXioih4fzmvtoV0yOReWClS+otGgXoJyZHcbaKNOjDwSM -rIkUoX6OUJmtHYP0HRELnKw35m33LdBPXpFGS4tRS7NeSpvc04KtjT6jYXY9FjWy5hcn17 -Sxc/3DnJqLgJBur8acY7FeIzpWmKixPd/dGkEjdWoD9gO6szLczGuQgrOdYmSRL4yKadTJ -lVjz5OSeKSYYGQy33US2XQassRRNYf4e9byTA3DKvHa/OcTt7lFerea0kZdDpAboqffz7T -Yaw/hFskAYLIEdTW3aoXBGHSOvu8AkDOtb7qwuxGSQ27pjkDLDNsp1ceCFaCaQ6X83RZuK -ACv9JUBI5KaSf81e0bs0KezJKkhB9czeZ6dk96qISbgayEBnvhYgXvUDKtHn7HzNlCJKfK -5ABhNxfGG2CD+NKqcrndwFgS1sQO3hbA84zPQb26ShBovT8ytHBmW1F8ZK4O9Bz61Q6EZK -vs/u6xP6LUean/so5daa ------END SSH SIGNATURE----- diff -ruN openssh-9.4p1/regress/unittests/sshsig/testdata/signed-data openssh-9.4p1+x509-14.2.1/regress/unittests/sshsig/testdata/signed-data --- openssh-9.4p1/regress/unittests/sshsig/testdata/signed-data 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/unittests/sshsig/testdata/signed-data 1970-01-01 02:00:00.000000000 +0200 @@ -1 +0,0 @@ -This is a test, this is only a test \ No newline at end of file diff -ruN openssh-9.4p1/regress/unittests/sshsig/tests.c openssh-9.4p1+x509-14.2.1/regress/unittests/sshsig/tests.c --- openssh-9.4p1/regress/unittests/sshsig/tests.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/unittests/sshsig/tests.c 1970-01-01 02:00:00.000000000 +0200 @@ -1,142 +0,0 @@ -/* $OpenBSD: tests.c,v 1.3 2021/12/14 21:25:27 deraadt Exp $ */ -/* - * Regress test for sshbuf.h buffer API - * - * Placed in the public domain - */ - -#include "includes.h" - -#include -#include -#include -#include -#ifdef HAVE_STDINT_H -#include -#endif -#include -#include -#include - -#ifdef WITH_OPENSSL -#include -#include -#endif - -#include "ssherr.h" -#include "authfile.h" -#include "sshkey.h" -#include "sshbuf.h" -#include "sshsig.h" -#include "log.h" - -#include "../test_helper/test_helper.h" - -static struct sshbuf * -load_file(const char *name) -{ - struct sshbuf *ret = NULL; - - ASSERT_INT_EQ(sshbuf_load_file(test_data_file(name), &ret), 0); - ASSERT_PTR_NE(ret, NULL); - return ret; -} - -static struct sshkey * -load_key(const char *name) -{ - struct sshkey *ret = NULL; - ASSERT_INT_EQ(sshkey_load_public(test_data_file(name), &ret, NULL), 0); - ASSERT_PTR_NE(ret, NULL); - return ret; -} - -static void -check_sig(const char *keyname, const char *signame, const struct sshbuf *msg, - const char *namespace) -{ - struct sshkey *k, *sign_key; - struct sshbuf *sig, *rawsig; - struct sshkey_sig_details *sig_details; - - k = load_key(keyname); - sig = load_file(signame); - sign_key = NULL; - sig_details = NULL; - rawsig = NULL; - ASSERT_INT_EQ(sshsig_dearmor(sig, &rawsig), 0); - ASSERT_INT_EQ(sshsig_verifyb(rawsig, msg, namespace, - &sign_key, &sig_details), 0); - ASSERT_INT_EQ(sshkey_equal(k, sign_key), 1); - sshkey_free(k); - sshkey_free(sign_key); - sshkey_sig_details_free(sig_details); - sshbuf_free(sig); - sshbuf_free(rawsig); -} - -void -tests(void) -{ - struct sshbuf *msg; - char *namespace; - -#if 0 - log_init("test_sshsig", SYSLOG_LEVEL_DEBUG3, SYSLOG_FACILITY_AUTH, 1); -#endif - -#ifdef WITH_OPENSSL - OpenSSL_add_all_algorithms(); - ERR_load_crypto_strings(); -#endif - - TEST_START("load data"); - msg = load_file("namespace"); - namespace = sshbuf_dup_string(msg); - ASSERT_PTR_NE(namespace, NULL); - sshbuf_free(msg); - msg = load_file("signed-data"); - TEST_DONE(); - -#ifdef WITH_OPENSSL - TEST_START("check RSA signature"); - check_sig("rsa.pub", "rsa.sig", msg, namespace); - TEST_DONE(); - - TEST_START("check DSA signature"); - check_sig("dsa.pub", "dsa.sig", msg, namespace); - TEST_DONE(); - -#ifdef OPENSSL_HAS_ECC - TEST_START("check ECDSA signature"); - check_sig("ecdsa.pub", "ecdsa.sig", msg, namespace); - TEST_DONE(); -#endif -#endif - - TEST_START("check ED25519 signature"); - check_sig("ed25519.pub", "ed25519.sig", msg, namespace); - TEST_DONE(); - -#ifdef ENABLE_SK -#if defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC) - TEST_START("check ECDSA-SK signature"); - check_sig("ecdsa_sk.pub", "ecdsa_sk.sig", msg, namespace); - TEST_DONE(); -#endif - - TEST_START("check ED25519-SK signature"); - check_sig("ed25519_sk.pub", "ed25519_sk.sig", msg, namespace); - TEST_DONE(); - -#if defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC) - TEST_START("check ECDSA-SK webauthn signature"); - check_sig("ecdsa_sk_webauthn.pub", "ecdsa_sk_webauthn.sig", - msg, namespace); - TEST_DONE(); -#endif -#endif /* ENABLE_SK */ - - sshbuf_free(msg); - free(namespace); -} diff -ruN openssh-9.4p1/regress/unittests/sshsig/webauthn.html openssh-9.4p1+x509-14.2.1/regress/unittests/sshsig/webauthn.html --- openssh-9.4p1/regress/unittests/sshsig/webauthn.html 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/unittests/sshsig/webauthn.html 1970-01-01 02:00:00.000000000 +0200 @@ -1,766 +0,0 @@ - - - -webauthn test - - -

webauthn test

-

-This is a demo/test page for generating FIDO keys and signatures in SSH -formats. The page initially displays a form to generate a FIDO key and -convert it to a SSH public key. -

-

-Once a key has been generated, an additional form will be displayed to -allow signing of data using the just-generated key. The data may be signed -as either a raw SSH signature or wrapped in a sshsig message (the latter is -easier to test using command-line tools. -

-

-Lots of debugging is printed along the way. -

-

Enroll

- -
- - - - - - -
Username:
-
- - - - - - - diff -ruN openssh-9.4p1/regress/unittests/test_helper/fuzz.c openssh-9.4p1+x509-14.2.1/regress/unittests/test_helper/fuzz.c --- openssh-9.4p1/regress/unittests/test_helper/fuzz.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/unittests/test_helper/fuzz.c 2023-08-20 10:07:01.000000000 +0300 @@ -17,24 +17,21 @@ /* Utility functions/framework for fuzz tests */ -#include "includes.h" +#include "test_helper.h" -#include #include #include #include #include -#ifdef HAVE_STDINT_H -# include -#endif #include #include #include #include -#include "test_helper.h" #include "atomicio.h" +typedef void (*sshsig_t)(int); +sshsig_t ssh_signal(int, sshsig_t); /* #define FUZZ_DEBUG */ @@ -192,7 +189,7 @@ fputs(buf, stderr); fprintf(stderr, "fuzz original %p len = %zu\n", fuzz->seed, fuzz->slen); dump(fuzz->seed, fuzz->slen); - fprintf(stderr, "fuzz context %p len = %zu\n", fuzz, fuzz_len(fuzz)); + fprintf(stderr, "fuzz context %p len = %zu\n", (void*)fuzz, fuzz_len(fuzz)); dump(fuzz_ptr(fuzz), fuzz_len(fuzz)); } @@ -233,9 +230,9 @@ last_fuzz = ret; #ifdef SIGINFO - signal(SIGINFO, siginfo); + ssh_signal(SIGINFO, siginfo); #endif - signal(SIGUSR1, siginfo); + ssh_signal(SIGUSR1, siginfo); return ret; } @@ -246,9 +243,9 @@ FUZZ_DBG(("cleanup, fuzz = %p", fuzz)); last_fuzz = NULL; #ifdef SIGINFO - signal(SIGINFO, SIG_DFL); + ssh_signal(SIGINFO, SIG_DFL); #endif - signal(SIGUSR1, SIG_DFL); + ssh_signal(SIGUSR1, SIG_DFL); assert(fuzz != NULL); assert(fuzz->seed != NULL); assert(fuzz->fuzzed != NULL); diff -ruN openssh-9.4p1/regress/unittests/test_helper/test_helper.c openssh-9.4p1+x509-14.2.1/regress/unittests/test_helper/test_helper.c --- openssh-9.4p1/regress/unittests/test_helper/test_helper.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/unittests/test_helper/test_helper.c 2023-08-20 10:07:01.000000000 +0300 @@ -17,17 +17,13 @@ /* Utility functions/framework for regress tests */ -#include "includes.h" +#include "test_helper.h" -#include #include #include #include #include -#ifdef HAVE_STDINT_H -# include -#endif #include #include #include @@ -35,7 +31,6 @@ #include #ifdef WITH_OPENSSL -#include #include #endif @@ -43,11 +38,9 @@ # include #endif -#define MINIMUM(a, b) (((a) < (b)) ? (a) : (b)) - -#include "entropy.h" -#include "test_helper.h" #include "atomicio.h" +typedef void (*sshsig_t)(int); +sshsig_t ssh_signal(int, sshsig_t); #define TEST_CHECK_INT(r, pred) do { \ switch (pred) { \ @@ -129,16 +122,11 @@ { int ch; - seed_rng(); -#ifdef WITH_OPENSSL - ERR_load_crypto_strings(); -#endif - /* Handle systems without __progname */ if (__progname == NULL) { __progname = strrchr(argv[0], '/'); if (__progname == NULL || __progname[1] == '\0') - __progname = argv[0]; + __progname = argv[0]; else __progname++; if ((__progname = strdup(__progname)) == NULL) { @@ -253,9 +241,9 @@ printf("test %u - \"%s\": ", test_number, active_test_name); test_number++; #ifdef SIGINFO - signal(SIGINFO, siginfo); + ssh_signal(SIGINFO, siginfo); #endif - signal(SIGUSR1, siginfo); + ssh_signal(SIGUSR1, siginfo); } void @@ -341,7 +329,7 @@ test_header(const char *file, int line, const char *a1, const char *a2, const char *name, enum test_predicate pred) { - fprintf(stderr, "\n%s:%d test #%u \"%s\"%s%s\n", + fprintf(stderr, "\n%s:%d test #%u \"%s\"%s%s\n", file, line, test_number, active_test_name, *subtest_info != '\0' ? " - " : "", subtest_info); fprintf(stderr, "ASSERT_%s_%s(%s%s%s) failed:\n", diff -ruN openssh-9.4p1/regress/unittests/test_helper/test_helper.h openssh-9.4p1+x509-14.2.1/regress/unittests/test_helper/test_helper.h --- openssh-9.4p1/regress/unittests/test_helper/test_helper.h 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/unittests/test_helper/test_helper.h 2023-08-20 10:07:00.000000000 +0300 @@ -22,14 +22,16 @@ #include "includes.h" +/* from "includes.h" above #include +#include #ifdef HAVE_STDINT_H # include #endif +*/ #ifdef WITH_OPENSSL #include -#include #endif enum test_predicate { @@ -103,7 +105,7 @@ #define TEST_START(n) test_start(n) #define TEST_DONE() test_done() #define TEST_ONERROR(f, c) set_onerror_func(f, c) -#define SSL_ERR_CHECK() ssl_err_check(__FILE__, __LINE__) +#define SSL_ERR_CHECK() ssl_err_check(__FILE__, __LINE__) #define ASSERT_BIGNUM_EQ(a1, a2) \ assert_bignum(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_EQ) diff -ruN openssh-9.4p1/regress/unittests/utf8/tests.c openssh-9.4p1+x509-14.2.1/regress/unittests/utf8/tests.c --- openssh-9.4p1/regress/unittests/utf8/tests.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/unittests/utf8/tests.c 2023-08-20 10:07:01.000000000 +0300 @@ -6,15 +6,13 @@ * and placed in the public domain. */ -#include "includes.h" +#include "../test_helper/test_helper.h" #include #include #include #include -#include "../test_helper/test_helper.h" - #include "utf8.h" static void diff -ruN openssh-9.4p1/regress/valgrind-unit.sh openssh-9.4p1+x509-14.2.1/regress/valgrind-unit.sh --- openssh-9.4p1/regress/valgrind-unit.sh 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/regress/valgrind-unit.sh 2023-08-20 10:07:00.000000000 +0300 @@ -2,14 +2,15 @@ UNIT_BINARY="$1" shift -UNIT_ARGS="$@" +UNIT_ARGS=${1+"$@"} test "x$OBJ" = "x" && OBJ=$PWD +mkdir $OBJ/valgrind-out 2>/dev/null || : # This mostly replicates the logic in test-exec.sh for running the # regress tests under valgrind, except that we unconditionally enable # leak checking because the unit tests should be clean. -VG_LEAK="--leak-check=full" +VG_LEAK="--leak-check=full --show-leak-kinds=all" VG_TEST=`basename $UNIT_BINARY` VG_LOG="$OBJ/valgrind-out/${VG_TEST}.%p" VG_OPTS="--track-origins=yes $VG_LEAK --log-file=${VG_LOG}" @@ -19,6 +20,4 @@ VG_PATH="$VALGRIND_PATH" fi -mkdir -p "$OBJ/valgrind-out" - exec $VG_PATH $VG_OPTS $UNIT_BINARY $UNIT_ARGS diff -ruN openssh-9.4p1/sandbox-capsicum.c openssh-9.4p1+x509-14.2.1/sandbox-capsicum.c --- openssh-9.4p1/sandbox-capsicum.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/sandbox-capsicum.c 2023-08-20 10:07:01.000000000 +0300 @@ -18,7 +18,6 @@ #ifdef SANDBOX_CAPSICUM -#include #include #include #include @@ -58,7 +57,7 @@ * Strictly, we don't need to maintain any state here but we need * to return non-NULL to satisfy the API. */ - debug3("%s: preparing capsicum sandbox", __func__); + debug3_f("preparing capsicum sandbox"); box = xcalloc(1, sizeof(*box)); box->monitor = monitor; box->child_pid = 0; @@ -78,37 +77,49 @@ rl_zero.rlim_cur = rl_zero.rlim_max = 0; +#ifndef SANDBOX_SKIP_RLIMIT_FSIZE if (setrlimit(RLIMIT_FSIZE, &rl_zero) == -1) - fatal("%s: setrlimit(RLIMIT_FSIZE, { 0, 0 }): %s", - __func__, strerror(errno)); + fatal_f("setrlimit(RLIMIT_FSIZE, { 0, 0 }): %s", + strerror(errno)); +#endif #ifndef SANDBOX_SKIP_RLIMIT_NOFILE - if (setrlimit(RLIMIT_NOFILE, &rl_zero) == -1) - fatal("%s: setrlimit(RLIMIT_NOFILE, { 0, 0 }): %s", - __func__, strerror(errno)); +/* + * Define to disable RLIMIT_NOFILE in sandboxes. + * In some FreeBSD configurations, C library may attempt to open + * additional file descriptors required by cryptographic operations + * and program may crash if open fail. + */ +{ struct rlimit rl_nofile; + /* Cannot use zero because of poll(2) requirement */ + rl_nofile.rlim_cur = rl_nofile.rlim_max = 1; + if (setrlimit(RLIMIT_NOFILE, &rl_nofile) == -1) + fatal_f("setrlimit(RLIMIT_NOFILE, { 1, 1 }): %s", + strerror(errno)); +} #endif if (setrlimit(RLIMIT_NPROC, &rl_zero) == -1) - fatal("%s: setrlimit(RLIMIT_NPROC, { 0, 0 }): %s", - __func__, strerror(errno)); + fatal_f("setrlimit(RLIMIT_NPROC, { 0, 0 }): %s", + strerror(errno)); cap_rights_init(&rights); if (cap_rights_limit(STDIN_FILENO, &rights) < 0 && errno != ENOSYS) - fatal("can't limit stdin: %m"); + fatal("can't limit stdin: %s", strerror(errno)); if (cap_rights_limit(STDOUT_FILENO, &rights) < 0 && errno != ENOSYS) - fatal("can't limit stdout: %m"); + fatal("can't limit stdout: %s", strerror(errno)); if (cap_rights_limit(STDERR_FILENO, &rights) < 0 && errno != ENOSYS) - fatal("can't limit stderr: %m"); + fatal("can't limit stderr: %s", strerror(errno)); cap_rights_init(&rights, CAP_READ, CAP_WRITE); if (cap_rights_limit(box->monitor->m_recvfd, &rights) < 0 && errno != ENOSYS) - fatal("%s: failed to limit the network socket", __func__); + fatal_f("failed to limit the network socket"); cap_rights_init(&rights, CAP_WRITE); if (cap_rights_limit(box->monitor->m_log_sendfd, &rights) < 0 && errno != ENOSYS) - fatal("%s: failed to limit the logging socket", __func__); + fatal_f("failed to limit the logging socket"); if (cap_enter() < 0 && errno != ENOSYS) - fatal("%s: failed to enter capability mode", __func__); + fatal_f("failed to enter capability mode"); } @@ -116,7 +127,7 @@ ssh_sandbox_parent_finish(struct ssh_sandbox *box) { free(box); - debug3("%s: finished", __func__); + debug3_f("finished"); } void diff -ruN openssh-9.4p1/sandbox-darwin.c openssh-9.4p1+x509-14.2.1/sandbox-darwin.c --- openssh-9.4p1/sandbox-darwin.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/sandbox-darwin.c 2023-08-20 10:07:01.000000000 +0300 @@ -49,7 +49,7 @@ * Strictly, we don't need to maintain any state here but we need * to return non-NULL to satisfy the API. */ - debug3("%s: preparing Darwin sandbox", __func__); + debug3_f("preparing Darwin sandbox"); box = xcalloc(1, sizeof(*box)); box->child_pid = 0; @@ -62,32 +62,40 @@ char *errmsg; struct rlimit rl_zero; - debug3("%s: starting Darwin sandbox", __func__); + debug3_f("starting Darwin sandbox"); if (sandbox_init(kSBXProfilePureComputation, SANDBOX_NAMED, &errmsg) == -1) - fatal("%s: sandbox_init: %s", __func__, errmsg); + fatal_f("sandbox_init: %s", errmsg); /* * The kSBXProfilePureComputation still allows sockets, so * we must disable these using rlimit. */ rl_zero.rlim_cur = rl_zero.rlim_max = 0; +#ifndef SANDBOX_SKIP_RLIMIT_FSIZE if (setrlimit(RLIMIT_FSIZE, &rl_zero) == -1) - fatal("%s: setrlimit(RLIMIT_FSIZE, { 0, 0 }): %s", - __func__, strerror(errno)); - if (setrlimit(RLIMIT_NOFILE, &rl_zero) == -1) - fatal("%s: setrlimit(RLIMIT_NOFILE, { 0, 0 }): %s", - __func__, strerror(errno)); + fatal_f("setrlimit(RLIMIT_FSIZE, { 0, 0 }): %s", + strerror(errno)); +#endif +#ifndef SANDBOX_SKIP_RLIMIT_NOFILE +{ struct rlimit rl_nofile; + /* Cannot use zero because of poll(2) requirement */ + rl_nofile.rlim_cur = rl_nofile.rlim_max = 1; + if (setrlimit(RLIMIT_NOFILE, &rl_nofile) == -1) + fatal_f("setrlimit(RLIMIT_NOFILE, { 1, 1 }): %s", + strerror(errno)); +} +#endif if (setrlimit(RLIMIT_NPROC, &rl_zero) == -1) - fatal("%s: setrlimit(RLIMIT_NPROC, { 0, 0 }): %s", - __func__, strerror(errno)); + fatal_f("setrlimit(RLIMIT_NPROC, { 0, 0 }): %s", + strerror(errno)); } void ssh_sandbox_parent_finish(struct ssh_sandbox *box) { free(box); - debug3("%s: finished", __func__); + debug3_f("finished"); } void diff -ruN openssh-9.4p1/sandbox-null.c openssh-9.4p1+x509-14.2.1/sandbox-null.c --- openssh-9.4p1/sandbox-null.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/sandbox-null.c 2023-08-20 10:07:01.000000000 +0300 @@ -43,6 +43,7 @@ { struct ssh_sandbox *box; + UNUSED(monitor); /* * Strictly, we don't need to maintain any state here but we need * to return non-NULL to satisfy the API. @@ -54,6 +55,7 @@ void ssh_sandbox_child(struct ssh_sandbox *box) { + UNUSED(box); /* Nothing to do here */ } @@ -66,6 +68,8 @@ void ssh_sandbox_parent_preauth(struct ssh_sandbox *box, pid_t child_pid) { + UNUSED(box); + UNUSED(child_pid); /* Nothing to do here */ } diff -ruN openssh-9.4p1/sandbox-rlimit.c openssh-9.4p1+x509-14.2.1/sandbox-rlimit.c --- openssh-9.4p1/sandbox-rlimit.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/sandbox-rlimit.c 2023-08-20 10:07:01.000000000 +0300 @@ -45,6 +45,7 @@ { struct ssh_sandbox *box; + UNUSED(monitor); /* * Strictly, we don't need to maintain any state here but we need * to return non-NULL to satisfy the API. @@ -61,6 +62,7 @@ { struct rlimit rl_zero; + UNUSED(box); rl_zero.rlim_cur = rl_zero.rlim_max = 0; #ifndef SANDBOX_SKIP_RLIMIT_FSIZE @@ -69,9 +71,20 @@ strerror(errno)); #endif #ifndef SANDBOX_SKIP_RLIMIT_NOFILE - if (setrlimit(RLIMIT_NOFILE, &rl_zero) == -1) - fatal_f("setrlimit(RLIMIT_NOFILE, { 0, 0 }): %s", +/* + * Define to disable RLIMIT_NOFILE in sandboxes. + * In some builds OpenSSL cryptographic library opens regularly + * random device and program may crash if open fail. + * For instance OpenSSL FIPS 1.2 module requires access + * to random device. + */ +{ struct rlimit rl_nofile; + /* Cannot use zero because of poll(2) requirement */ + rl_nofile.rlim_cur = rl_nofile.rlim_max = 1; + if (setrlimit(RLIMIT_NOFILE, &rl_nofile) == -1) + fatal_f("setrlimit(RLIMIT_NOFILE, { 1, 1 }): %s", strerror(errno)); +} #endif #ifdef HAVE_RLIMIT_NPROC if (setrlimit(RLIMIT_NPROC, &rl_zero) == -1) diff -ruN openssh-9.4p1/sandbox-seccomp-filter.c openssh-9.4p1+x509-14.2.1/sandbox-seccomp-filter.c --- openssh-9.4p1/sandbox-seccomp-filter.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/sandbox-seccomp-filter.c 2023-08-20 10:07:01.000000000 +0300 @@ -1,6 +1,5 @@ /* * Copyright (c) 2012 Will Drewry - * Copyright (c) 2015,2017,2019,2020,2023 Damien Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -26,12 +25,12 @@ */ /* #define SANDBOX_SECCOMP_FILTER_DEBUG 1 */ +/* XXX it should be possible to do logging via the log socket safely */ + #if 0 -/* - * For older toolchains, it may be necessary to use the kernel - * headers directly. - */ +/* NOTE: on older kernels - error: redefinition of 'union sigval' */ #ifdef SANDBOX_SECCOMP_FILTER_DEBUG +/* Use the kernel headers in case of an older toolchain. */ # include # define __have_siginfo_t 1 # define __have_sigval_t 1 @@ -49,7 +48,6 @@ #include #include -#include #include #include #include @@ -134,71 +132,6 @@ /* reload syscall number; all rules expect it in accumulator */ \ BPF_STMT(BPF_LD+BPF_W+BPF_ABS, \ offsetof(struct seccomp_data, nr)) -/* Deny unless syscall argument contains only values in mask */ -#define SC_DENY_UNLESS_ARG_MASK(_nr, _arg_nr, _arg_mask, _errno) \ - BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (_nr), 0, 8), \ - /* load, mask and test syscall argument, low word */ \ - BPF_STMT(BPF_LD+BPF_W+BPF_ABS, \ - offsetof(struct seccomp_data, args[(_arg_nr)]) + ARG_LO_OFFSET), \ - BPF_STMT(BPF_ALU+BPF_AND+BPF_K, ~((_arg_mask) & 0xFFFFFFFF)), \ - BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 0, 0, 3), \ - /* load, mask and test syscall argument, high word */ \ - BPF_STMT(BPF_LD+BPF_W+BPF_ABS, \ - offsetof(struct seccomp_data, args[(_arg_nr)]) + ARG_HI_OFFSET), \ - BPF_STMT(BPF_ALU+BPF_AND+BPF_K, \ - ~(((uint32_t)((uint64_t)(_arg_mask) >> 32)) & 0xFFFFFFFF)), \ - BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 0, 1, 0), \ - BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ERRNO|(_errno)), \ - /* reload syscall number; all rules expect it in accumulator */ \ - BPF_STMT(BPF_LD+BPF_W+BPF_ABS, \ - offsetof(struct seccomp_data, nr)) -#define SC_DENY_UNLESS_MASK(_nr, _arg_nr, _arg_val, _errno) \ -/* Special handling for futex(2) that combines a bitmap and operation number */ -#if defined(__NR_futex) || defined(__NR_futex_time64) -#define SC_FUTEX_MASK (FUTEX_PRIVATE_FLAG|FUTEX_CLOCK_REALTIME) -#define SC_ALLOW_FUTEX_OP(_nr, _op) \ - BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (_nr), 0, 8), \ - /* load syscall argument, low word */ \ - BPF_STMT(BPF_LD+BPF_W+BPF_ABS, \ - offsetof(struct seccomp_data, args[1]) + ARG_LO_OFFSET), \ - /* mask off allowed bitmap values, low word */ \ - BPF_STMT(BPF_ALU+BPF_AND+BPF_K, ~(SC_FUTEX_MASK & 0xFFFFFFFF)), \ - /* test operation number, low word */ \ - BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, ((_op) & 0xFFFFFFFF), 0, 4), \ - /* load syscall argument, high word */ \ - BPF_STMT(BPF_LD+BPF_W+BPF_ABS, \ - offsetof(struct seccomp_data, args[1]) + ARG_HI_OFFSET), \ - /* mask off allowed bitmap values, high word */ \ - BPF_STMT(BPF_ALU+BPF_AND+BPF_K, \ - ~(((uint32_t)((uint64_t)SC_FUTEX_MASK >> 32)) & 0xFFFFFFFF)), \ - /* test operation number, high word */ \ - BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, \ - (((uint32_t)((uint64_t)(_op) >> 32)) & 0xFFFFFFFF), 0, 1), \ - BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW), \ - /* reload syscall number; all rules expect it in accumulator */ \ - BPF_STMT(BPF_LD+BPF_W+BPF_ABS, offsetof(struct seccomp_data, nr)) - -/* Use this for both __NR_futex and __NR_futex_time64 */ -# define SC_FUTEX(_nr) \ - SC_ALLOW_FUTEX_OP(__NR_futex, FUTEX_WAIT), \ - SC_ALLOW_FUTEX_OP(__NR_futex, FUTEX_WAIT_BITSET), \ - SC_ALLOW_FUTEX_OP(__NR_futex, FUTEX_WAKE), \ - SC_ALLOW_FUTEX_OP(__NR_futex, FUTEX_WAKE_BITSET), \ - SC_ALLOW_FUTEX_OP(__NR_futex, FUTEX_REQUEUE), \ - SC_ALLOW_FUTEX_OP(__NR_futex, FUTEX_CMP_REQUEUE) -#endif /* __NR_futex || __NR_futex_time64 */ - -#if defined(__NR_mmap) || defined(__NR_mmap2) -# ifdef MAP_FIXED_NOREPLACE -# define SC_MMAP_FLAGS MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED|MAP_FIXED_NOREPLACE -# else -# define SC_MMAP_FLAGS MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED -# endif /* MAP_FIXED_NOREPLACE */ -/* Use this for both __NR_mmap and __NR_mmap2 variants */ -# define SC_MMAP(_nr) \ - SC_DENY_UNLESS_ARG_MASK(_nr, 3, SC_MMAP_FLAGS, EINVAL), \ - SC_ALLOW_ARG_MASK(_nr, 2, PROT_READ|PROT_WRITE|PROT_NONE) -#endif /* __NR_mmap || __NR_mmap2 */ /* Syscall filtering set for preauth. */ static const struct sock_filter preauth_insns[] = { @@ -278,10 +211,10 @@ SC_ALLOW(__NR_exit_group), #endif #ifdef __NR_futex - SC_FUTEX(__NR_futex), + SC_ALLOW(__NR_futex), #endif #ifdef __NR_futex_time64 - SC_FUTEX(__NR_futex_time64), + SC_ALLOW(__NR_futex_time64), #endif #ifdef __NR_geteuid SC_ALLOW(__NR_geteuid), @@ -295,6 +228,9 @@ #ifdef __NR_getpid SC_ALLOW(__NR_getpid), #endif +#ifdef __NR_gettid + SC_ALLOW(__NR_gettid), +#endif #ifdef __NR_getrandom SC_ALLOW(__NR_getrandom), #endif @@ -311,29 +247,13 @@ SC_ALLOW(__NR_getuid32), #endif #ifdef __NR_madvise - SC_ALLOW_ARG(__NR_madvise, 2, MADV_NORMAL), -# ifdef MADV_FREE - SC_ALLOW_ARG(__NR_madvise, 2, MADV_FREE), -# endif -# ifdef MADV_DONTNEED - SC_ALLOW_ARG(__NR_madvise, 2, MADV_DONTNEED), -# endif -# ifdef MADV_DONTFORK - SC_ALLOW_ARG(__NR_madvise, 2, MADV_DONTFORK), -# endif -# ifdef MADV_DONTDUMP - SC_ALLOW_ARG(__NR_madvise, 2, MADV_DONTDUMP), -# endif -# ifdef MADV_WIPEONFORK - SC_ALLOW_ARG(__NR_madvise, 2, MADV_WIPEONFORK), -# endif - SC_DENY(__NR_madvise, EINVAL), + SC_ALLOW(__NR_madvise), #endif #ifdef __NR_mmap - SC_MMAP(__NR_mmap), + SC_ALLOW_ARG_MASK(__NR_mmap, 2, PROT_READ|PROT_WRITE|PROT_NONE), #endif #ifdef __NR_mmap2 - SC_MMAP(__NR_mmap2), + SC_ALLOW_ARG_MASK(__NR_mmap2, 2, PROT_READ|PROT_WRITE|PROT_NONE), #endif #ifdef __NR_mprotect SC_ALLOW_ARG_MASK(__NR_mprotect, 2, PROT_READ|PROT_WRITE|PROT_NONE), @@ -353,9 +273,6 @@ #ifdef __NR_clock_nanosleep_time64 SC_ALLOW(__NR_clock_nanosleep_time64), #endif -#ifdef __NR_clock_gettime64 - SC_ALLOW(__NR_clock_gettime64), -#endif #ifdef __NR__newselect SC_ALLOW(__NR__newselect), #endif @@ -377,6 +294,9 @@ #ifdef __NR_read SC_ALLOW(__NR_read), #endif +#ifdef __NR_rt_sigaction + SC_ALLOW(__NR_rt_sigaction), +#endif #ifdef __NR_rt_sigprocmask SC_ALLOW(__NR_rt_sigprocmask), #endif @@ -402,6 +322,9 @@ SC_ALLOW_ARG(__NR_socketcall, 0, SYS_SHUTDOWN), SC_DENY(__NR_socketcall, EACCES), #endif +#ifdef __NR_socket + SC_DENY(__NR_socket, EACCES), +#endif #if defined(__NR_ioctl) && defined(__s390__) /* Allow ioctls for ICA crypto card on s390 */ SC_ALLOW_ARG(__NR_ioctl, 1, Z90STAT_STATUS_MASK), @@ -438,11 +361,12 @@ { struct ssh_sandbox *box; + UNUSED(monitor); /* * Strictly, we don't need to maintain any state here but we need * to return non-NULL to satisfy the API. */ - debug3("%s: preparing seccomp filter sandbox", __func__); + debug3_f("preparing seccomp filter sandbox"); box = xcalloc(1, sizeof(*box)); box->child_pid = 0; @@ -451,17 +375,18 @@ #ifdef SANDBOX_SECCOMP_FILTER_DEBUG extern struct monitor *pmonitor; -void mm_log_handler(LogLevel level, int forced, const char *msg, void *ctx); +void mm_log_handler(LogLevel level, const char *msg, void *ctx); static void ssh_sandbox_violation(int signum, siginfo_t *info, void *void_context) { char msg[256]; + UNUSED(signum); UNUSED(void_context); snprintf(msg, sizeof(msg), "%s: unexpected system call (arch:0x%x,syscall:%d @ %p)", __func__, info->si_arch, info->si_syscall, info->si_call_addr); - mm_log_handler(SYSLOG_LEVEL_FATAL, 0, msg, pmonitor); + mm_log_handler(SYSLOG_LEVEL_FATAL, msg, pmonitor); _exit(1); } @@ -471,7 +396,7 @@ struct sigaction act; sigset_t mask; - debug3("%s: installing SIGSYS handler", __func__); + debug3_f("installing SIGSYS handler"); memset(&act, 0, sizeof(act)); sigemptyset(&mask); sigaddset(&mask, SIGSYS); @@ -479,59 +404,68 @@ act.sa_sigaction = &ssh_sandbox_violation; act.sa_flags = SA_SIGINFO; if (sigaction(SIGSYS, &act, NULL) == -1) - fatal("%s: sigaction(SIGSYS): %s", __func__, strerror(errno)); + fatal_f("sigaction(SIGSYS): %s", strerror(errno)); if (sigprocmask(SIG_UNBLOCK, &mask, NULL) == -1) - fatal("%s: sigprocmask(SIGSYS): %s", - __func__, strerror(errno)); + fatal_f("sigprocmask(SIGSYS): %s", strerror(errno)); } #endif /* SANDBOX_SECCOMP_FILTER_DEBUG */ void ssh_sandbox_child(struct ssh_sandbox *box) { - struct rlimit rl_zero, rl_one = {.rlim_cur = 1, .rlim_max = 1}; + struct rlimit rl_zero; int nnp_failed = 0; + UNUSED(box); /* Set rlimits for completeness if possible. */ rl_zero.rlim_cur = rl_zero.rlim_max = 0; +#ifndef SANDBOX_SKIP_RLIMIT_FSIZE if (setrlimit(RLIMIT_FSIZE, &rl_zero) == -1) - fatal("%s: setrlimit(RLIMIT_FSIZE, { 0, 0 }): %s", - __func__, strerror(errno)); - /* - * Cannot use zero for nfds, because poll(2) will fail with - * errno=EINVAL if npfds>RLIMIT_NOFILE. - */ - if (setrlimit(RLIMIT_NOFILE, &rl_one) == -1) - fatal("%s: setrlimit(RLIMIT_NOFILE, { 0, 0 }): %s", - __func__, strerror(errno)); + fatal_f("setrlimit(RLIMIT_FSIZE, { 0, 0 }): %s", + strerror(errno)); +#endif +#ifndef SANDBOX_SKIP_RLIMIT_NOFILE +/* + * NOTE: The Open Group Base Specifications requires poll to return error + * EINVAL if argument nfds argument is greater than limit {OPEN_MAX}. + * Switch to poll requires to set limits to one on systems that conform + * with POSIX specification. Also note that cryptographic library + * may require file description to obtain random data. + */ +{ struct rlimit rl_nofile; + /* Cannot use zero because of poll(2) requirement */ + rl_nofile.rlim_cur = rl_nofile.rlim_max = 1; + if (setrlimit(RLIMIT_NOFILE, &rl_nofile) == -1) + fatal_f("setrlimit(RLIMIT_NOFILE, { 1, 1 }): %s", + strerror(errno)); +} +#endif if (setrlimit(RLIMIT_NPROC, &rl_zero) == -1) - fatal("%s: setrlimit(RLIMIT_NPROC, { 0, 0 }): %s", - __func__, strerror(errno)); + fatal_f("setrlimit(RLIMIT_NPROC, { 0, 0 }): %s", + strerror(errno)); #ifdef SANDBOX_SECCOMP_FILTER_DEBUG ssh_sandbox_child_debugging(); #endif /* SANDBOX_SECCOMP_FILTER_DEBUG */ - debug3("%s: setting PR_SET_NO_NEW_PRIVS", __func__); + debug3_f("setting PR_SET_NO_NEW_PRIVS"); if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) == -1) { - debug("%s: prctl(PR_SET_NO_NEW_PRIVS): %s", - __func__, strerror(errno)); + debug_f("prctl(PR_SET_NO_NEW_PRIVS): %s", strerror(errno)); nnp_failed = 1; } - debug3("%s: attaching seccomp filter program", __func__); + debug3_f("attaching seccomp filter program"); if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &preauth_program) == -1) - debug("%s: prctl(PR_SET_SECCOMP): %s", - __func__, strerror(errno)); + debug_f("prctl(PR_SET_SECCOMP): %s", strerror(errno)); else if (nnp_failed) - fatal("%s: SECCOMP_MODE_FILTER activated but " - "PR_SET_NO_NEW_PRIVS failed", __func__); + fatal_f("SECCOMP_MODE_FILTER activated but " + "PR_SET_NO_NEW_PRIVS failed"); } void ssh_sandbox_parent_finish(struct ssh_sandbox *box) { free(box); - debug3("%s: finished", __func__); + debug3_f("finished"); } void diff -ruN openssh-9.4p1/sandbox-solaris.c openssh-9.4p1+x509-14.2.1/sandbox-solaris.c --- openssh-9.4p1/sandbox-solaris.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/sandbox-solaris.c 2023-08-20 10:07:01.000000000 +0300 @@ -47,6 +47,7 @@ { struct ssh_sandbox *box = NULL; + UNUSED(monitor); box = xcalloc(1, sizeof(*box)); /* Start with "basic" and drop everything we don't need. */ @@ -108,6 +109,7 @@ void ssh_sandbox_parent_preauth(struct ssh_sandbox *box, pid_t child_pid) { + UNUSED(box); UNUSED(child_pid); /* Nothing to do here */ } diff -ruN openssh-9.4p1/sandbox-systrace.c openssh-9.4p1+x509-14.2.1/sandbox-systrace.c --- openssh-9.4p1/sandbox-systrace.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/sandbox-systrace.c 2023-08-20 10:07:01.000000000 +0300 @@ -101,7 +101,7 @@ { struct ssh_sandbox *box; - debug3("%s: preparing systrace sandbox", __func__); + debug3_f("preparing systrace sandbox"); box = xcalloc(1, sizeof(*box)); box->systrace_fd = -1; box->child_pid = 0; @@ -113,11 +113,11 @@ void ssh_sandbox_child(struct ssh_sandbox *box) { - debug3("%s: ready", __func__); + debug3_f("ready"); ssh_signal(SIGCHLD, box->osigchld); if (kill(getpid(), SIGSTOP) != 0) - fatal("%s: kill(%d, SIGSTOP)", __func__, getpid()); - debug3("%s: started", __func__); + fatal_f("kill(%d, SIGSTOP)", getpid()); + debug3_f("started"); } static void @@ -129,34 +129,34 @@ struct systrace_policy policy; /* Wait for the child to send itself a SIGSTOP */ - debug3("%s: wait for child %ld", __func__, (long)child_pid); + debug3_f("wait for child %ld", (long)child_pid); do { pid = waitpid(child_pid, &status, WUNTRACED); } while (pid == -1 && errno == EINTR); ssh_signal(SIGCHLD, box->osigchld); if (!WIFSTOPPED(status)) { if (WIFSIGNALED(status)) - fatal("%s: child terminated with signal %d", - __func__, WTERMSIG(status)); + fatal_f("child terminated with signal %d", + WTERMSIG(status)); if (WIFEXITED(status)) - fatal("%s: child exited with status %d", - __func__, WEXITSTATUS(status)); - fatal("%s: child not stopped", __func__); + fatal_f("child exited with status %d", + WEXITSTATUS(status)); + fatal_f("child not stopped"); } - debug3("%s: child %ld stopped", __func__, (long)child_pid); + debug3_f("child %ld stopped", (long)child_pid); box->child_pid = child_pid; /* Set up systracing of child */ if ((dev_systrace = open("/dev/systrace", O_RDONLY)) == -1) - fatal("%s: open(\"/dev/systrace\"): %s", __func__, + fatal_f("open(\"/dev/systrace\"): %s", strerror(errno)); if (ioctl(dev_systrace, STRIOCCLONE, &box->systrace_fd) == -1) - fatal("%s: ioctl(STRIOCCLONE, %d): %s", __func__, + fatal_f("ioctl(STRIOCCLONE, %d): %s", dev_systrace, strerror(errno)); close(dev_systrace); - debug3("%s: systrace attach, fd=%d", __func__, box->systrace_fd); + debug3_f("systrace attach, fd=%d", box->systrace_fd); if (ioctl(box->systrace_fd, STRIOCATTACH, &child_pid) == -1) - fatal("%s: ioctl(%d, STRIOCATTACH, %d): %s", __func__, + fatal_f("ioctl(%d, STRIOCATTACH, %d): %s", box->systrace_fd, child_pid, strerror(errno)); /* Allocate and assign policy */ @@ -164,14 +164,14 @@ policy.strp_op = SYSTR_POLICY_NEW; policy.strp_maxents = SYS_MAXSYSCALL; if (ioctl(box->systrace_fd, STRIOCPOLICY, &policy) == -1) - fatal("%s: ioctl(%d, STRIOCPOLICY (new)): %s", __func__, + fatal_f("ioctl(%d, STRIOCPOLICY (new)): %s", box->systrace_fd, strerror(errno)); policy.strp_op = SYSTR_POLICY_ASSIGN; policy.strp_pid = box->child_pid; if (ioctl(box->systrace_fd, STRIOCPOLICY, &policy) == -1) - fatal("%s: ioctl(%d, STRIOCPOLICY (assign)): %s", - __func__, box->systrace_fd, strerror(errno)); + fatal_f("ioctl(%d, STRIOCPOLICY (assign)): %s", + box->systrace_fd, strerror(errno)); /* Set per-syscall policy */ for (i = 0; i < SYS_MAXSYSCALL; i++) { @@ -187,16 +187,16 @@ policy.strp_policy = found ? allowed_syscalls[j].action : SYSTR_POLICY_KILL; if (found) - debug3("%s: policy: enable syscall %d", __func__, i); + debug3_f("policy: enable syscall %d", i); if (ioctl(box->systrace_fd, STRIOCPOLICY, &policy) == -1) - fatal("%s: ioctl(%d, STRIOCPOLICY (modify)): %s", - __func__, box->systrace_fd, strerror(errno)); + fatal_f("ioctl(%d, STRIOCPOLICY (modify)): %s", + box->systrace_fd, strerror(errno)); } /* Signal the child to start running */ - debug3("%s: start child %ld", __func__, (long)child_pid); + debug3_f("start child %ld", (long)child_pid); if (kill(box->child_pid, SIGCONT) != 0) - fatal("%s: kill(%d, SIGCONT)", __func__, box->child_pid); + fatal_f("kill(%d, SIGCONT)", box->child_pid); } void @@ -206,7 +206,7 @@ close(box->systrace_fd); free(box); - debug3("%s: finished", __func__); + debug3_f("finished"); } void diff -ruN openssh-9.4p1/scp.0 openssh-9.4p1+x509-14.2.1/scp.0 --- openssh-9.4p1/scp.0 2023-08-10 04:11:18.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/scp.0 2023-08-20 10:07:00.000000000 +0300 @@ -1,7 +1,7 @@ -SCP(1) General Commands Manual SCP(1) +SCP(1) BSD General Commands Manual SCP(1) NAME - scp M-bM-^@M-^S OpenSSH secure file copy + scp -- Secure copy (remote file copy program) SYNOPSIS scp [-346ABCOpqRrsTv] [-c cipher] [-D sftp_server_path] [-F ssh_config] @@ -11,18 +11,17 @@ DESCRIPTION scp copies files between hosts on a network. - scp uses the SFTP protocol over a ssh(1) connection for data transfer, - and uses the same authentication and provides the same security as a - login session. + It uses ssh(1) for data transfer, and uses the same authentication and + provides the same security as a login session. - scp will ask for passwords or passphrases if they are needed for - authentication. + scp will ask for passwords or passphrases if they are needed for authen- + tication. The source and target may be specified as a local pathname, a remote host with optional path in the form [user@]host:[path], or a URI in the form scp://[user@]host[:port][/path]. Local file names can be made explicit using absolute or relative pathnames to avoid scp treating file names - containing M-bM-^@M-^X:M-bM-^@M-^Y as host specifiers. + containing ':' as host specifiers. When copying between two remote hosts, if the URI format is used, a port cannot be specified on the target if the -R option is used. @@ -31,32 +30,32 @@ -3 Copies between two remote hosts are transferred through the local host. Without this option the data is copied directly between - the two remote hosts. Note that, when using the legacy SCP - protocol (via the -O flag), this option selects batch mode for - the second host as scp cannot ask for passwords or passphrases - for both hosts. This mode is the default. + the two remote hosts. Note that, when using the original SCP + protocol (the default), this option selects batch mode for the + second host as scp cannot ask for passwords or passphrases for + both hosts. This mode is the default. -4 Forces scp to use IPv4 addresses only. -6 Forces scp to use IPv6 addresses only. - -A Allows forwarding of ssh-agent(1) to the remote system. The - default is not to forward an authentication agent. + -A Allows forwarding of ssh-agent(1) to the remote system. The de- + fault is not to forward an authentication agent. -B Selects batch mode (prevents asking for passwords or passphrases). - -C Compression enable. Passes the -C flag to ssh(1) to enable - compression. + -C Compression enable. Passes the -C flag to ssh(1) to enable com- + pression. -c cipher Selects the cipher to use for encrypting the data transfer. This option is directly passed to ssh(1). -D sftp_server_path - Connect directly to a local SFTP server program rather than a - remote one via ssh(1). This option may be useful in debugging - the client and server. + When using the SFTP protocol support via -s, connect directly to + a local SFTP server program rather than a remote one via ssh(1). + This option may be useful in debugging the client and server. -F ssh_config Specifies an alternative per-user configuration file for ssh. @@ -78,84 +77,22 @@ -l limit Limits the used bandwidth, specified in Kbit/s. - -O Use the legacy SCP protocol for file transfers instead of the - SFTP protocol. Forcing the use of the SCP protocol may be - necessary for servers that do not implement SFTP, for backwards- - compatibility for particular filename wildcard patterns and for - expanding paths with a M-bM-^@M-^X~M-bM-^@M-^Y prefix for older SFTP servers. + -O Use the original SCP protocol for file transfers instead of the + SFTP protocol. Forcing the use of the SCP protocol may be neces- + sary for servers that do not implement SFTP, for backwards-com- + patibility for particular filename wildcard patterns and for ex- + panding paths with a '~' prefix for older SFTP servers. This + mode is the default. -o ssh_option Can be used to pass options to ssh in the format used in ssh_config(5). This is useful for specifying options for which there is no separate scp command-line flag. For full details of - the options listed below, and their possible values, see - ssh_config(5). - - AddressFamily - BatchMode - BindAddress - BindInterface - CanonicalDomains - CanonicalizeFallbackLocal - CanonicalizeHostname - CanonicalizeMaxDots - CanonicalizePermittedCNAMEs - CASignatureAlgorithms - CertificateFile - CheckHostIP - Ciphers - Compression - ConnectionAttempts - ConnectTimeout - ControlMaster - ControlPath - ControlPersist - GlobalKnownHostsFile - GSSAPIAuthentication - GSSAPIDelegateCredentials - HashKnownHosts - Host - HostbasedAcceptedAlgorithms - HostbasedAuthentication - HostKeyAlgorithms - HostKeyAlias - Hostname - IdentitiesOnly - IdentityAgent - IdentityFile - IPQoS - KbdInteractiveAuthentication - KbdInteractiveDevices - KexAlgorithms - KnownHostsCommand - LogLevel - MACs - NoHostAuthenticationForLocalhost - NumberOfPasswordPrompts - PasswordAuthentication - PKCS11Provider - Port - PreferredAuthentications - ProxyCommand - ProxyJump - PubkeyAcceptedAlgorithms - PubkeyAuthentication - RekeyLimit - RequiredRSASize - SendEnv - ServerAliveInterval - ServerAliveCountMax - SetEnv - StrictHostKeyChecking - TCPKeepAlive - UpdateHostKeys - User - UserKnownHostsFile - VerifyHostKeyDNS + the options and their possible values, see ssh_config(5). -P port Specifies the port to connect to on the remote host. Note that - this option is written with a capital M-bM-^@M-^XPM-bM-^@M-^Y, because -p is already + this option is written with a capital 'P', because -p is already reserved for preserving the times and mode bits of the file. -p Preserves modification times, access times, and file mode bits @@ -169,16 +106,24 @@ running on the origin host can authenticate to the destination host without requiring a password. - -r Recursively copy entire directories. Note that scp follows - symbolic links encountered in the tree traversal. + -r Recursively copy entire directories. Note that scp follows sym- + bolic links encountered in the tree traversal. -S program Name of program to use for the encrypted connection. The program must understand ssh(1) options. + -s Use the SFTP protocol for transfers rather than the original scp + protocol. + + Note functionality is considered as experimental and is still un- + der development. In some cases requires specific SFTP server ex- + tension to work, in other cases may fail. As result is not con- + sidered as drop-in replacement of secure copy utility. + -T Disable strict filename checking. By default when copying files - from a remote host to a local directory scp checks that the - received filenames match those requested on the command-line to + from a remote host to a local directory scp checks that the re- + ceived filenames match those requested on the command-line to prevent the remote end from sending unexpected or unwanted files. Because of differences in how various operating systems and shells interpret filename wildcards, these checks may cause @@ -191,22 +136,30 @@ authentication, and configuration problems. -X sftp_option - Specify an option that controls aspects of SFTP protocol - behaviour. The valid options are: + Specify an option that controls aspects of SFTP protocol behav- + iour. The valid options are: nrequests=value Controls how many concurrent SFTP read or write requests may be in progress at any point in time during a download - or upload. By default 64 requests may be active - concurrently. + or upload. By default 64 requests may be active concur- + rently. Maximum accepted value is 1024. buffer=value Controls the maximum buffer size for a single SFTP read/write operation used during download or upload. By - default a 32KB buffer is used. + default a 32KB buffer is used. Maximum accepted value is + 256K. + +ENVIRONMENT + SSH_SCP_MODE + Specify mode for remote copy. If value is "sftp" will be used + sftp protocol. If value is "scp" will be used scp protocol. + Note any other value or if variable is not set means use scp pro- + tocol. EXIT STATUS - The scp utility exitsM-BM- 0 on success, andM-BM- >0 if an error occurs. + The scp utility exits 0 on success, and >0 if an error occurs. SEE ALSO sftp(1), ssh(1), ssh-add(1), ssh-agent(1), ssh-keygen(1), ssh_config(5), @@ -216,17 +169,14 @@ scp is based on the rcp program in BSD source code from the Regents of the University of California. - Since OpenSSH 9.0, scp has used the SFTP protocol for transfers by - default. - AUTHORS Timo Rinne Tatu Ylonen CAVEATS - The legacy SCP protocol (selected by the -O flag) requires execution of - the remote user's shell to perform glob(3) pattern matching. This - requires careful quoting of any characters that have special meaning to - the remote shell, such as quote characters. + The original SCP protocol (used by default) requires execution of the re- + mote user's shell to perform glob(3) pattern matching. This requires + careful quoting of any characters that have special meaning to the remote + shell, such as quote characters. -OpenBSD 7.3 December 16, 2022 OpenBSD 7.3 +BSD 10 January 2023 BSD diff -ruN openssh-9.4p1/scp.1 openssh-9.4p1+x509-14.2.1/scp.1 --- openssh-9.4p1/scp.1 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/scp.1 2023-08-20 10:07:00.000000000 +0300 @@ -1,3 +1,11 @@ +.\" Implement .Dd with the Mdocdate RCS keyword +.rn Dd xD +.de Dd +.ie \\$1$Mdocdate: \{\ +. xD \\$3 \\$2 \\$4 +.\} +.el .xD \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 +.. .\" .\" scp.1 .\" @@ -5,17 +13,18 @@ .\" .\" Copyright (c) 1995 Tatu Ylonen , Espoo, Finland .\" All rights reserved +.\" Copyright (c) 2011-2023 Roumen Petrov. All rights reserved. .\" .\" Created: Sun May 7 00:14:37 1995 ylo .\" .\" $OpenBSD: scp.1,v 1.112 2022/12/16 07:13:22 djm Exp $ .\" -.Dd $Mdocdate: December 16 2022 $ +.Dd $Mdocdate: January 10 2023 $ .Dt SCP 1 .Os .Sh NAME .Nm scp -.Nd OpenSSH secure file copy +.Nd Secure copy (remote file copy program) .Sh SYNOPSIS .Nm scp .Op Fl 346ABCOpqRrsTv @@ -34,11 +43,10 @@ .Nm copies files between hosts on a network. .Pp -.Nm -uses the SFTP protocol over a +It uses .Xr ssh 1 -connection for data transfer, and uses the same authentication and provides -the same security as a login session. +for data transfer, and uses the same authentication and provides the +same security as a login session. .Pp .Nm will ask for passwords or passphrases if they are needed for @@ -78,9 +86,7 @@ Copies between two remote hosts are transferred through the local host. Without this option the data is copied directly between the two remote hosts. -Note that, when using the legacy SCP protocol (via the -.Fl O -flag), this option +Note that, when using the original SCP protocol (the default), this option selects batch mode for the second host as .Nm cannot ask for passwords or passphrases for both hosts. @@ -112,7 +118,9 @@ This option is directly passed to .Xr ssh 1 . .It Fl D Ar sftp_server_path -Connect directly to a local SFTP server program rather than a +When using the SFTP protocol support via +.Fl s , +connect directly to a local SFTP server program rather than a remote one via .Xr ssh 1 . This option may be useful in debugging the client and server. @@ -143,12 +151,13 @@ .It Fl l Ar limit Limits the used bandwidth, specified in Kbit/s. .It Fl O -Use the legacy SCP protocol for file transfers instead of the SFTP protocol. +Use the original SCP protocol for file transfers instead of the SFTP protocol. Forcing the use of the SCP protocol may be necessary for servers that do not implement SFTP, for backwards-compatibility for particular filename wildcard patterns and for expanding paths with a .Sq ~ prefix for older SFTP servers. +This mode is the default. .It Fl o Ar ssh_option Can be used to pass options to .Nm ssh @@ -158,72 +167,8 @@ for which there is no separate .Nm scp command-line flag. -For full details of the options listed below, and their possible values, see +For full details of the options and their possible values, see .Xr ssh_config 5 . -.Pp -.Bl -tag -width Ds -offset indent -compact -.It AddressFamily -.It BatchMode -.It BindAddress -.It BindInterface -.It CanonicalDomains -.It CanonicalizeFallbackLocal -.It CanonicalizeHostname -.It CanonicalizeMaxDots -.It CanonicalizePermittedCNAMEs -.It CASignatureAlgorithms -.It CertificateFile -.It CheckHostIP -.It Ciphers -.It Compression -.It ConnectionAttempts -.It ConnectTimeout -.It ControlMaster -.It ControlPath -.It ControlPersist -.It GlobalKnownHostsFile -.It GSSAPIAuthentication -.It GSSAPIDelegateCredentials -.It HashKnownHosts -.It Host -.It HostbasedAcceptedAlgorithms -.It HostbasedAuthentication -.It HostKeyAlgorithms -.It HostKeyAlias -.It Hostname -.It IdentitiesOnly -.It IdentityAgent -.It IdentityFile -.It IPQoS -.It KbdInteractiveAuthentication -.It KbdInteractiveDevices -.It KexAlgorithms -.It KnownHostsCommand -.It LogLevel -.It MACs -.It NoHostAuthenticationForLocalhost -.It NumberOfPasswordPrompts -.It PasswordAuthentication -.It PKCS11Provider -.It Port -.It PreferredAuthentications -.It ProxyCommand -.It ProxyJump -.It PubkeyAcceptedAlgorithms -.It PubkeyAuthentication -.It RekeyLimit -.It RequiredRSASize -.It SendEnv -.It ServerAliveInterval -.It ServerAliveCountMax -.It SetEnv -.It StrictHostKeyChecking -.It TCPKeepAlive -.It UpdateHostKeys -.It User -.It UserKnownHostsFile -.It VerifyHostKeyDNS -.El .It Fl P Ar port Specifies the port to connect to on the remote host. Note that this option is written with a capital @@ -259,6 +204,13 @@ The program must understand .Xr ssh 1 options. +.It Fl s +Use the SFTP protocol for transfers rather than the original scp protocol. +.Pp +Note functionality is considered as experimental and is still under development. +In some cases requires specific SFTP server extension to work, +in other cases may fail. +As result is not considered as drop-in replacement of secure copy utility. .It Fl T Disable strict filename checking. By default when copying files from a remote host to a local directory @@ -286,12 +238,26 @@ Controls how many concurrent SFTP read or write requests may be in progress at any point in time during a download or upload. By default 64 requests may be active concurrently. +Maximum accepted value is 1024. .It Cm buffer Ns = Ns Ar value Controls the maximum buffer size for a single SFTP read/write operation used during download or upload. By default a 32KB buffer is used. +Maximum accepted value is 256K. .El .El +.Sh ENVIRONMENT +.Bl -tag -width Ds +.It Ev SSH_SCP_MODE +Specify mode for remote copy. +If value is +.Dq sftp +will be used sftp protocol. +If value is +.Dq scp +will be used scp protocol. +Note any other value or if variable is not set means use scp protocol. +.El .Sh EXIT STATUS .Ex -std scp .Sh SEE ALSO @@ -308,17 +274,12 @@ is based on the rcp program in .Bx source code from the Regents of the University of California. -.Pp -Since OpenSSH 9.0, -.Nm -has used the SFTP protocol for transfers by default. .Sh AUTHORS .An Timo Rinne Aq Mt tri@iki.fi .An Tatu Ylonen Aq Mt ylo@cs.hut.fi .Sh CAVEATS -The legacy SCP protocol (selected by the -.Fl O -flag) requires execution of the remote user's shell to perform +The original SCP protocol (used by default) requires execution of the +remote user's shell to perform .Xr glob 3 pattern matching. This requires careful quoting of any characters that have special meaning to diff -ruN openssh-9.4p1/scp.c openssh-9.4p1+x509-14.2.1/scp.c --- openssh-9.4p1/scp.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/scp.c 2023-08-20 10:07:01.000000000 +0300 @@ -17,6 +17,7 @@ /* * Copyright (c) 1999 Theo de Raadt. All rights reserved. * Copyright (c) 1999 Aaron Campbell. All rights reserved. + * Copyright (c) 2022-2023 Roumen Petrov. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -78,7 +79,7 @@ # include #endif #ifdef HAVE_POLL_H -#include +# include #else # ifdef HAVE_SYS_POLL_H # include @@ -142,7 +143,7 @@ #define COPY_BUFLEN 16384 -int do_cmd(char *, char *, char *, int, int, char *, int *, int *, pid_t *); +int do_cmd(const char *, char *, char *, int, int, char *, int *, int *, pid_t *); int do_cmd2(char *, char *, int, char *, int, int); /* Struct for addargs */ @@ -173,15 +174,18 @@ int sshport = -1; /* This is the program to execute for the secured connection. ("ssh" or -S) */ -char *ssh_program = _PATH_SSH_PROGRAM; +static const char *ssh_program = _PATH_SSH_PROGRAM; /* This is used to store the pid of ssh_program */ pid_t do_cmd_pid = -1; pid_t do_cmd_pid2 = -1; /* SFTP copy parameters */ -size_t sftp_copy_buflen; -size_t sftp_nrequests; +/* Set to zero to enforce defaults of 32768 and 64 respectively, + * see do_init() in sftp-client.c + */ +static size_t sftp_copy_buflen = 0; +static size_t sftp_nrequests = 0; /* Needed for sftp */ volatile sig_atomic_t interrupted = 0; @@ -235,7 +239,7 @@ pid_t pid; if (a->num == 0) - fatal("do_local_cmd: no arguments"); + fatal_f("no arguments"); if (verbose_mode) { fprintf(stderr, "Executing:"); @@ -244,7 +248,7 @@ fprintf(stderr, "\n"); } if ((pid = fork()) == -1) - fatal("do_local_cmd: fork: %s", strerror(errno)); + fatal_f("fork: %s", strerror(errno)); if (pid == 0) { execvp(a->list[0], a->list); @@ -259,7 +263,7 @@ while (waitpid(pid, &status, 0) == -1) if (errno != EINTR) - fatal("do_local_cmd: waitpid: %s", strerror(errno)); + fatal_f("waitpid: %s", strerror(errno)); do_cmd_pid = -1; @@ -276,7 +280,7 @@ */ int -do_cmd(char *program, char *host, char *remuser, int port, int subsystem, +do_cmd(const char *program, char *host, char *remuser, int port, int subsystem, char *cmd, int *fdin, int *fdout, pid_t *pid) { #ifdef USE_PIPES @@ -394,10 +398,10 @@ /* Fork a child to execute the command on the remote host using ssh. */ pid = fork(); if (pid == 0) { - if (dup2(fdin, 0) == -1) - perror("dup2"); - if (dup2(fdout, 1) == -1) - perror("dup2"); + if (dup2(fdin, STDIN_FILENO) == -1) + perror("dup2 stdin"); + if (dup2(fdout, STDOUT_FILENO) == -1) + perror("dup2 stdout"); replacearg(&args, 0, "%s", ssh_program); if (port != -1) { @@ -421,7 +425,7 @@ } while (waitpid(pid, &status, 0) == -1) if (errno != EINTR) - fatal("do_cmd2: waitpid: %s", strerror(errno)); + fatal_f("waitpid: %s", strerror(errno)); return 0; } @@ -436,7 +440,7 @@ void run_err(const char *,...) __attribute__((__format__ (printf, 1, 2))) __attribute__((__nonnull__ (1))); -int note_err(const char *,...) +void note_err(const char *,...) __attribute__((__format__ (printf, 1, 2))); void verifydir(char *); @@ -448,6 +452,9 @@ #define CMDNEEDS 64 char cmd[CMDNEEDS]; /* must hold "rcp -r -p -d\0" */ +static const char *cmdprefix = NULL; +static const char *cmdprefix2 = NULL; + enum scp_mode_e { MODE_SCP, MODE_SFTP @@ -474,7 +481,21 @@ const char *errstr; extern char *optarg; extern int optind; - enum scp_mode_e mode = MODE_SFTP; +/* NOTE "sftp mode" requires non-standard extension to + * sftp protocol version 3 - expand-path@openssh.com. + * - Last sftp version is 6. It is unlikely implementation that + * support sftp version greater than 3 to change code; + * - Implementation of sftp functionality with scp interface + * was rejected many times. Side effect is that users have + * enough time to change scripts to use sftp instead scp; + * - Implementation uses custom server extension. It is not + * part of current "enterprise" Linux releases. It is expected + * to be part of next "enterprise" Linux release but this + * requires a lot of time to be deployed in production. + * Based on above estimated usability of sftp based on scp + * command interface, is after 5 - 10 years (not before 2027). + */ + enum scp_mode_e mode = MODE_SCP; char *sftp_direct = NULL; long long llv; @@ -494,6 +515,11 @@ log_init(argv0, log_level, SYSLOG_FACILITY_USER, 2); +#ifdef __ANDROID__ +{ static char pathbuf[PATH_MAX]; + ssh_program = relocate_path(ssh_program, pathbuf, sizeof(pathbuf)); +} +#endif memset(&args, '\0', sizeof(args)); memset(&remote_remote_args, '\0', sizeof(remote_remote_args)); args.list = remote_remote_args.list = NULL; @@ -504,9 +530,17 @@ addargs(&args, "-oRemoteCommand=none"); addargs(&args, "-oRequestTTY=no"); +{ const char *s = getenv("SSH_SCP_MODE"); + if (s != NULL) { + if (strcmp(s, "sftp") == 0) + mode = MODE_SFTP; + else if (strcmp(s, "scp") == 0) + mode = MODE_SCP; + } +} fflag = Tflag = tflag = 0; while ((ch = getopt(argc, argv, - "12346ABCTdfOpqRrstvD:F:J:M:P:S:c:i:l:o:X:")) != -1) { + "12346ABCTdfOpqRrstvD:F:J:M:P:S:X:c:i:l:o:")) != -1) { switch (ch) { /* User-visible flags. */ case '1': @@ -515,9 +549,9 @@ case '2': /* Ignored */ break; - case 'A': case '4': case '6': + case 'A': case 'C': addargs(&args, "-%c", ch); addargs(&remote_remote_args, "-%c", ch); @@ -590,22 +624,24 @@ case 'X': /* Please keep in sync with sftp.c -X */ if (strncmp(optarg, "buffer=", 7) == 0) { - r = scan_scaled(optarg + 7, &llv); + optarg += 7; + r = scan_scaled(optarg, &llv); if (r == 0 && (llv <= 0 || llv > 256 * 1024)) { r = -1; errno = EINVAL; } if (r == -1) { fatal("Invalid buffer size \"%s\": %s", - optarg + 7, strerror(errno)); + optarg, strerror(errno)); } sftp_copy_buflen = (size_t)llv; } else if (strncmp(optarg, "nrequests=", 10) == 0) { - llv = strtonum(optarg + 10, 1, 256 * 1024, + optarg += 10; + llv = strtonum(optarg, 1, 1024/*RLIMIT_NOFILE?*/, &errstr); if (errstr != NULL) { fatal("Invalid number of requests " - "\"%s\": %s", optarg + 10, errstr); + "\"%s\": %s", optarg, errstr); } sftp_nrequests = (size_t)llv; } else { @@ -689,6 +725,12 @@ iamrecursive ? " -r" : "", pflag ? " -p" : "", targetshouldbedirectory ? " -d" : ""); + /* mainly for testing purposes */ + cmdprefix = getenv("SCP_REMOTE_PREFIX"); + if (cmdprefix == NULL) cmdprefix=""; + cmdprefix2 = getenv("SCP_REMOTE_PREFIX2"); + if (cmdprefix2 == NULL) cmdprefix2=cmdprefix; + (void) ssh_signal(SIGPIPE, lostconn); if (colon(argv[argc - 1])) /* Dest is remote host. */ @@ -838,12 +880,12 @@ int sel_start, int sel_end, char ***patternsp, size_t *npatternsp) { char *cp; - size_t pattern_len; int o = 0, tail_len; - if ((pattern_len = strlen(pattern)) == 0 || pattern_len >= INT_MAX) +{ size_t pattern_len = strlen(pattern); + if (pattern_len == 0 || pattern_len >= INT_MAX) return -1; - +} tail_len = strlen(pattern + brace_end + 1); if ((cp = malloc(brace_start + (sel_end - sel_start) + tail_len + 1)) == NULL) @@ -1024,6 +1066,11 @@ } else { freeargs(&args); addargs(&args, "sftp-server"); + if (verbose_mode) { + addargs(&args, "-e"); + addargs(&args, "-l"); + addargs(&args, "DEBUG3"); + } if (do_cmd(sftp_direct, host, NULL, -1, 0, "sftp", reminp, remoutp, pidp) < 0) return NULL; @@ -1041,7 +1088,6 @@ struct sftp_conn *conn = NULL, *conn2 = NULL; arglist alist; int i, r, status; - struct stat sb; u_int j; memset(&alist, '\0', sizeof(alist)); @@ -1122,23 +1168,23 @@ ++errs; do_cmd_pid2 = -1; continue; - } else { - xasprintf(&bp, "%s -f %s%s", cmd, - *src == '-' ? "-- " : "", src); - if (do_cmd(ssh_program, host, suser, sport, 0, - bp, &remin, &remout, &do_cmd_pid) < 0) - exit(1); - free(bp); - xasprintf(&bp, "%s -t %s%s", cmd, - *targ == '-' ? "-- " : "", targ); - if (do_cmd2(thost, tuser, tport, bp, - remin, remout) < 0) - exit(1); - free(bp); - (void) close(remin); - (void) close(remout); - remin = remout = -1; } + /* SCP */ + xasprintf(&bp, "%s%s -f %s%s", cmdprefix, cmd, + *src == '-' ? "-- " : "", src); + if (do_cmd(ssh_program, host, suser, sport, 0, + bp, &remin, &remout, &do_cmd_pid) < 0) + exit(1); + free(bp); + xasprintf(&bp, "%s%s -t %s%s", cmdprefix2, cmd, + *targ == '-' ? "-- " : "", targ); + if (do_cmd2(thost, tuser, tport, bp, + remin, remout) < 0) + exit(1); + free(bp); + (void) close(remin); + (void) close(remout); + remin = remout = -1; } else if (host) { /* standard remote to remote */ /* * Second remote user is passed to first remote side @@ -1175,7 +1221,7 @@ } addargs(&alist, "--"); addargs(&alist, "%s", host); - addargs(&alist, "%s", cmd); + addargs(&alist, "%s%s", cmdprefix, cmd); addargs(&alist, "%s", src); addargs(&alist, "%s%s%s:%s", tuser ? tuser : "", tuser ? "@" : "", @@ -1184,11 +1230,14 @@ errs = 1; } else { /* local to remote */ if (mode == MODE_SFTP) { - /* no need to glob: already done by shell */ + { struct stat sb; + /* NOTE: glob already done by shell */ if (stat(argv[i], &sb) != 0) { - fatal("stat local \"%s\": %s", argv[i], + error("local %s: %s", argv[i], strerror(errno)); + continue; } + } if (remin == -1) { /* Connect to remote now */ conn = do_sftp_connect(thost, tuser, @@ -1206,7 +1255,7 @@ } /* SCP */ if (remin == -1) { - xasprintf(&bp, "%s -t %s%s", cmd, + xasprintf(&bp, "%s%s -t %s%s", cmdprefix, cmd, *targ == '-' ? "-- " : "", targ); if (do_cmd(ssh_program, thost, tuser, tport, 0, bp, &remin, &remout, &do_cmd_pid) < 0) @@ -1234,7 +1283,6 @@ { char *bp, *host = NULL, *src = NULL, *suser = NULL; arglist alist; - struct sftp_conn *conn = NULL; int i, r, sport = -1; memset(&alist, '\0', sizeof(alist)); @@ -1272,6 +1320,8 @@ } /* Remote to local. */ if (mode == MODE_SFTP) { + struct sftp_conn *conn; + conn = do_sftp_connect(host, suser, sport, sftp_direct, &remin, &remout, &do_cmd_pid); if (conn == NULL) { @@ -1290,7 +1340,7 @@ continue; } /* SCP */ - xasprintf(&bp, "%s -f %s%s", + xasprintf(&bp, "%s%s -f %s%s", cmdprefix, cmd, *src == '-' ? "-- " : "", src); if (do_cmd(ssh_program, host, suser, sport, 0, bp, &remin, &remout, &do_cmd_pid) < 0) { @@ -1312,17 +1362,18 @@ static char * prepare_remote_path(struct sftp_conn *conn, const char *path) { - size_t nslash; - /* Handle ~ prefixed paths */ if (*path == '\0' || strcmp(path, "~") == 0) return xstrdup("."); if (*path != '~') return xstrdup(path); if (strncmp(path, "~/", 2) == 0) { - if ((nslash = strspn(path + 2, "/")) == strlen(path + 2)) + size_t nslash; + path += 2; + nslash = strspn(path, "/"); + if (nslash == strlen(path)) return xstrdup("."); - return xstrdup(path + 2 + nslash); + return xstrdup(path + nslash); } if (can_expand_path(conn)) return do_expand_path(conn, path); @@ -1337,13 +1388,13 @@ { char *target = NULL, *filename = NULL, *abs_dst = NULL; int src_is_dir, target_is_dir; - Attrib a; struct stat st; - memset(&a, '\0', sizeof(a)); - if (stat(src, &st) != 0) - fatal("stat local \"%s\": %s", src, strerror(errno)); + UNUSED(argc); + if (stat(src, &st) == -1) + fatal("local stat \"%s\": %s", src, strerror(errno)); src_is_dir = S_ISDIR(st.st_mode); + if ((filename = basename(src)) == NULL) fatal("basename \"%s\": %s", src, strerror(errno)); @@ -1355,6 +1406,8 @@ cleanup_exit(255); target_is_dir = remote_is_dir(conn, target); if (targetshouldbedirectory && !target_is_dir) { + Attrib a; + memset(&a, '\0', sizeof(a)); debug("target directory \"%s\" does not exist", target); a.flags = SSH2_FILEXFER_ATTR_PERMISSIONS; a.perm = st.st_mode | 0700; /* ensure writable */ @@ -1553,9 +1606,9 @@ char *abs_dst = NULL; glob_t g; char *filename, *tmp = NULL; - int i, r, err = 0, dst_is_dir; - struct stat st; + int i, r, err = 0, dst_is_dir = 0; + UNUSED(argc); memset(&g, 0, sizeof(g)); /* @@ -1592,19 +1645,23 @@ } } - if ((r = stat(dst, &st)) != 0) +{ struct stat st; + r = stat(dst, &st); + if (r != -1) + dst_is_dir = S_ISDIR(st.st_mode); + else debug2_f("stat local \"%s\": %s", dst, strerror(errno)); - dst_is_dir = r == 0 && S_ISDIR(st.st_mode); +} if (g.gl_matchc > 1 && !dst_is_dir) { - if (r == 0) { + if (r != -1) { /* chech stat result */ error("Multiple files match pattern, but destination " "\"%s\" is not a directory", dst); err = -1; goto out; } debug2_f("creating destination \"%s\"", dst); - if (mkdir(dst, 0777) != 0) { + if (mkdir(dst, 0777) == -1) { error("local mkdir \"%s\": %s", dst, strerror(errno)); err = -1; goto out; @@ -1693,7 +1750,7 @@ verifydir(targ); (void) atomicio(vwrite, remout, "", 1); - if (stat(targ, &stb) == 0 && S_ISDIR(stb.st_mode)) + if (stat(targ, &stb) != -1 && S_ISDIR(stb.st_mode)) targisdir = 1; if (src != NULL && !iamrecursive && !Tflag) { /* @@ -1833,7 +1890,7 @@ } else np = targ; curfile = cp; - exists = stat(np, &stb) == 0; + exists = stat(np, &stb) != -1; if (buf[0] == 'D') { int mod_flag = pflag; if (!iamrecursive) @@ -1874,13 +1931,14 @@ continue; } cp = bp->buf; - wrerr = 0; /* * NB. do not use run_err() unless immediately followed by * exit() below as it may send a spurious reply that might * desyncronise us from the peer. Use note_err() instead. */ + wrerr = 0; + statbytes = 0; if (showprogress) start_progress_meter(curfile, size, &statbytes); @@ -1918,49 +1976,57 @@ } } unset_nonblock(remin); - if (count != 0 && !wrerr && + if (!wrerr && count != 0 && atomicio(vwrite, ofd, bp->buf, count) != count) { note_err("%s: %s", np, strerror(errno)); wrerr = 1; } if (!wrerr && (!exists || S_ISREG(stb.st_mode)) && - ftruncate(ofd, size) != 0) + ftruncate(ofd, size) != 0) { note_err("%s: truncate: %s", np, strerror(errno)); + wrerr = 1; + } if (pflag) { - if (exists || omode != mode) + if (!wrerr && (exists || omode != mode)) #ifdef HAVE_FCHMOD - if (fchmod(ofd, omode)) { + if (fchmod(ofd, omode) == -1) { #else /* HAVE_FCHMOD */ - if (chmod(np, omode)) { + if (chmod(np, omode) == -1) { #endif /* HAVE_FCHMOD */ note_err("%s: set mode: %s", np, strerror(errno)); + wrerr = 1; } } else { - if (!exists && omode != mode) + if (!wrerr && (!exists && omode != mode)) #ifdef HAVE_FCHMOD - if (fchmod(ofd, omode & ~mask)) { + if (fchmod(ofd, omode & ~mask) == -1) { #else /* HAVE_FCHMOD */ - if (chmod(np, omode & ~mask)) { + if (chmod(np, omode & ~mask) == -1) { #endif /* HAVE_FCHMOD */ note_err("%s: set mode: %s", np, strerror(errno)); + wrerr = 1; } } - if (close(ofd) == -1) + if (close(ofd) == -1) { note_err("%s: close: %s", np, strerror(errno)); + wrerr = 1; + } (void) response(); if (showprogress) stop_progress_meter(); - if (setimes && !wrerr) { + if (!wrerr && setimes) { setimes = 0; if (utimes(np, tv) == -1) { note_err("%s: set times: %s", np, strerror(errno)); + wrerr = 1; } } - /* If no error was noted then signal success for this file */ - if (note_err(NULL) == 0) + if (wrerr) + note_err(NULL); + else (void) atomicio(vwrite, remout, "", 1); } done: @@ -2138,35 +2204,34 @@ } /* - * Notes a sink error for sending at the end of a file transfer. Returns 0 if - * no error has been noted or -1 otherwise. Use note_err(NULL) to flush - * any active error at the end of the transfer. + * Notes a sink error for sending at the end of a file transfer. + * Use note_err(NULL) to flush any active error at the end of the transfer. */ -int +void note_err(const char *fmt, ...) { - static char *emsg; - va_list ap; + static char *emsg = NULL; /* Replay any previously-noted error */ if (fmt == NULL) { - if (emsg == NULL) - return 0; + if (emsg == NULL) return; + run_err("%s", emsg); free(emsg); emsg = NULL; - return -1; + return; } errs++; /* Prefer first-noted error */ - if (emsg != NULL) - return -1; + if (emsg != NULL) return; + +{ va_list ap; va_start(ap, fmt); vasnmprintf(&emsg, INT_MAX, NULL, fmt, ap); va_end(ap); - return -1; +} } void @@ -2174,7 +2239,7 @@ { struct stat stb; - if (!stat(cp, &stb)) { + if (stat(cp, &stb) != -1) { if (S_ISDIR(stb.st_mode)) return; errno = ENOTDIR; diff -ruN openssh-9.4p1/SECURITY.md openssh-9.4p1+x509-14.2.1/SECURITY.md --- openssh-9.4p1/SECURITY.md 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/SECURITY.md 1970-01-01 02:00:00.000000000 +0200 @@ -1,5 +0,0 @@ -# Reporting OpenSSH Security Issues - -To report security issues in OpenSSH, please refer to our website -[OpenSSH Security](https://www.openssh.com/security.html). - diff -ruN openssh-9.4p1/servconf.c openssh-9.4p1+x509-14.2.1/servconf.c --- openssh-9.4p1/servconf.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/servconf.c 2023-08-20 10:07:01.000000000 +0300 @@ -8,14 +8,41 @@ * software must be clearly marked as such, and if the derived work is * incompatible with the protocol description in the RFC file, it must be * called by a name other than "ssh" or "Secure Shell". + * + * Copyright (c) 2002-2023 Roumen Petrov. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "includes.h" +#if !defined(HAVE_SYS_VALID_RDOMAIN) && defined(HAVE_SYS_SYSCTL_H) +# if defined(__OpenBSD__) +# define USE_SYSCTL_NET +# endif +#endif + #include #include -#include -#ifdef __OpenBSD__ +#ifdef USE_SYSCTL_NET #include #endif @@ -53,6 +80,7 @@ #include "sshbuf.h" #include "misc.h" #include "servconf.h" +#include "ssh-xkalg.h" #include "pathnames.h" #include "cipher.h" #include "sshkey.h" @@ -63,7 +91,6 @@ #include "groupaccess.h" #include "canohost.h" #include "packet.h" -#include "ssherr.h" #include "hostfile.h" #include "auth.h" #include "myproposal.h" @@ -77,10 +104,16 @@ const char *filename, struct sshbuf *conf, struct include_list *includes, struct connection_info *connectinfo, int flags, int *activep, int depth); +/* used in kex.c */ +extern char *server_pkalgs; + /* Use of privilege separation or not */ extern int use_privsep; extern struct sshbuf *cfg; +/* used in ssh-rsa.c */ +extern int required_rsa_size; + /* Initializes the server options to their default values. */ void @@ -91,6 +124,26 @@ /* Portable-specific options */ options->use_pam = -1; + /* X.509 Standard Options */ + options->hostbased_algorithms = NULL; + options->pubkey_algorithms = NULL; + options->accepted_algorithms = NULL; + ssh_x509flags_initialize(&options->x509flags, 1); + X509StoreOptions_init(&options->ca); +#ifdef LDAP_ENABLED + options->ca_ldap_url = NULL; + options->ca_ldap_ver = NULL; +#endif +#ifdef USE_OPENSSL_STORE2 + options->num_store_uri = 0; + options->store_uri = NULL; +#endif +#ifdef SSH_OCSP_ENABLED + options->va.type = -1; + options->va.certificate_file = NULL; + options->va.responder_url = NULL; +#endif /*def SSH_OCSP_ENABLED*/ + /* Standard Options */ options->num_ports = 0; options->ports_from_cmdline = 0; @@ -104,6 +157,7 @@ options->num_host_cert_files = 0; options->host_key_agent = NULL; options->pid_file = NULL; + options->moduli_file = NULL; options->login_grace_time = -1; options->permit_root_login = PERMIT_NOT_SET; options->ignore_rhosts = -1; @@ -122,13 +176,12 @@ options->log_level = SYSLOG_LEVEL_NOT_SET; options->num_log_verbose = 0; options->log_verbose = NULL; + options->num_auth_methods = 0; + options->auth_methods = NULL; options->hostbased_authentication = -1; options->hostbased_uses_name_from_packet_only = -1; - options->hostbased_accepted_algos = NULL; options->hostkeyalgorithms = NULL; options->pubkey_authentication = -1; - options->pubkey_auth_options = -1; - options->pubkey_accepted_algos = NULL; options->kerberos_authentication = -1; options->kerberos_or_local_passwd = -1; options->kerberos_ticket_cleanup = -1; @@ -182,7 +235,6 @@ options->authorized_keys_command = NULL; options->authorized_keys_command_user = NULL; options->revoked_keys_file = NULL; - options->sk_provider = NULL; options->trusted_user_ca_keys = NULL; options->authorized_principals_file = NULL; options->authorized_principals_command = NULL; @@ -209,44 +261,32 @@ static void assemble_algorithms(ServerOptions *o) { - char *all_cipher, *all_mac, *all_kex, *all_key, *all_sig; - char *def_cipher, *def_mac, *def_kex, *def_key, *def_sig; + char *all; int r; - - all_cipher = cipher_alg_list(',', 0); - all_mac = mac_alg_list(','); - all_kex = kex_alg_list(','); - all_key = sshkey_alg_list(0, 0, 1, ','); - all_sig = sshkey_alg_list(0, 1, 1, ','); - /* remove unsupported algos from default lists */ - def_cipher = match_filter_allowlist(KEX_SERVER_ENCRYPT, all_cipher); - def_mac = match_filter_allowlist(KEX_SERVER_MAC, all_mac); - def_kex = match_filter_allowlist(KEX_SERVER_KEX, all_kex); - def_key = match_filter_allowlist(KEX_DEFAULT_PK_ALG, all_key); - def_sig = match_filter_allowlist(SSH_ALLOWED_CA_SIGALGS, all_sig); #define ASSEMBLE(what, defaults, all) \ do { \ - if ((r = kex_assemble_names(&o->what, defaults, all)) != 0) \ + char *def = match_filter_allowlist(defaults, all); \ + if ((r = kex_assemble_names(&o->what, def, all)) != 0) \ fatal_fr(r, "%s", #what); \ + free(def); \ } while (0) - ASSEMBLE(ciphers, def_cipher, all_cipher); - ASSEMBLE(macs, def_mac, all_mac); - ASSEMBLE(kex_algorithms, def_kex, all_kex); - ASSEMBLE(hostkeyalgorithms, def_key, all_key); - ASSEMBLE(hostbased_accepted_algos, def_key, all_key); - ASSEMBLE(pubkey_accepted_algos, def_key, all_key); - ASSEMBLE(ca_sign_algorithms, def_sig, all_sig); + + all = cipher_alg_list(',', 0); + ASSEMBLE(ciphers, KEX_SERVER_ENCRYPT, all); + free(all); + + all = mac_alg_list(','); + ASSEMBLE(macs, KEX_SERVER_MAC, all); + free(all); + + all = kex_alg_list(','); + ASSEMBLE(kex_algorithms, KEX_SERVER_KEX, all); + free(all); + + all = sshkey_alg_list(0, 1, 1, ','); + ASSEMBLE(ca_sign_algorithms, SSH_ALLOWED_CA_SIGALGS, all); + free(all); #undef ASSEMBLE - free(all_cipher); - free(all_mac); - free(all_kex); - free(all_key); - free(all_sig); - free(def_cipher); - free(def_mac); - free(def_kex); - free(def_key); - free(def_sig); } void @@ -281,6 +321,27 @@ if (options->use_pam == -1) options->use_pam = 0; + /* X.509 Standard Options */ + /* options->hostbased_algorithms */ + /* options->pubkey_algorithms */ + /* options->accepted_algorithms */ + fill_default_xkalg(); + ssh_x509flags_defaults(&options->x509flags); + memcpy(&ssh_x509flags, &options->x509flags, sizeof(ssh_x509flags)); + X509StoreOptions_system_defaults(&options->ca); + (void)ssh_x509store_addlocations(&options->ca); +#ifdef LDAP_ENABLED + (void)ssh_x509store_addldapurl(options->ca_ldap_url, options->ca_ldap_ver); +#endif +#ifdef USE_OPENSSL_STORE2 + (void)ssh_x509store_adduri(options->store_uri, options->num_store_uri); +#endif +#ifdef SSH_OCSP_ENABLED + if (options->va.type == -1) + options->va.type = ssh_get_default_vatype(); + ssh_set_validator(&options->va); +#endif /*def SSH_OCSP_ENABLED*/ + /* Standard Options */ if (options->num_host_key_files == 0) { /* fill default hostkeys for protocols */ @@ -306,8 +367,7 @@ add_listen_addr(options, NULL, NULL, 0); if (options->pid_file == NULL) options->pid_file = xstrdup(_PATH_SSH_DAEMON_PID_FILE); - if (options->moduli_file == NULL) - options->moduli_file = xstrdup(_PATH_DH_MODULI); + /* options->moduli_file = NULL; */ if (options->login_grace_time == -1) options->login_grace_time = 120; if (options->permit_root_login == PERMIT_NOT_SET) @@ -346,8 +406,6 @@ options->hostbased_uses_name_from_packet_only = 0; if (options->pubkey_authentication == -1) options->pubkey_authentication = 1; - if (options->pubkey_auth_options == -1) - options->pubkey_auth_options = 0; if (options->kerberos_authentication == -1) options->kerberos_authentication = 0; if (options->kerberos_or_local_passwd == -1) @@ -397,8 +455,8 @@ options->max_startups_rate = 30; /* 30% */ if (options->max_startups_begin == -1) options->max_startups_begin = 10; - if (options->per_source_max_startups == -1) - options->per_source_max_startups = INT_MAX; + if (options->per_source_max_startups < -1) + options->per_source_max_startups = -1; if (options->per_source_masklen_ipv4 == -1) options->per_source_masklen_ipv4 = 32; if (options->per_source_masklen_ipv6 == -1) @@ -441,10 +499,16 @@ options->disable_forwarding = 0; if (options->expose_userauth_info == -1) options->expose_userauth_info = 0; - if (options->sk_provider == NULL) - options->sk_provider = xstrdup("internal"); if (options->required_rsa_size == -1) - options->required_rsa_size = SSH_RSA_MINIMUM_MODULUS_SIZE; + /* get default */ + options->required_rsa_size = required_rsa_size; + else { + /* transfer */ + if (options->required_rsa_size < required_rsa_size) + fatal("RSA key size %d is less then minimum %d.", + options->required_rsa_size, required_rsa_size); + required_rsa_size = options->required_rsa_size; + } if (options->unused_connection_timeout == -1) options->unused_connection_timeout = 0; @@ -476,7 +540,6 @@ CLEAR_ON_NONE(options->banner); CLEAR_ON_NONE(options->trusted_user_ca_keys); CLEAR_ON_NONE(options->revoked_keys_file); - CLEAR_ON_NONE(options->sk_provider); CLEAR_ON_NONE(options->authorized_principals_file); CLEAR_ON_NONE(options->adm_forced_command); CLEAR_ON_NONE(options->chroot_directory); @@ -489,9 +552,41 @@ CLEAR_ON_NONE(options->host_cert_files[i]); CLEAR_ON_NONE_ARRAY(channel_timeouts, num_channel_timeouts, "none"); + CLEAR_ON_NONE_ARRAY(log_verbose, num_log_verbose, "none"); CLEAR_ON_NONE_ARRAY(auth_methods, num_auth_methods, "any"); #undef CLEAR_ON_NONE #undef CLEAR_ON_NONE_ARRAY + + if (options->hostbased_algorithms != NULL) { + if (!sshkey_names_valid2(options->hostbased_algorithms, 1, 0)) + fatal("Bad protocol 2 hostbased algorithms '%s'.", + options->hostbased_algorithms); + } else + options->hostbased_algorithms = xstrdup("*"); + + if (options->pubkey_algorithms != NULL) { + if (!sshkey_names_valid2(options->pubkey_algorithms, 1, 0)) + fatal("Bad protocol 2 public key algorithms '%s'.", + options->pubkey_algorithms); + } else + options->pubkey_algorithms = xstrdup("*"); + + if (options->hostkeyalgorithms != NULL) { + if (!sshkey_names_valid2(options->hostkeyalgorithms, 1, 0)) + fatal("Bad protocol 2 host key algorithms '%s'.", + options->hostkeyalgorithms); + } else + options->hostkeyalgorithms = xstrdup("*"); + + if (options->accepted_algorithms != NULL) { + if (!sshkey_names_valid2(options->accepted_algorithms, 1, 0)) + fatal("Bad protocol 2 key algorithms '%s'.", + options->accepted_algorithms); + } else + options->accepted_algorithms = xstrdup("*"); + + server_pkalgs = ssh_get_allnames(',', 0, options->accepted_algorithms); + verbose("announced algorithms: %s", server_pkalgs); } /* Keyword tokens. */ @@ -499,12 +594,27 @@ sBadOption, /* == unknown option */ /* Portable-specific options */ sUsePAM, + /* X.509 Standard Options */ + sHostbasedAlgorithms, + sPubkeyAlgorithms, + sAcceptedAlgorithms, + sX509KeyAlgorithm, + sAllowedClientCertPurpose, + sKeyAllowSelfIssued, sMandatoryCRL, + sValidateFirst, + sCACertificateFile, sCACertificatePath, + sCARevocationFile, sCARevocationPath, + sCAStoreURI, + sCAldapVersion, sCAldapURL, + sVAType, sVACertificateFile, + sVAOCSPResponderURL, /* Standard Options */ sPort, sHostKeyFile, sLoginGraceTime, sPermitRootLogin, sLogFacility, sLogLevel, sLogVerbose, sKerberosAuthentication, sKerberosOrLocalPasswd, sKerberosTicketCleanup, - sKerberosGetAFSToken, sPasswordAuthentication, - sKbdInteractiveAuthentication, sListenAddress, sAddressFamily, + sKerberosGetAFSToken, + sPasswordAuthentication, sKbdInteractiveAuthentication, + sListenAddress, sAddressFamily, sPrintMotd, sPrintLastLog, sIgnoreRhosts, sX11Forwarding, sX11DisplayOffset, sX11UseLocalhost, sPermitTTY, sStrictModes, sEmptyPasswd, sTCPKeepAlive, @@ -529,7 +639,7 @@ sAuthenticationMethods, sHostKeyAgent, sPermitUserRC, sStreamLocalBindMask, sStreamLocalBindUnlink, sAllowStreamLocalForwarding, sFingerprintHash, sDisableForwarding, - sExposeAuthInfo, sRDomain, sPubkeyAuthOptions, sSecurityKeyProvider, + sExposeAuthInfo, sRDomain, sRequiredRSASize, sChannelTimeout, sUnusedConnectionTimeout, sDeprecated, sIgnore, sUnsupported } ServerOpCodes; @@ -553,6 +663,25 @@ { "usepam", sUnsupported, SSHCFG_GLOBAL }, #endif { "pamauthenticationviakbdint", sDeprecated, SSHCFG_GLOBAL }, + /* X.509 Standard Options */ + { "hostbasedalgorithms", sHostbasedAlgorithms, SSHCFG_ALL }, + { "pubkeyalgorithms", sPubkeyAlgorithms, SSHCFG_ALL }, + { "acceptedalgorithms", sAcceptedAlgorithms, SSHCFG_ALL }, + { "x509keyalgorithm", sX509KeyAlgorithm, SSHCFG_GLOBAL }, + { "allowedcertpurpose", sAllowedClientCertPurpose, SSHCFG_GLOBAL }, + { "keyallowselfissued", sKeyAllowSelfIssued, SSHCFG_GLOBAL } , + { "mandatorycrl", sMandatoryCRL, SSHCFG_GLOBAL } , + { "validatefirst", sValidateFirst, SSHCFG_GLOBAL } , + { "cacertificatefile", sCACertificateFile, SSHCFG_GLOBAL }, + { "cacertificatepath", sCACertificatePath, SSHCFG_GLOBAL }, + { "carevocationfile", sCARevocationFile, SSHCFG_GLOBAL }, + { "carevocationpath", sCARevocationPath, SSHCFG_GLOBAL }, + { "castoreuri", sCAStoreURI, SSHCFG_GLOBAL }, /* experimental, i.e. no documentation */ + { "caldapversion", sCAldapVersion, SSHCFG_GLOBAL }, + { "caldapurl", sCAldapURL, SSHCFG_GLOBAL }, + { "vatype", sVAType, SSHCFG_GLOBAL }, + { "vacertificatefile", sVACertificateFile, SSHCFG_GLOBAL }, + { "vaocspresponderurl", sVAOCSPResponderURL, SSHCFG_GLOBAL }, /* Standard Options */ { "port", sPort, SSHCFG_GLOBAL }, { "hostkey", sHostKeyFile, SSHCFG_GLOBAL }, @@ -578,7 +707,6 @@ { "pubkeyauthentication", sPubkeyAuthentication, SSHCFG_ALL }, { "pubkeyacceptedalgorithms", sPubkeyAcceptedAlgorithms, SSHCFG_ALL }, { "pubkeyacceptedkeytypes", sPubkeyAcceptedAlgorithms, SSHCFG_ALL }, /* obsolete */ - { "pubkeyauthoptions", sPubkeyAuthOptions, SSHCFG_ALL }, { "dsaauthentication", sPubkeyAuthentication, SSHCFG_GLOBAL }, /* alias */ #ifdef KRB5 { "kerberosauthentication", sKerberosAuthentication, SSHCFG_ALL }, @@ -609,7 +737,7 @@ { "passwordauthentication", sPasswordAuthentication, SSHCFG_ALL }, { "kbdinteractiveauthentication", sKbdInteractiveAuthentication, SSHCFG_ALL }, { "challengeresponseauthentication", sKbdInteractiveAuthentication, SSHCFG_ALL }, /* alias */ - { "skeyauthentication", sKbdInteractiveAuthentication, SSHCFG_ALL }, /* alias */ + { "skeyauthentication", sDeprecated, SSHCFG_GLOBAL }, { "checkmail", sDeprecated, SSHCFG_GLOBAL }, { "listenaddress", sListenAddress, SSHCFG_GLOBAL }, { "addressfamily", sAddressFamily, SSHCFG_GLOBAL }, @@ -657,7 +785,7 @@ { "clientalivecountmax", sClientAliveCountMax, SSHCFG_ALL }, { "authorizedkeysfile", sAuthorizedKeysFile, SSHCFG_ALL }, { "authorizedkeysfile2", sDeprecated, SSHCFG_ALL }, - { "useprivilegeseparation", sDeprecated, SSHCFG_GLOBAL}, + { "useprivilegeseparation", sUsePrivilegeSeparation, SSHCFG_GLOBAL}, { "acceptenv", sAcceptEnv, SSHCFG_ALL }, { "setenv", sSetEnv, SSHCFG_ALL }, { "permittunnel", sPermitTunnel, SSHCFG_ALL }, @@ -687,9 +815,12 @@ { "fingerprinthash", sFingerprintHash, SSHCFG_GLOBAL }, { "disableforwarding", sDisableForwarding, SSHCFG_ALL }, { "exposeauthinfo", sExposeAuthInfo, SSHCFG_ALL }, +#ifdef ENABLE_ROUTING_DOMAIN { "rdomain", sRDomain, SSHCFG_ALL }, +#else + { "rdomain", sUnsupported, SSHCFG_ALL }, +#endif { "casignaturealgorithms", sCASignatureAlgorithms, SSHCFG_ALL }, - { "securitykeyprovider", sSecurityKeyProvider, SSHCFG_GLOBAL }, { "requiredrsasize", sRequiredRSASize, SSHCFG_ALL }, { "channeltimeout", sChannelTimeout, SSHCFG_ALL }, { "unusedconnectiontimeout", sUnusedConnectionTimeout, SSHCFG_ALL }, @@ -827,7 +958,7 @@ { #if defined(HAVE_SYS_VALID_RDOMAIN) return sys_valid_rdomain(name); -#elif defined(__OpenBSD__) +#elif defined(USE_SYSCTL_NET) const char *errstr; long long num; struct rt_tableinfo info; @@ -851,7 +982,8 @@ return 0; return 1; -#else /* defined(__OpenBSD__) */ +#else /* defined(USE_SYSCTL_NET) */ + UNUSED(name); error("Routing domains are not supported on this platform"); return 0; #endif @@ -958,10 +1090,10 @@ /* Parse a ChannelTimeout clause "pattern=interval" */ static int -parse_timeout(const char *s, char **typep, int *secsp) +parse_timeout(const char *s, char **typep, long *secsp) { char *cp, *sdup; - int secs; + long secs; if (typep != NULL) *typep = NULL; @@ -992,13 +1124,13 @@ void process_channel_timeouts(struct ssh *ssh, ServerOptions *options) { - int secs; u_int i; - char *type; debug3_f("setting %u timeouts", options->num_channel_timeouts); channel_clear_timeouts(ssh); for (i = 0; i < options->num_channel_timeouts; i++) { + char *type; + long secs; if (parse_timeout(options->channel_timeouts[i], &type, &secs) != 0) { fatal_f("internal error: bad timeout %s", @@ -1012,7 +1144,15 @@ struct connection_info * get_connection_info(struct ssh *ssh, int populate, int use_dns) { - static struct connection_info ci; + static struct connection_info ci = { + NULL /* user */, + NULL /* host */, + NULL /* address */, + NULL /* laddress */, + -1 /* lport */, + NULL /* rdomain */, + 0 /* test */ + }; if (ssh == NULL || !populate) return &ci; @@ -1113,29 +1253,21 @@ ci->laddress ? ci->laddress : "(null)", ci->lport); while ((attrib = strdelim(&cp)) && *attrib != '\0') { - /* Terminate on comment */ - if (*attrib == '#') { - cp = NULL; /* mark all arguments consumed */ - break; - } - arg = NULL; attributes++; /* Criterion "all" has no argument and must appear alone */ if (strcasecmp(attrib, "all") == 0) { if (attributes > 1 || ((arg = strdelim(&cp)) != NULL && - *arg != '\0' && *arg != '#')) { + *arg != '\0')) { error("'all' cannot be combined with other " "Match attributes"); return -1; } - if (arg != NULL && *arg == '#') - cp = NULL; /* mark all arguments consumed */ *condition = cp; return 1; } /* All other criteria require an argument */ if ((arg = strdelim(&cp)) == NULL || - *arg == '\0' || *arg == '#') { + *arg == '\0') { error("Missing Match criteria for %s", attrib); return -1; } @@ -1269,11 +1401,29 @@ return result; } +static int +parse_time(const char *arg, const char *filename, int linenum) +{ + long t = convtime(arg); + + if (t == -1) { + error("%s line %d: invalid time value.", filename, linenum); + return -1; + } +#if SIZEOF_LONG_INT > SIZEOF_INT + if (t > INT_MAX) { + error("%s line %d: time value too high.", filename, linenum); + return -1; + } +#endif + return (int)t; /*safe cast*/ +} + #define WHITESPACE " \t\r\n" /* Multistate option parsing */ struct multistate { - char *key; + const char *key; int value; }; static const struct multistate multistate_flag[] = { @@ -1284,7 +1434,9 @@ static const struct multistate multistate_ignore_rhosts[] = { { "yes", IGNORE_RHOSTS_YES }, { "no", IGNORE_RHOSTS_NO }, - { "shosts-only", IGNORE_RHOSTS_SHOSTS }, + { "rhosts-only", IGNORE_RHOSTS_ONLY }, + /*compatibility*/ + { "shosts-only", IGNORE_RHOSTS_ONLY }, { NULL, -1 } }; static const struct multistate multistate_addressfamily[] = { @@ -1294,8 +1446,8 @@ { NULL, -1 } }; static const struct multistate multistate_permitrootlogin[] = { - { "without-password", PERMIT_NO_PASSWD }, { "prohibit-password", PERMIT_NO_PASSWD }, + { "without-password", PERMIT_NO_PASSWD }, { "forced-commands-only", PERMIT_FORCED_ONLY }, { "yes", PERMIT_YES }, { "no", PERMIT_NO }, @@ -1315,6 +1467,13 @@ { "no", 0 }, { NULL, -1 } }; +static const struct multistate multistate_privsep[] = { + { "yes", PRIVSEP_NOSANDBOX }, + { "sandbox", PRIVSEP_ON }, + { "nosandbox", PRIVSEP_NOSANDBOX }, + { "no", PRIVSEP_OFF }, + { NULL, -1 } +}; static const struct multistate multistate_tcpfwd[] = { { "yes", FORWARD_ALLOW }, { "all", FORWARD_ALLOW }, @@ -1331,20 +1490,20 @@ struct include_list *includes) { char *str, ***chararrayptr, **charptr, *arg, *arg2, *p, *keyword; + char **oav = NULL, **av; + int oac = 0, ac; int cmdline = 0, *intptr, value, value2, n, port, oactive, r, found; - int ca_only = 0; + int ca_only; SyslogFacility *log_facility_ptr; LogLevel *log_level_ptr; ServerOpCodes opcode; - u_int i, *uintptr, uvalue, flags = 0; + u_int i, *uintptr, flags = 0; size_t len; long long val64; const struct multistate *multistate_ptr; const char *errstr; struct include_item *item; glob_t gbuf; - char **oav = NULL, **av; - int oac = 0, ac; int ret = -1; /* Strip trailing whitespace. Allow \f (form feed) at EOL only */ @@ -1362,13 +1521,18 @@ /* Ignore leading whitespace */ if (*keyword == '\0') keyword = strdelim(&str); - if (!keyword || !*keyword || *keyword == '#') + if (keyword == NULL || *keyword == '\0' || *keyword == '\n' || *keyword == '#') return 0; + + /* Prepare to parse remainder of line */ + if (str != NULL) + str += strspn(str, WHITESPACE); if (str == NULL || *str == '\0') { error("%s line %d: no argument after keyword \"%s\"", filename, linenum, keyword); return -1; } + intptr = NULL; charptr = NULL; opcode = parse_token(keyword, filename, linenum, &flags); @@ -1379,6 +1543,7 @@ } ac = oac; av = oav; + ca_only = 0; if (activep == NULL) { /* We are processing a command line directive */ cmdline = 1; @@ -1402,6 +1567,164 @@ intptr = &options->use_pam; goto parse_flag; + /* X.509 Standard Options */ + case sHostbasedAcceptedAlgorithms: /* compatibility ;) */ + case sHostbasedAlgorithms: + arg = argv_next(&ac, &av); + if (arg == NULL || *arg == '\0') + fatal("%s line %d: %s missing argument.", + filename, linenum, keyword); + /* cannot validate here - depend from X509KeyAlgorithm */ + if (*activep && options->hostbased_algorithms == NULL) + options->hostbased_algorithms = xstrdup(arg); + break; + + case sPubkeyAcceptedAlgorithms: /* compatibility ;) */ + case sPubkeyAlgorithms: + arg = argv_next(&ac, &av); + if (arg == NULL || *arg == '\0') + fatal("%s line %d: %s missing argument.", + filename, linenum, keyword); + /* cannot validate here - depend from X509KeyAlgorithm */ + if (*activep && options->pubkey_algorithms == NULL) + options->pubkey_algorithms = xstrdup(arg); + break; + + case sAcceptedAlgorithms: + arg = argv_next(&ac, &av); + if (arg == NULL || *arg == '\0') + fatal("%s line %d: %s missing argument.", + filename, linenum, keyword); + /* cannot validate here - depend from X509KeyAlgorithm */ + if (*activep && options->accepted_algorithms == NULL) + options->accepted_algorithms = xstrdup(arg); + break; + + case sX509KeyAlgorithm: + arg = argv_next(&ac, &av); + if (arg == NULL || *arg == '\0') + fatal("%s line %d: %s missing argument.", + filename, linenum, keyword); + if (ssh_add_x509key_alg(arg) < 0) { + fatal("%s line %d: bad X.509 key algorithm '%s'.", + filename, linenum, arg); + } + break; + + case sAllowedClientCertPurpose: + intptr = &options->x509flags.allowedcertpurpose; + arg = argv_next(&ac, &av); + if (arg != NULL && *arg != '\0') { + if (strcasecmp(arg, "skip") == 0) goto skip_purpose; + + /* convert string to OpenSSL index */ + value = ssh_get_x509purpose_s (1, arg); + if (value < 0) + fatal("%s line %d: bad certificate purpose '%s'.", + filename, linenum, arg); + + if (*intptr == -1) + *intptr = value; + } else { +skip_purpose: + if (*intptr == -1) { + *intptr = -2; + verbose("%s line %d: %s is set do not check certificate purpose.", + filename, linenum, keyword); + } + } + break; + + case sKeyAllowSelfIssued: + intptr = &options->x509flags.key_allow_selfissued; + goto parse_flag; + + case sMandatoryCRL: + intptr = &options->x509flags.mandatory_crl; + goto parse_flag; + + case sValidateFirst: + intptr = &options->x509flags.validate_first; + goto parse_flag; + + case sCACertificateFile: + /* X509StoreOptions preffered type is 'const char*' */ + charptr = (char**)&options->ca.certificate_file; +parse_string: + arg = argv_next(&ac, &av); + if (arg == NULL || *arg == '\0') + fatal("%s line %d: %s missing argument.", + filename, linenum, keyword); + if (*charptr == NULL) + *charptr = xstrdup(arg); + break; + + case sCACertificatePath: + /* X509StoreOptions preffered type is 'const char*' */ + charptr = (char**)&options->ca.certificate_path; + goto parse_string; + + case sCARevocationFile: + /* X509StoreOptions preffered type is 'const char*' */ + charptr = (char**)&options->ca.revocation_file; + goto parse_string; + + case sCARevocationPath: + /* X509StoreOptions preffered type is 'const char*' */ + charptr = (char**)&options->ca.revocation_path; + goto parse_string; + +#ifdef USE_OPENSSL_STORE2 + case sCAStoreURI: + arg = argv_next(&ac, &av); + if (arg == NULL || *arg == '\0') + fatal("%s line %d: %s missing argument.", + filename, linenum, keyword); + opt_array_append(filename, linenum, "CAStoreURI", + (char***)&options->store_uri, &options->num_store_uri, + arg); + break; +#endif /*def USE_OPENSSL_STORE2*/ + +#ifdef LDAP_ENABLED + case sCAldapVersion: + charptr = (char**)&options->ca_ldap_ver; + goto parse_string; + + case sCAldapURL: + charptr = (char**)&options->ca_ldap_url; + goto parse_string; +#endif /*def LDAP_ENABLED*/ + +#ifdef SSH_OCSP_ENABLED + case sVAType: + intptr = &options->va.type; + arg = argv_next(&ac, &av); + if (arg == NULL || *arg == '\0') + fatal("%s line %d: %s missing argument.", + filename, linenum, keyword); + + value = ssh_get_vatype_s(arg); + if (value < 0) { + fatal("%s line %d: Bad OCSP responder type '%.30s'.", + filename, linenum, arg); + } + + if (*intptr == -1) + *intptr = value; + break; + + case sVACertificateFile: + /* VAOptions preffered type is 'const char*' */ + charptr = (char**)&options->va.certificate_file; + goto parse_string; + + case sVAOCSPResponderURL: + /* VAOptions preffered type is 'const char*' */ + charptr = (char**)&options->va.responder_url; + goto parse_string; +#endif /*def SSH_OCSP_ENABLED*/ + /* Standard Options */ case sBadOption: goto out; @@ -1415,7 +1738,7 @@ fatal("%s line %d: too many ports.", filename, linenum); arg = argv_next(&ac, &av); - if (!arg || *arg == '\0') + if (arg == NULL || *arg == '\0') fatal("%s line %d: missing port number.", filename, linenum); options->ports[options->num_ports++] = a2port(arg); @@ -1428,12 +1751,11 @@ intptr = &options->login_grace_time; parse_time: arg = argv_next(&ac, &av); - if (!arg || *arg == '\0') + if (arg == NULL || *arg == '\0') fatal("%s line %d: missing time value.", filename, linenum); - if ((value = convtime(arg)) == -1) - fatal("%s line %d: invalid time value.", - filename, linenum); + value = parse_time(arg, filename, linenum); + if (value == -1) goto out; if (*activep && *intptr == -1) *intptr = value; break; @@ -1481,9 +1803,9 @@ multistate_ptr = multistate_addressfamily; parse_multistate: arg = argv_next(&ac, &av); - if (!arg || *arg == '\0') - fatal("%s line %d: missing argument.", - filename, linenum); + if (arg == NULL || *arg == '\0') + fatal("%s line %d: %s missing argument.", + filename, linenum, keyword); value = -1; for (i = 0; multistate_ptr[i].key != NULL; i++) { if (strcasecmp(arg, multistate_ptr[i].key) == 0) { @@ -1500,19 +1822,18 @@ case sHostKeyFile: arg = argv_next(&ac, &av); - if (!arg || *arg == '\0') + if (arg == NULL || *arg == '\0') fatal("%s line %d: missing file name.", filename, linenum); - if (*activep) { + if (*activep) servconf_add_hostkey(filename, linenum, options, arg, 1); - } break; case sHostKeyAgent: charptr = &options->host_key_agent; arg = argv_next(&ac, &av); - if (!arg || *arg == '\0') + if (arg == NULL || *arg == '\0') fatal("%s line %d: missing socket name.", filename, linenum); if (*activep && *charptr == NULL) @@ -1522,7 +1843,7 @@ case sHostCertificate: arg = argv_next(&ac, &av); - if (!arg || *arg == '\0') + if (arg == NULL || *arg == '\0') fatal("%s line %d: missing file name.", filename, linenum); if (*activep) @@ -1533,7 +1854,7 @@ charptr = &options->pid_file; parse_filename: arg = argv_next(&ac, &av); - if (!arg || *arg == '\0') + if (arg == NULL || *arg == '\0') fatal("%s line %d: missing file name.", filename, linenum); if (*activep && *charptr == NULL) { @@ -1572,63 +1893,34 @@ intptr = &options->hostbased_uses_name_from_packet_only; goto parse_flag; - case sHostbasedAcceptedAlgorithms: - charptr = &options->hostbased_accepted_algos; - ca_only = 0; - parse_pubkey_algos: + case sHostKeyAlgorithms: + charptr = &options->hostkeyalgorithms; + parse_key_algorithms: arg = argv_next(&ac, &av); - if (!arg || *arg == '\0') - fatal("%s line %d: Missing argument.", - filename, linenum); + if (arg == NULL || *arg == '\0') + fatal("%s line %d: %s missing argument.", + filename, linenum, keyword); + /* cannot validate here - depend from X509KeyAlgorithm */ + if (ca_only) { if (*arg != '-' && !sshkey_names_valid2(*arg == '+' || *arg == '^' ? arg + 1 : arg, 1, ca_only)) - fatal("%s line %d: Bad key types '%s'.", + fatal("%s line %d: bad key types '%s'.", filename, linenum, arg ? arg : ""); + } if (*activep && *charptr == NULL) *charptr = xstrdup(arg); break; - case sHostKeyAlgorithms: - charptr = &options->hostkeyalgorithms; - ca_only = 0; - goto parse_pubkey_algos; - case sCASignatureAlgorithms: charptr = &options->ca_sign_algorithms; ca_only = 1; - goto parse_pubkey_algos; + goto parse_key_algorithms; case sPubkeyAuthentication: intptr = &options->pubkey_authentication; - ca_only = 0; goto parse_flag; - case sPubkeyAcceptedAlgorithms: - charptr = &options->pubkey_accepted_algos; - ca_only = 0; - goto parse_pubkey_algos; - - case sPubkeyAuthOptions: - intptr = &options->pubkey_auth_options; - value = 0; - while ((arg = argv_next(&ac, &av)) != NULL) { - if (strcasecmp(arg, "none") == 0) - continue; - if (strcasecmp(arg, "touch-required") == 0) - value |= PUBKEYAUTH_TOUCH_REQUIRED; - else if (strcasecmp(arg, "verify-required") == 0) - value |= PUBKEYAUTH_VERIFY_REQUIRED; - else { - error("%s line %d: unsupported %s option %s", - filename, linenum, keyword, arg); - goto out; - } - } - if (*activep && *intptr == -1) - *intptr = value; - break; - case sKerberosAuthentication: intptr = &options->kerberos_authentication; goto parse_flag; @@ -1720,7 +2012,7 @@ intptr = &options->permit_user_env; charptr = &options->permit_user_env_allowlist; arg = argv_next(&ac, &av); - if (!arg || *arg == '\0') + if (arg == NULL || *arg == '\0') fatal("%s line %d: %s missing argument.", filename, linenum, keyword); value = 0; @@ -1749,7 +2041,7 @@ case sRekeyLimit: arg = argv_next(&ac, &av); - if (!arg || *arg == '\0') + if (arg == NULL || *arg == '\0') fatal("%s line %d: %s missing argument.", filename, linenum, keyword); if (strcmp(arg, "default") == 0) { @@ -1765,7 +2057,7 @@ } if (*activep && options->rekey_limit == -1) options->rekey_limit = val64; - if (ac != 0) { /* optional rekey interval present */ + if (ac > 0) { /* optional rekey interval present */ if (strcmp(av[0], "none") == 0) { (void)argv_next(&ac, &av); /* discard */ break; @@ -1807,14 +2099,12 @@ break; case sLogVerbose: - found = options->num_log_verbose == 0; + found = options->num_log_verbose > 0; i = 0; while ((arg = argv_next(&ac, &av)) != NULL) { - if (*arg == '\0') { - error("%s line %d: keyword %s empty argument", + if (*arg == '\0') + fatal("%s line %d: empty %s pattern", filename, linenum, keyword); - goto out; - } /* Allow "none" only in first position */ if (strcasecmp(arg, "none") == 0) { if (i > 0 || ac > 0) { @@ -1825,7 +2115,7 @@ } } i++; - if (!found || !*activep) + if (!*activep || found) continue; opt_array_append(filename, linenum, keyword, &options->log_verbose, &options->num_log_verbose, @@ -1851,13 +2141,20 @@ intptr = &options->disable_forwarding; goto parse_flag; + case sUsePrivilegeSeparation: + intptr = &use_privsep; + multistate_ptr = multistate_privsep; + goto parse_multistate; + case sAllowUsers: chararrayptr = &options->allow_users; uintptr = &options->num_allow_users; parse_allowdenyusers: while ((arg = argv_next(&ac, &av)) != NULL) { - if (*arg == '\0' || - match_user(NULL, NULL, NULL, arg) == -1) + if (*arg == '\0') + fatal("%s line %d: empty %s pattern", + filename, linenum, keyword); + if (match_user(NULL, NULL, NULL, arg) == -1) fatal("%s line %d: invalid %s pattern: \"%s\"", filename, linenum, keyword, arg); if (!*activep) @@ -1894,7 +2191,7 @@ case sCiphers: arg = argv_next(&ac, &av); - if (!arg || *arg == '\0') + if (arg == NULL || *arg == '\0') fatal("%s line %d: %s missing argument.", filename, linenum, keyword); if (*arg != '-' && @@ -1907,7 +2204,7 @@ case sMacs: arg = argv_next(&ac, &av); - if (!arg || *arg == '\0') + if (arg == NULL || *arg == '\0') fatal("%s line %d: %s missing argument.", filename, linenum, keyword); if (*arg != '-' && @@ -1920,7 +2217,7 @@ case sKexAlgorithms: arg = argv_next(&ac, &av); - if (!arg || *arg == '\0') + if (arg == NULL || *arg == '\0') fatal("%s line %d: %s missing argument.", filename, linenum, keyword); if (*arg != '-' && @@ -1938,7 +2235,7 @@ filename, linenum); } arg = argv_next(&ac, &av); - if (!arg || *arg == '\0') + if (arg == NULL || *arg == '\0') fatal("%s line %d: %s missing argument.", filename, linenum, keyword); if (!*activep) { @@ -1947,19 +2244,22 @@ } for (i = 0; i < options->num_subsystems; i++) if (strcmp(arg, options->subsystem_name[i]) == 0) - fatal("%s line %d: Subsystem '%s' " - "already defined.", filename, linenum, arg); + fatal("%s line %d: %s already defined %s.", + filename, linenum, keyword, arg); options->subsystem_name[options->num_subsystems] = xstrdup(arg); arg = argv_next(&ac, &av); - if (!arg || *arg == '\0') - fatal("%s line %d: Missing subsystem command.", - filename, linenum); + if (arg == NULL || *arg == '\0') + fatal("%s line %d: %s missing command.", + filename, linenum, keyword); options->subsystem_command[options->num_subsystems] = xstrdup(arg); /* Collect arguments (separate to executable) */ p = xstrdup(arg); len = strlen(p) + 1; while ((arg = argv_next(&ac, &av)) != NULL) { + if (*arg == '\0') + fatal("%s line %d: empty %s pattern", + filename, linenum, keyword); len += 1 + strlen(arg); p = xreallocarray(p, 1, len); strlcat(p, " ", len); @@ -1971,7 +2271,7 @@ case sMaxStartups: arg = argv_next(&ac, &av); - if (!arg || *arg == '\0') + if (arg == NULL || *arg == '\0') fatal("%s line %d: %s missing argument.", filename, linenum, keyword); if ((n = sscanf(arg, "%d:%d:%d", @@ -1989,49 +2289,50 @@ filename, linenum, keyword); else options->max_startups = options->max_startups_begin; - if (options->max_startups <= 0 || - options->max_startups_begin <= 0) + if (options->max_startups_begin <= 0) fatal("%s line %d: Invalid %s spec.", filename, linenum, keyword); break; case sPerSourceNetBlockSize: + intptr = &options->per_source_masklen_ipv4; arg = argv_next(&ac, &av); - if (!arg || *arg == '\0') + if (arg == NULL || *arg == '\0') fatal("%s line %d: %s missing argument.", filename, linenum, keyword); - switch (n = sscanf(arg, "%d:%d", &value, &value2)) { - case 2: + value2 = -1; + n = sscanf(arg, "%d:%d", &value, &value2); + if (n > 2) n = -1; /*?*/ + if (n >= 2) if (value2 < 0 || value2 > 128) n = -1; - /* FALLTHROUGH */ - case 1: + if (n >= 1) if (value < 0 || value > 32) n = -1; - } - if (n != 1 && n != 2) + if (n < 1) fatal("%s line %d: Invalid %s spec.", filename, linenum, keyword); - if (*activep) { - options->per_source_masklen_ipv4 = value; + if (*activep && *intptr == -1) { + *intptr = value; options->per_source_masklen_ipv6 = value2; } break; case sPerSourceMaxStartups: + intptr = &options->per_source_max_startups; arg = argv_next(&ac, &av); - if (!arg || *arg == '\0') + if (arg == NULL || *arg == '\0') fatal("%s line %d: %s missing argument.", filename, linenum, keyword); if (strcmp(arg, "none") == 0) { /* no limit */ - value = INT_MAX; + value = -2; } else { if ((errstr = atoi_err(arg, &value)) != NULL) fatal("%s line %d: %s integer value %s.", filename, linenum, keyword, errstr); } - if (*activep) - options->per_source_max_startups = value; + if (*activep && *intptr == -1) + *intptr = value; break; case sMaxAuthTries: @@ -2053,15 +2354,13 @@ * AuthorizedKeysFile /etc/ssh_keys/%u */ case sAuthorizedKeysFile: - uvalue = options->num_authkeys_files; + found = options->num_authkeys_files > 0; while ((arg = argv_next(&ac, &av)) != NULL) { - if (*arg == '\0') { - error("%s line %d: keyword %s empty argument", + if (*arg == '\0') + fatal("%s line %d: empty %s pattern", filename, linenum, keyword); - goto out; - } arg2 = tilde_expand_filename(arg, getuid()); - if (*activep && uvalue == 0) { + if (*activep && !found) { opt_array_append(filename, linenum, keyword, &options->authorized_keys_files, &options->num_authkeys_files, arg2); @@ -2073,7 +2372,7 @@ case sAuthorizedPrincipalsFile: charptr = &options->authorized_principals_file; arg = argv_next(&ac, &av); - if (!arg || *arg == '\0') + if (arg == NULL || *arg == '\0') fatal("%s line %d: %s missing argument.", filename, linenum, keyword); if (*activep && *charptr == NULL) { @@ -2094,9 +2393,16 @@ case sAcceptEnv: while ((arg = argv_next(&ac, &av)) != NULL) { - if (*arg == '\0' || strchr(arg, '=') != NULL) - fatal("%s line %d: Invalid environment name.", + if (*arg == '\0') { + error("%s line %d: keyword %s empty argument", + filename, linenum, keyword); + goto out; + } + if (strchr(arg, '=') != NULL) { + error("%s line %d: Invalid environment name.", filename, linenum); + goto out; + } if (!*activep) continue; opt_array_append(filename, linenum, keyword, @@ -2106,12 +2412,18 @@ break; case sSetEnv: - uvalue = options->num_setenv; while ((arg = argv_next(&ac, &av)) != NULL) { - if (*arg == '\0' || strchr(arg, '=') == NULL) - fatal("%s line %d: Invalid environment.", + if (*arg == '\0') { + error("%s line %d: keyword %s empty argument", + filename, linenum, keyword); + goto out; + } + if (strchr(arg, '=') == NULL) { + error("%s line %d: Invalid environment name.", filename, linenum); - if (!*activep || uvalue != 0) + goto out; + } + if (!*activep) continue; if (lookup_setenv_in_list(arg, options->setenv, options->num_setenv) != NULL) { @@ -2127,7 +2439,7 @@ case sPermitTunnel: intptr = &options->permit_tun; arg = argv_next(&ac, &av); - if (!arg || *arg == '\0') + if (arg == NULL || *arg == '\0') fatal("%s line %d: %s missing argument.", filename, linenum, keyword); value = -1; @@ -2150,11 +2462,9 @@ } value = 0; while ((arg2 = argv_next(&ac, &av)) != NULL) { - if (*arg2 == '\0') { - error("%s line %d: keyword %s empty argument", + if (*arg2 == '\0') + fatal("%s line %d: empty %s pattern", filename, linenum, keyword); - goto out; - } value++; found = 0; if (*arg2 != '/' && *arg2 != '~') { @@ -2272,12 +2582,12 @@ chararrayptr = &options->permitted_opens; } arg = argv_next(&ac, &av); - if (!arg || *arg == '\0') + if (arg == NULL || *arg == '\0') fatal("%s line %d: %s missing argument.", filename, linenum, keyword); - uvalue = *uintptr; /* modified later */ + found = *uintptr > 0; if (strcmp(arg, "any") == 0 || strcmp(arg, "none") == 0) { - if (*activep && uvalue == 0) { + if (*activep && !found) { *uintptr = 1; *chararrayptr = xcalloc(1, sizeof(**chararrayptr)); @@ -2285,7 +2595,10 @@ } break; } - for (; arg != NULL && *arg != '\0'; arg = argv_next(&ac, &av)) { + for (; arg != NULL; arg = argv_next(&ac, &av)) { + if (*arg == '\0') + fatal("%s line %d: empty %s pattern", + filename, linenum, keyword); if (opcode == sPermitListen && strchr(arg, ':') == NULL) { /* @@ -2307,7 +2620,7 @@ fatal("%s line %d: %s bad port number", filename, linenum, keyword); } - if (*activep && uvalue == 0) { + if (*activep && !found) { opt_array_append(filename, linenum, keyword, chararrayptr, uintptr, arg2); } @@ -2316,9 +2629,6 @@ break; case sForceCommand: - if (str == NULL || *str == '\0') - fatal("%s line %d: %s missing argument.", - filename, linenum, keyword); len = strspn(str, WHITESPACE); if (*activep && options->adm_forced_command == NULL) options->adm_forced_command = xstrdup(str + len); @@ -2329,7 +2639,7 @@ charptr = &options->chroot_directory; arg = argv_next(&ac, &av); - if (!arg || *arg == '\0') + if (arg == NULL || *arg == '\0') fatal("%s line %d: %s missing argument.", filename, linenum, keyword); if (*activep && *charptr == NULL) @@ -2344,24 +2654,9 @@ charptr = &options->revoked_keys_file; goto parse_filename; - case sSecurityKeyProvider: - charptr = &options->sk_provider; - arg = argv_next(&ac, &av); - if (!arg || *arg == '\0') - fatal("%s line %d: %s missing argument.", - filename, linenum, keyword); - if (*activep && *charptr == NULL) { - *charptr = strcasecmp(arg, "internal") == 0 ? - xstrdup(arg) : derelativise_path(arg); - /* increase optional counter */ - if (intptr != NULL) - *intptr = *intptr + 1; - } - break; - case sIPQoS: arg = argv_next(&ac, &av); - if (!arg || *arg == '\0') + if (arg == NULL || *arg == '\0') fatal("%s line %d: %s missing argument.", filename, linenum, keyword); if ((value = parse_ipqos(arg)) == -1) @@ -2373,25 +2668,17 @@ else if ((value2 = parse_ipqos(arg)) == -1) fatal("%s line %d: Bad %s value: %s", filename, linenum, keyword, arg); - if (*activep) { + if (*activep && options->ip_qos_interactive == -1) { options->ip_qos_interactive = value; options->ip_qos_bulk = value2; } break; case sVersionAddendum: - if (str == NULL || *str == '\0') - fatal("%s line %d: %s missing argument.", - filename, linenum, keyword); len = strspn(str, WHITESPACE); - if (strchr(str + len, '\r') != NULL) { - fatal("%.200s line %d: Invalid %s argument", + if (strchr(str + len, '\r') != NULL) + fatal("%s line %d: Invalid %s argument", filename, linenum, keyword); - } - if ((arg = strchr(line, '#')) != NULL) { - *arg = '\0'; - rtrim(line); - } if (*activep && options->version_addendum == NULL) { if (strcasecmp(str + len, "none") == 0) options->version_addendum = xstrdup(""); @@ -2405,10 +2692,9 @@ charptr = &options->authorized_keys_command; parse_command: len = strspn(str, WHITESPACE); - if (str[len] != '/' && strcasecmp(str + len, "none") != 0) { - fatal("%.200s line %d: %s must be an absolute path", + if (str[len] != '/' && strcasecmp(str + len, "none") != 0) + fatal("%s line %d: %s must be an absolute path", filename, linenum, keyword); - } if (*activep && *charptr == NULL) *charptr = xstrdup(str + len); argv_consume(&ac); @@ -2418,10 +2704,9 @@ charptr = &options->authorized_keys_command_user; parse_localuser: arg = argv_next(&ac, &av); - if (!arg || *arg == '\0') { - fatal("%s line %d: missing %s argument.", + if (arg == NULL || *arg == '\0') + fatal("%s line %d: %s missing argument.", filename, linenum, keyword); - } if (*activep && *charptr == NULL) *charptr = xstrdup(arg); break; @@ -2435,10 +2720,13 @@ goto parse_localuser; case sAuthenticationMethods: - found = options->num_auth_methods == 0; + found = options->num_auth_methods > 0; value = 0; /* seen "any" pseudo-method */ value2 = 0; /* successfully parsed any method */ while ((arg = argv_next(&ac, &av)) != NULL) { + if (*arg == '\0') + fatal("%s line %d: empty %s pattern", + filename, linenum, keyword); if (strcmp(arg, "any") == 0) { if (options->num_auth_methods > 0) { fatal("%s line %d: \"any\" must " @@ -2450,11 +2738,11 @@ fatal("%s line %d: \"any\" must appear " "alone in %s", filename, linenum, keyword); } else if (auth2_methods_valid(arg, 0) != 0) { - fatal("%s line %d: invalid %s method list.", + fatal("%s line %d: Invalid %s spec.", filename, linenum, keyword); } value2 = 1; - if (!found || !*activep) + if (!*activep || found) continue; opt_array_append(filename, linenum, keyword, &options->auth_methods, @@ -2468,7 +2756,7 @@ case sStreamLocalBindMask: arg = argv_next(&ac, &av); - if (!arg || *arg == '\0') + if (arg == NULL || *arg == '\0') fatal("%s line %d: %s missing argument.", filename, linenum, keyword); /* Parse mode in octal format */ @@ -2476,7 +2764,7 @@ if (arg == p || value < 0 || value > 0777) fatal("%s line %d: Invalid %s.", filename, linenum, keyword); - if (*activep) + if (*activep && options->fwd_opts.streamlocal_bind_mask == (mode_t)-1) options->fwd_opts.streamlocal_bind_mask = (mode_t)value; break; @@ -2486,13 +2774,13 @@ case sFingerprintHash: arg = argv_next(&ac, &av); - if (!arg || *arg == '\0') + if (arg == NULL || *arg == '\0') fatal("%s line %d: %s missing argument.", filename, linenum, keyword); if ((value = ssh_digest_alg_by_name(arg)) == -1) - fatal("%.200s line %d: Invalid %s algorithm \"%s\".", + fatal("%s line %d: Invalid %s algorithm \"%s\".", filename, linenum, keyword, arg); - if (*activep) + if (*activep && options->fingerprint_hash == -1) options->fingerprint_hash = value; break; @@ -2500,14 +2788,11 @@ intptr = &options->expose_userauth_info; goto parse_flag; +#ifdef ENABLE_ROUTING_DOMAIN case sRDomain: -#if !defined(__OpenBSD__) && !defined(HAVE_SYS_SET_PROCESS_RDOMAIN) - fatal("%s line %d: setting RDomain not supported on this " - "platform.", filename, linenum); -#endif charptr = &options->routing_domain; arg = argv_next(&ac, &av); - if (!arg || *arg == '\0') + if (arg == NULL || *arg == '\0') fatal("%s line %d: %s missing argument.", filename, linenum, keyword); if (strcasecmp(arg, "none") != 0 && strcmp(arg, "%D") != 0 && @@ -2517,13 +2802,14 @@ if (*activep && *charptr == NULL) *charptr = xstrdup(arg); break; +#endif case sRequiredRSASize: intptr = &options->required_rsa_size; goto parse_int; case sChannelTimeout: - uvalue = options->num_channel_timeouts; + found = options->num_channel_timeouts > 0; i = 0; while ((arg = argv_next(&ac, &av)) != NULL) { /* Allow "none" only in first position */ @@ -2538,7 +2824,7 @@ fatal("%s line %d: invalid channel timeout %s", filename, linenum, arg); } - if (!*activep || uvalue != 0) + if (!*activep || found) continue; opt_array_append(filename, linenum, keyword, &options->channel_timeouts, @@ -2559,12 +2845,24 @@ case sDeprecated: case sIgnore: +#ifndef USE_OPENSSL_STORE2 + case sCAStoreURI: +#endif +#ifndef LDAP_ENABLED + case sCAldapVersion: + case sCAldapURL: +#endif /*ndef LDAP_ENABLED*/ +#ifndef SSH_OCSP_ENABLED + case sVAType: + case sVACertificateFile: + case sVAOCSPResponderURL: +#endif /*ndef SSH_OCSP_ENABLED*/ case sUnsupported: do_log2(opcode == sIgnore ? SYSLOG_LEVEL_DEBUG2 : SYSLOG_LEVEL_INFO, "%s line %d: %s option %s", filename, linenum, - opcode == sUnsupported ? "Unsupported" : "Deprecated", - keyword); + opcode == sDeprecated || opcode == sIgnore ? + "Deprecated" : "Unsupported", keyword); argv_consume(&ac); break; @@ -2574,7 +2872,7 @@ } /* Check that there is no garbage at end of line. */ if (ac > 0) { - error("%.200s line %d: keyword %s extra arguments " + error("%s line %d: keyword %s extra arguments " "at end of line", filename, linenum, keyword); goto out; } @@ -2603,8 +2901,7 @@ void load_server_config(const char *filename, struct sshbuf *conf) { - struct stat st; - char *line = NULL, *cp; + char *line = NULL; size_t linesize = 0; FILE *f; int r; @@ -2615,9 +2912,8 @@ exit(1); } sshbuf_reset(conf); - /* grow buffer, so realloc is avoided for large config files */ - if (fstat(fileno(f), &st) == 0 && st.st_size > 0 && - (r = sshbuf_allocate(conf, st.st_size)) != 0) + /* allocate buffer for large config files */ + if ((r = sshbuf_allocate_fd(fileno(f), conf)) != 0) fatal_fr(r, "allocate"); while (getline(&line, &linesize, f) != -1) { /* @@ -2625,7 +2921,7 @@ * NB - preserve newlines, they are needed to reproduce * line numbers later for error messages */ - cp = line + strspn(line, " \t\r"); + char *cp = line + strspn(line, " \t\r"); if ((r = sshbuf_put(conf, cp, strlen(cp))) != 0) fatal_fr(r, "sshbuf_put"); } @@ -2697,7 +2993,6 @@ M_CP_INTOPT(password_authentication); M_CP_INTOPT(gss_authentication); M_CP_INTOPT(pubkey_authentication); - M_CP_INTOPT(pubkey_auth_options); M_CP_INTOPT(kerberos_authentication); M_CP_INTOPT(hostbased_authentication); M_CP_INTOPT(hostbased_uses_name_from_packet_only); @@ -2761,12 +3056,12 @@ } \ } while(0) + M_CP_STROPT(hostbased_algorithms); + M_CP_STROPT(pubkey_algorithms); + /* See comment in servconf.h */ COPY_MATCH_STRING_OPTS(); - /* Arguments that accept '+...' need to be expanded */ - assemble_algorithms(dst); - /* * The only things that should be below this point are string options * which are only used after authentication. @@ -2859,6 +3154,8 @@ return fmt_multistate_int(val, multistate_gatewayports); case sCompression: return fmt_multistate_int(val, multistate_compression); + case sUsePrivilegeSeparation: + return fmt_multistate_int(val, multistate_privsep); case sAllowTcpForwarding: return fmt_multistate_int(val, multistate_tcpfwd); case sAllowStreamLocalForwarding: @@ -2867,6 +3164,13 @@ return fmt_multistate_int(val, multistate_ignore_rhosts); case sFingerprintHash: return ssh_digest_alg_name(val); + case sAllowedClientCertPurpose: + return format_x509_purpose(val); +#ifdef SSH_OCSP_ENABLED + case sVAType: { + return ssh_get_vatype_i(val); + } break; +#endif default: switch (val) { case 0: @@ -2904,6 +3208,8 @@ static void dump_cfg_string(ServerOpCodes code, const char *val) { + if (val == NULL) + return; printf("%s %s\n", lookup_opcode_name(code), val == NULL ? "none" : val); } @@ -2921,24 +3227,26 @@ dump_cfg_strarray_oneline(ServerOpCodes code, u_int count, char **vals) { u_int i; + const char *def = ""; - switch (code) { - case sAuthenticationMethods: - case sChannelTimeout: - break; - default: - if (count <= 0) + if ((int)count < 0) return; + + if (count == 0) { + switch(code) { + case sAuthenticationMethods: + def = " any"; break; + case sChannelTimeout: + def = " none"; break; + case sLogVerbose: + def = " none"; break; + default: return; - break; + } } - printf("%s", lookup_opcode_name(code)); + printf("%s%s", lookup_opcode_name(code), def); for (i = 0; i < count; i++) printf(" %s", vals[i]); - if (code == sAuthenticationMethods && count == 0) - printf(" any"); - else if (code == sChannelTimeout && count == 0) - printf(" none"); printf("\n"); } @@ -3002,6 +3310,33 @@ #ifdef USE_PAM dump_cfg_fmtint(sUsePAM, o->use_pam); #endif + /* X.509 Standard Options */ + dump_cfg_string(sHostbasedAlgorithms, o->hostbased_algorithms); + dump_cfg_string(sPubkeyAlgorithms, o->pubkey_algorithms); + dump_cfg_string(sAcceptedAlgorithms, o->accepted_algorithms); + /* TODO to implement dump of sX509KeyAlgorithm */ + /* sshd PKI(X509) flags */ + dump_cfg_fmtint(sAllowedClientCertPurpose, o->x509flags.allowedcertpurpose); + dump_cfg_fmtint(sKeyAllowSelfIssued, o->x509flags.key_allow_selfissued); + dump_cfg_fmtint(sMandatoryCRL , o->x509flags.mandatory_crl ); + dump_cfg_fmtint(sValidateFirst , o->x509flags.validate_first ); + /* sshd PKI(X509) system store */ + dump_cfg_string(sCACertificateFile, o->ca.certificate_file); + dump_cfg_string(sCACertificatePath, o->ca.certificate_path); + dump_cfg_string(sCARevocationFile , o->ca.revocation_file ); + dump_cfg_string(sCARevocationPath , o->ca.revocation_path ); +#ifdef LDAP_ENABLED + dump_cfg_string(sCAldapVersion , o->ca_ldap_ver ); + dump_cfg_string(sCAldapURL , o->ca_ldap_url ); +#endif +#ifdef SSH_OCSP_ENABLED + /* ssh X.509 extra validation */ + dump_cfg_fmtint(sVAType , o->va.type ); + dump_cfg_string(sVACertificateFile , o->va.certificate_file); + dump_cfg_string(sVAOCSPResponderURL, o->va.responder_url ); +#endif /*def SSH_OCSP_ENABLED*/ + + /* Standard Options */ dump_cfg_int(sLoginGraceTime, o->login_grace_time); dump_cfg_int(sX11DisplayOffset, o->x11_display_offset); dump_cfg_int(sMaxAuthTries, o->max_authtries); @@ -3054,6 +3389,7 @@ dump_cfg_fmtint(sDisableForwarding, o->disable_forwarding); dump_cfg_fmtint(sAllowStreamLocalForwarding, o->allow_streamlocal_forwarding); dump_cfg_fmtint(sStreamLocalBindUnlink, o->fwd_opts.streamlocal_bind_unlink); + dump_cfg_fmtint(sUsePrivilegeSeparation, use_privsep); dump_cfg_fmtint(sFingerprintHash, o->fingerprint_hash); dump_cfg_fmtint(sExposeAuthInfo, o->expose_userauth_info); @@ -3068,7 +3404,6 @@ dump_cfg_string(sChrootDirectory, o->chroot_directory); dump_cfg_string(sTrustedUserCAKeys, o->trusted_user_ca_keys); dump_cfg_string(sRevokedKeys, o->revoked_keys_file); - dump_cfg_string(sSecurityKeyProvider, o->sk_provider); dump_cfg_string(sAuthorizedPrincipalsFile, o->authorized_principals_file); dump_cfg_string(sVersionAddendum, *o->version_addendum == '\0' @@ -3080,12 +3415,8 @@ dump_cfg_string(sHostKeyAgent, o->host_key_agent); dump_cfg_string(sKexAlgorithms, o->kex_algorithms); dump_cfg_string(sCASignatureAlgorithms, o->ca_sign_algorithms); - dump_cfg_string(sHostbasedAcceptedAlgorithms, o->hostbased_accepted_algos); dump_cfg_string(sHostKeyAlgorithms, o->hostkeyalgorithms); - dump_cfg_string(sPubkeyAcceptedAlgorithms, o->pubkey_accepted_algos); -#if defined(__OpenBSD__) || defined(HAVE_SYS_SET_PROCESS_RDOMAIN) dump_cfg_string(sRDomain, o->routing_domain); -#endif /* string arguments requiring a lookup */ dump_cfg_string(sLogLevel, log_level_name(o->log_level)); @@ -3118,11 +3449,8 @@ printf("maxstartups %d:%d:%d\n", o->max_startups_begin, o->max_startups_rate, o->max_startups); - printf("persourcemaxstartups "); - if (o->per_source_max_startups == INT_MAX) - printf("none\n"); - else - printf("%d\n", o->per_source_max_startups); + if (o->per_source_max_startups >= 0) + printf("persourcemaxstartups, %d\n", o->per_source_max_startups); printf("persourcenetblocksize %d:%d\n", o->per_source_masklen_ipv4, o->per_source_masklen_ipv6); @@ -3165,12 +3493,4 @@ o->permit_user_env_allowlist); } - printf("pubkeyauthoptions"); - if (o->pubkey_auth_options == 0) - printf(" none"); - if (o->pubkey_auth_options & PUBKEYAUTH_TOUCH_REQUIRED) - printf(" touch-required"); - if (o->pubkey_auth_options & PUBKEYAUTH_VERIFY_REQUIRED) - printf(" verify-required"); - printf("\n"); } diff -ruN openssh-9.4p1/servconf.h openssh-9.4p1+x509-14.2.1/servconf.h --- openssh-9.4p1/servconf.h 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/servconf.h 2023-08-20 10:07:00.000000000 +0300 @@ -1,5 +1,4 @@ /* $OpenBSD: servconf.h,v 1.159 2023/01/17 09:44:48 djm Exp $ */ - /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -11,12 +10,35 @@ * software must be clearly marked as such, and if the derived work is * incompatible with the protocol description in the RFC file, it must be * called by a name other than "ssh" or "Secure Shell". + * + * Copyright (c) 2002-2021 Roumen Petrov. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef SERVCONF_H #define SERVCONF_H -#include +#include "openbsd-compat/sys-queue.h" +#include "x509store.h" #define MAX_PORTS 256 /* Max # ports. */ @@ -41,7 +63,7 @@ /* IgnoreRhosts */ #define IGNORE_RHOSTS_NO 0 #define IGNORE_RHOSTS_YES 1 -#define IGNORE_RHOSTS_SHOSTS 2 +#define IGNORE_RHOSTS_ONLY 2 #define DEFAULT_AUTH_FAIL_MAX 6 /* Default for MaxAuthTries */ #define DEFAULT_SESSIONS_MAX 10 /* Default for MaxSessions */ @@ -49,10 +71,6 @@ /* Magic name for internal sftp-server */ #define INTERNAL_SFTP_NAME "internal-sftp" -/* PubkeyAuthOptions flags */ -#define PUBKEYAUTH_TOUCH_REQUIRED (1) -#define PUBKEYAUTH_VERIFY_REQUIRED (1<<1) - struct ssh; struct fwd_perm_list; @@ -119,16 +137,13 @@ struct ForwardOptions fwd_opts; /* forwarding options */ SyslogFacility log_facility; /* Facility for system logging. */ LogLevel log_level; /* Level for system logging. */ - u_int num_log_verbose; /* Verbose log overrides */ - char **log_verbose; + u_int num_log_verbose; /* Verbose log overrides */ + char **log_verbose; int hostbased_authentication; /* If true, permit ssh2 hostbased auth */ int hostbased_uses_name_from_packet_only; /* experimental */ - char *hostbased_accepted_algos; /* Algos allowed for hostbased */ - char *hostkeyalgorithms; /* SSH2 server key types */ + char *hostkeyalgorithms; /* SSH2 allowed server host-key algorithms */ char *ca_sign_algorithms; /* Allowed CA signature algorithms */ int pubkey_authentication; /* If true, permit ssh2 pubkey authentication. */ - char *pubkey_accepted_algos; /* Signature algos allowed for pubkey */ - int pubkey_auth_options; /* -1 or mask of PUBKEYAUTH_* flags */ int kerberos_authentication; /* If true, permit Kerberos * authentication. */ int kerberos_or_local_passwd; /* If true, permit kerberos @@ -201,6 +216,30 @@ int use_pam; /* Enable auth via PAM */ + char* hostbased_algorithms; /* Allowed hostbased algorithms. */ + char* pubkey_algorithms; /* Allowed pubkey algorithms. */ + char* accepted_algorithms; /* Announced to client algorithms. */ + + /* Supported X.509 key algorithms and signatures + are defined is external source. */ + + /* sshd PKI(X509) flags */ + SSH_X509Flags x509flags; + /* sshd PKI(X509) system store */ + X509StoreOptions ca; +#ifdef LDAP_ENABLED + const char *ca_ldap_url; + const char *ca_ldap_ver; /* outdated */ +#endif +#ifdef USE_OPENSSL_STORE2 + u_int num_store_uri; + const char **store_uri; +#endif +#ifdef SSH_OCSP_ENABLED + /* ssh X.509 extra validation */ + VAOptions va; +#endif /*def SSH_OCSP_ENABLED*/ + int permit_tun; char **permitted_opens; /* May also be one of PERMITOPEN_* */ @@ -228,7 +267,6 @@ int fingerprint_hash; int expose_userauth_info; u_int64_t timing_secret; - char *sk_provider; int required_rsa_size; /* minimum size of RSA keys */ char **channel_timeouts; /* inactivity timeout by channel type */ @@ -277,8 +315,6 @@ M_CP_STROPT(authorized_principals_file); \ M_CP_STROPT(authorized_principals_command); \ M_CP_STROPT(authorized_principals_command_user); \ - M_CP_STROPT(hostbased_accepted_algos); \ - M_CP_STROPT(pubkey_accepted_algos); \ M_CP_STROPT(ca_sign_algorithms); \ M_CP_STROPT(routing_domain); \ M_CP_STROPT(permit_user_env_allowlist); \ diff -ruN openssh-9.4p1/serverloop.c openssh-9.4p1+x509-14.2.1/serverloop.c --- openssh-9.4p1/serverloop.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/serverloop.c 2023-08-20 10:07:01.000000000 +0300 @@ -13,6 +13,7 @@ * * SSH2 support by Markus Friedl. * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. + * Copyright (c) 2017-2023 Roumen Petrov. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -50,9 +51,6 @@ #include #include #include -#ifdef HAVE_POLL_H -#include -#endif #include #include #include @@ -62,7 +60,7 @@ #include "openbsd-compat/sys-queue.h" #include "xmalloc.h" #include "packet.h" -#include "sshbuf.h" +#include "ssh-x509.h" #include "log.h" #include "misc.h" #include "servconf.h" @@ -70,7 +68,6 @@ #include "sshpty.h" #include "channels.h" #include "ssh2.h" -#include "sshkey.h" #include "cipher.h" #include "kex.h" #include "hostfile.h" @@ -81,6 +78,25 @@ #include "serverloop.h" #include "ssherr.h" +/* read buffer size used in main loop */ +#if defined(HAVE_CYGWIN) && !defined(SSHD_IOBUFSZ) +# define SSHD_IOBUFSZ (64*1024) +#endif +#ifndef SSHD_IOBUFSZ +# define SSHD_IOBUFSZ (4*1024) +#endif +/* 32k 16k 8k 4k +memory: 1.345 1(*) 0.920 0.867 +buffer: 1.357 1.031 0.927 0.891 +Relative time for sftp 64M upload where (*) is old basis. +Deviation: +memory: 0.096 0.127 0.134 0.098 +buffer: 0.099 0.199 0.133 0.197 +*/ +#if 0 +# define USE_DIRECT_READ +#endif + extern ServerOptions options; /* XXX */ @@ -115,6 +131,7 @@ static void sigchld_handler(int sig) { + UNUSED(sig); child_terminated = 1; } @@ -158,36 +175,32 @@ } /* - * Sleep in ppoll() until we can do something. - * Optionally, a maximum time can be specified for the duration of - * the wait (0 = infinite). + * Sleep in pselect() until we can do something. This will initialize the + * pselect masks. Upon return, the masks will indicate which descriptors + * have data or can accept data. Optionally, a maximum time can be specified + * for the duration of the wait (0 = infinite). */ static void wait_until_can_do_something(struct ssh *ssh, - int connection_in, int connection_out, struct pollfd **pfdp, - u_int *npfd_allocp, u_int *npfd_activep, sigset_t *sigsetp, - int *conn_in_readyp, int *conn_out_readyp) + int connection_in, int connection_out, + fd_set **readsetp, fd_set **writesetp, int *maxfdp, + u_int *nallocp, sigset_t *sigsetp) { struct timespec timeout; - char remote_id[512]; int ret; int client_alive_scheduled = 0; - u_int p; time_t now; - static time_t last_client_time, unused_connection_expiry; - - *conn_in_readyp = *conn_out_readyp = 0; + static time_t last_client_time = 0, unused_connection_expiry = 0; - /* Prepare channel poll. First two pollfd entries are reserved */ ptimeout_init(&timeout); - channel_prepare_poll(ssh, pfdp, npfd_allocp, npfd_activep, 2, &timeout); + /* Allocate and update pselect() masks for channel descriptors. */ + channel_prepare_select(ssh, readsetp, writesetp, maxfdp, + nallocp, &timeout); now = monotime(); - if (*npfd_activep < 2) - fatal_f("bad npfd %u", *npfd_activep); /* shouldn't happen */ - if (options.rekey_interval > 0 && !ssh_packet_is_rekeying(ssh)) { + + if (options.rekey_interval > 0 && !ssh_packet_is_rekeying(ssh)) ptimeout_deadline_sec(&timeout, ssh_packet_get_rekey_timeout(ssh)); - } /* * If no channels are open and UnusedConnectionTimeout is set, then @@ -222,11 +235,14 @@ /* wrong: bad condition XXX */ if (channel_not_very_much_buffered_data()) #endif - /* Monitor client connection on reserved pollfd entries */ - (*pfdp)[0].fd = connection_in; - (*pfdp)[0].events = POLLIN; - (*pfdp)[1].fd = connection_out; - (*pfdp)[1].events = ssh_packet_have_data_to_write(ssh) ? POLLOUT : 0; + FD_SET(connection_in, *readsetp); + + /* + * If we have buffered packet data going to the client, mark that + * descriptor. + */ + if (ssh_packet_have_data_to_write(ssh)) + FD_SET(connection_out, *writesetp); /* * If child has terminated and there is enough buffer space to read @@ -236,20 +252,18 @@ ptimeout_deadline_ms(&timeout, 100); /* Wait for something to happen, or the timeout to expire. */ - ret = ppoll(*pfdp, *npfd_activep, ptimeout_get_tsp(&timeout), sigsetp); + ret = pselect((*maxfdp)+1, *readsetp, *writesetp, NULL, + ptimeout_get_tsp(&timeout), sigsetp); if (ret == -1) { - for (p = 0; p < *npfd_activep; p++) - (*pfdp)[p].revents = 0; + memset(*readsetp, 0, *nallocp); + memset(*writesetp, 0, *nallocp); if (errno != EINTR) - fatal_f("ppoll: %.100s", strerror(errno)); + error("pselect: %.100s", strerror(errno)); return; } - *conn_in_readyp = (*pfdp)[0].revents != 0; - *conn_out_readyp = (*pfdp)[1].revents != 0; - - now = monotime(); /* need to reset after ppoll() */ + now = monotime(); /* need to reset after pselect() */ /* ClientAliveInterval probing */ if (client_alive_scheduled) { if (ret == 0 && @@ -257,7 +271,7 @@ /* ppoll timed out and we're due to probe */ client_alive_check(ssh); last_client_time = now; - } else if (ret != 0 && *conn_in_readyp) { + } else if (ret != 0 && FD_ISSET(connection_in, *readsetp)) { /* Data from peer; reset probe timer. */ last_client_time = now; } @@ -266,6 +280,7 @@ /* UnusedConnectionTimeout handling */ if (unused_connection_expiry != 0 && now > unused_connection_expiry && !channel_still_open(ssh)) { + char remote_id[512]; sshpkt_fmt_connection_id(ssh, remote_id, sizeof(remote_id)); logit("terminating inactive connection from %s", remote_id); cleanup_exit(255); @@ -279,15 +294,42 @@ static int process_input(struct ssh *ssh, int connection_in) { +#ifndef USE_DIRECT_READ + /* read into memory buffer */ + int r, len; + char buf[SSHD_IOBUFSZ]; + + /* Read and buffer any input data from the client. */ + len = read(connection_in, buf, sizeof(buf)); + if (len == -1) { + if (errno == EAGAIN || errno == EINTR || errno == EWOULDBLOCK) + return 0; + verbose("Read error from remote host %s port %d: %s", + ssh_remote_ipaddr(ssh), ssh_remote_port(ssh), + strerror(errno)); + cleanup_exit(255); + } else if (len == 0) { + verbose("Connection closed by remote host %s port %d", + ssh_remote_ipaddr(ssh), ssh_remote_port(ssh)); + return -1; + } + /* Buffer any received data. */ + if ((r = ssh_packet_process_incoming(ssh, buf, len)) != 0) + fatal_fr(r, "ssh_packet_process_incoming"); + + return 0; +#else + /* direct read into input buffer */ int r; - if ((r = ssh_packet_process_read(ssh, connection_in)) == 0) - return 0; /* success */ + r = ssh_packet_process_read(ssh, connection_in, SSHD_IOBUFSZ); + if (r == 0) return r; /* success */ + if (r == SSH_ERR_SYSTEM_ERROR) { if (errno == EAGAIN || errno == EINTR || errno == EWOULDBLOCK) return 0; if (errno == EPIPE) { - verbose("Connection closed by %.100s port %d", + verbose("Connection closed by remote host %s port %d", ssh_remote_ipaddr(ssh), ssh_remote_port(ssh)); return -1; } @@ -297,13 +339,14 @@ cleanup_exit(255); } return -1; +#endif } /* * Sends data from internal buffers to client program stdin. */ static void -process_output(struct ssh *ssh, int connection_out) +process_output(struct ssh *ssh) { int r; @@ -339,12 +382,12 @@ void server_loop2(struct ssh *ssh, Authctxt *authctxt) { - struct pollfd *pfd = NULL; - u_int npfd_alloc = 0, npfd_active = 0; - int r, conn_in_ready, conn_out_ready; - u_int connection_in, connection_out; + fd_set *readset = NULL, *writeset = NULL; + int max_fd; + u_int nalloc = 0, connection_in, connection_out; sigset_t bsigset, osigset; + UNUSED(authctxt); debug("Entering interactive session for SSH2."); if (sigemptyset(&bsigset) == -1 || sigaddset(&bsigset, SIGCHLD) == -1) @@ -360,9 +403,13 @@ ssh_signal(SIGQUIT, sigterm_handler); } + max_fd = MAXIMUM(connection_in, connection_out); + server_init_dispatch(ssh); for (;;) { + int conn_in_ready, conn_out_ready; + process_buffered_input_packets(ssh); if (!ssh_packet_is_rekeying(ssh) && @@ -371,16 +418,18 @@ /* * Block SIGCHLD while we check for dead children, then pass - * the old signal mask through to ppoll() so that it'll wake + * the old signal mask through to pselect() so that it'll wake * up immediately if a child exits after we've called waitpid(). */ if (sigprocmask(SIG_BLOCK, &bsigset, &osigset) == -1) error_f("bsigset sigprocmask: %s", strerror(errno)); collect_children(ssh); wait_until_can_do_something(ssh, connection_in, connection_out, - &pfd, &npfd_alloc, &npfd_active, &osigset, - &conn_in_ready, &conn_out_ready); - if (sigprocmask(SIG_UNBLOCK, &bsigset, &osigset) == -1) + &readset, &writeset, &max_fd, &nalloc, + &osigset); + conn_in_ready = FD_ISSET(connection_in, readset); + conn_out_ready = FD_ISSET(connection_out, writeset); + if (sigprocmask(SIG_SETMASK, &osigset, NULL) == -1) error_f("osigset sigprocmask: %s", strerror(errno)); if (received_sigterm) { @@ -389,18 +438,22 @@ cleanup_exit(255); } - channel_after_poll(ssh, pfd, npfd_active); + channel_after_select(ssh, readset, writeset); if (conn_in_ready && process_input(ssh, connection_in) < 0) break; - /* A timeout may have triggered rekeying */ - if ((r = ssh_packet_check_rekey(ssh)) != 0) + { /* A timeout may have triggered rekeying */ + int r = ssh_packet_check_rekey(ssh); + if (r != 0) fatal_fr(r, "cannot start rekeying"); + } if (conn_out_ready) - process_output(ssh, connection_out); + process_output(ssh); } collect_children(ssh); - free(pfd); + + free(readset); + free(writeset); /* free all channels, no more reads and writes */ channel_free_all(ssh); @@ -427,7 +480,7 @@ { Channel *c = NULL; char *target = NULL, *originator = NULL; - u_int target_port = 0, originator_port = 0; + u_int32_t target_port = 0, originator_port = 0; int r; if ((r = sshpkt_get_cstring(ssh, &target, NULL)) != 0 || @@ -448,7 +501,8 @@ } debug_f("originator %s port %u, target %s port %u", - originator, originator_port, target, target_port); + originator, (unsigned)originator_port, + target, (unsigned)target_port); /* XXX fine grained permissions */ if ((options.allow_tcp_forwarding & FORWARD_LOCAL) != 0 && @@ -458,8 +512,9 @@ "direct-tcpip", "direct-tcpip", reason, errmsg); } else { logit("refused local port forward: " - "originator %s port %d, target %s port %d", - originator, originator_port, target, target_port); + "originator %s port %u, target %s port %u", + originator, (unsigned)originator_port, + target, (unsigned)target_port); if (reason != NULL) *reason = SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED; } @@ -475,7 +530,7 @@ { Channel *c = NULL; char *target = NULL, *originator = NULL; - u_int originator_port = 0; + u_int32_t originator_port = 0; struct passwd *pw = the_authctxt->pw; int r; @@ -492,8 +547,8 @@ goto out; } - debug_f("originator %s port %d, target %s", - originator, originator_port, target); + debug_f("originator %s port %u, target %s", + originator, (unsigned)originator_port, target); /* XXX fine grained permissions */ if ((options.allow_streamlocal_forwarding & FORWARD_LOCAL) != 0 && @@ -503,8 +558,8 @@ "direct-streamlocal@openssh.com", "direct-streamlocal"); } else { logit("refused streamlocal port forward: " - "originator %s port %d, target %s", - originator, originator_port, target); + "originator %s port %u, target %s", + originator, (unsigned)originator_port, target); } out: @@ -517,7 +572,7 @@ server_request_tun(struct ssh *ssh) { Channel *c = NULL; - u_int mode, tun; + u_int32_t mode, tun; int r, sock; char *tmp, *ifname = NULL; @@ -539,7 +594,7 @@ if ((r = sshpkt_get_u32(ssh, &tun)) != 0) sshpkt_fatal(ssh, r, "%s: parse device", __func__); - if (tun > INT_MAX) { + if ((tun > SSH_TUNID_MAX) && (tun != SSH_TUNID_ANY)) { debug_f("invalid tun"); goto done; } @@ -622,15 +677,17 @@ char *ctype = NULL; const char *errmsg = NULL; int r, reason = SSH2_OPEN_CONNECT_FAILED; - u_int rchan = 0, rmaxpack = 0, rwindow = 0; + u_int32_t rchan = 0, rmaxpack = 0, rwindow = 0; + UNUSED(type); + UNUSED(seq); if ((r = sshpkt_get_cstring(ssh, &ctype, NULL)) != 0 || (r = sshpkt_get_u32(ssh, &rchan)) != 0 || (r = sshpkt_get_u32(ssh, &rwindow)) != 0 || (r = sshpkt_get_u32(ssh, &rmaxpack)) != 0) sshpkt_fatal(ssh, r, "%s: parse packet", __func__); debug_f("ctype %s rchan %u win %u max %u", - ctype, rchan, rwindow, rmaxpack); + ctype, (unsigned)rchan, (unsigned)rwindow, (unsigned)rmaxpack); if (strcmp(ctype, "session") == 0) { c = server_request_session(ssh); @@ -680,25 +737,33 @@ struct sshbuf *resp = NULL; struct sshbuf *sigbuf = NULL; struct sshkey *key = NULL, *key_pub = NULL, *key_prv = NULL; + char *pkalg = NULL; int r, ndx, success = 0; const u_char *blob; - const char *sigalg, *kex_rsa_sigalg = NULL; + const char *rsa_kexalg = NULL; u_char *sig = 0; size_t blen, slen; + if (ssh->kex->hostkey_alg != NULL) { + int hktype = sshkey_type_from_name(ssh->kex->hostkey_alg); + if (sshkey_type_plain(hktype) == KEY_RSA) + rsa_kexalg = ssh->kex->hostkey_alg; + } + if ((resp = sshbuf_new()) == NULL || (sigbuf = sshbuf_new()) == NULL) fatal_f("sshbuf_new"); - if (sshkey_type_plain(sshkey_type_from_name( - ssh->kex->hostkey_alg)) == KEY_RSA) - kex_rsa_sigalg = ssh->kex->hostkey_alg; + while (ssh_packet_remaining(ssh) > 0) { sshkey_free(key); key = NULL; + free(pkalg); + pkalg = NULL; if ((r = sshpkt_get_string_direct(ssh, &blob, &blen)) != 0 || - (r = sshkey_from_blob(blob, blen, &key)) != 0) { + (r = parse_key_from_blob(blob, blen, &key, &pkalg)) != 0) { error_fr(r, "parse key"); goto out; } + debug3_f("pkalg %s", pkalg); /* * Better check that this is actually one of our hostkeys * before attempting to sign anything with it. @@ -707,6 +772,7 @@ error_f("unknown host %s key", sshkey_type(key)); goto out; } + debug3_f("ndx %d", ndx); /* * XXX refactor: make kex->sign just use an index rather * than passing in public and private keys @@ -719,33 +785,38 @@ sshbuf_reset(sigbuf); free(sig); sig = NULL; - /* - * For RSA keys, prefer to use the signature type negotiated - * during KEX to the default (SHA1). - */ - sigalg = NULL; - if (sshkey_type_plain(key->type) == KEY_RSA) { - if (kex_rsa_sigalg != NULL) - sigalg = kex_rsa_sigalg; - else if (ssh->kex->flags & KEX_RSA_SHA2_512_SUPPORTED) - sigalg = "rsa-sha2-512"; + if (sshkey_type_plain(key->type) == KEY_RSA && + !sshkey_is_x509(key) + ) { + const char *rsa_keyalg = NULL; + if (rsa_kexalg != NULL) + rsa_keyalg = rsa_kexalg; else if (ssh->kex->flags & KEX_RSA_SHA2_256_SUPPORTED) - sigalg = "rsa-sha2-256"; + rsa_keyalg = "rsa-sha2-256"; + else if (ssh->kex->flags & KEX_RSA_SHA2_512_SUPPORTED) + rsa_keyalg = "rsa-sha2-512"; + debug3_f("sign rsa key %d using %s signature", ndx, + rsa_keyalg == NULL ? "default" : rsa_keyalg); + if (rsa_keyalg != NULL) { + free(pkalg); + pkalg = xstrdup(rsa_keyalg); + } } - debug3_f("sign %s key (index %d) using sigalg %s", - sshkey_type(key), ndx, sigalg == NULL ? "default" : sigalg); + { ssh_sign_ctx ctx = { pkalg, key_prv, &ssh->compat, NULL, NULL }; + if ((r = sshbuf_put_cstring(sigbuf, "hostkeys-prove-00@openssh.com")) != 0 || (r = sshbuf_put_stringb(sigbuf, - ssh->kex->session_id)) != 0 || - (r = sshkey_puts(key, sigbuf)) != 0 || - (r = ssh->kex->sign(ssh, key_prv, key_pub, &sig, &slen, - sshbuf_ptr(sigbuf), sshbuf_len(sigbuf), sigalg)) != 0 || + ssh->kex->session_id)) != 0 || + (r = Xkey_puts(pkalg, key, sigbuf)) != 0 || + (r = ssh->kex->xsign(ssh, &ctx, key_pub, &sig, &slen, + sshbuf_ptr(sigbuf), sshbuf_len(sigbuf))) != 0 || (r = sshbuf_put_string(resp, sig, slen)) != 0) { error_fr(r, "assemble signature"); goto out; } } + } /* Success */ *respp = resp; resp = NULL; /* don't free it */ @@ -755,6 +826,7 @@ sshbuf_free(resp); sshbuf_free(sigbuf); sshkey_free(key); + free(pkalg); return success; } @@ -764,11 +836,13 @@ char *rtype = NULL; u_char want_reply = 0; int r, success = 0, allocated_listen_port = 0; - u_int port = 0; + u_int32_t port = 0; struct sshbuf *resp = NULL; struct passwd *pw = the_authctxt->pw; struct Forward fwd; + UNUSED(type); + UNUSED(seq); memset(&fwd, 0, sizeof(fwd)); if (pw == NULL || !the_authctxt->valid) fatal_f("no/invalid user"); @@ -776,7 +850,7 @@ if ((r = sshpkt_get_cstring(ssh, &rtype, NULL)) != 0 || (r = sshpkt_get_u8(ssh, &want_reply)) != 0) sshpkt_fatal(ssh, r, "%s: parse packet", __func__); - debug_f("rtype %s want_reply %d", rtype, want_reply); + debug_f("rtype %s want_reply %d", rtype, (int)want_reply); /* -R style forwarding */ if (strcmp(rtype, "tcpip-forward") == 0) { @@ -784,7 +858,7 @@ (r = sshpkt_get_u32(ssh, &port)) != 0) sshpkt_fatal(ssh, r, "%s: parse tcpip-forward", __func__); debug_f("tcpip-forward listen %s port %u", - fwd.listen_host, port); + fwd.listen_host, (unsigned)port); if (port <= INT_MAX) fwd.listen_port = (int)port; /* check permissions */ @@ -812,8 +886,8 @@ (r = sshpkt_get_u32(ssh, &port)) != 0) sshpkt_fatal(ssh, r, "%s: parse cancel-tcpip-forward", __func__); - debug_f("cancel-tcpip-forward addr %s port %d", - fwd.listen_host, port); + debug_f("cancel-tcpip-forward addr %s port %u", + fwd.listen_host, (unsigned)port); if (port <= INT_MAX) { fwd.listen_port = (int)port; success = channel_cancel_rport_listener(ssh, &fwd); @@ -873,19 +947,21 @@ int r, success = 0; char *rtype = NULL; u_char want_reply = 0; - u_int id = 0; + u_int32_t id = 0; + UNUSED(type); + UNUSED(seq); if ((r = sshpkt_get_u32(ssh, &id)) != 0 || (r = sshpkt_get_cstring(ssh, &rtype, NULL)) != 0 || (r = sshpkt_get_u8(ssh, &want_reply)) != 0) sshpkt_fatal(ssh, r, "%s: parse packet", __func__); debug("server_input_channel_req: channel %u request %s reply %d", - id, rtype, want_reply); + (unsigned)id, rtype, (int)want_reply); - if (id >= INT_MAX || (c = channel_lookup(ssh, (int)id)) == NULL) { - ssh_packet_disconnect(ssh, "%s: unknown channel %d", - __func__, id); + if (id >= INT_MAX || (c = channel_lookup(ssh, id)) == NULL) { + ssh_packet_disconnect(ssh, "%s: unknown channel %u", + __func__, (unsigned)id); } if (!strcmp(rtype, "eow@openssh.com")) { if ((r = sshpkt_get_end(ssh)) != 0) diff -ruN openssh-9.4p1/session.c openssh-9.4p1+x509-14.2.1/session.c --- openssh-9.4p1/session.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/session.c 2023-08-20 10:07:01.000000000 +0300 @@ -11,6 +11,7 @@ * * SSH2 support by Markus Friedl. * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. + * Copyright (c) 2012-2020 Roumen Petrov. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -35,7 +36,6 @@ #include "includes.h" -#include #ifdef HAVE_SYS_STAT_H # include #endif @@ -69,11 +69,9 @@ #include "sshpty.h" #include "packet.h" #include "sshbuf.h" -#include "ssherr.h" #include "match.h" #include "uidswap.h" #include "channels.h" -#include "sshkey.h" #include "cipher.h" #ifdef GSSAPI #include "ssh-gss.h" @@ -110,27 +108,21 @@ c[sizeof(INTERNAL_SFTP_NAME) - 1] == '\t')) /* func */ - -Session *session_new(void); -void session_set_fds(struct ssh *, Session *, int, int, int, int, int); -void session_pty_cleanup(Session *); -void session_proctitle(Session *); -int session_setup_x11fwd(struct ssh *, Session *); -int do_exec_pty(struct ssh *, Session *, const char *); -int do_exec_no_pty(struct ssh *, Session *, const char *); -int do_exec(struct ssh *, Session *, const char *); -void do_login(struct ssh *, Session *, const char *); -void do_child(struct ssh *, Session *, const char *); -void do_motd(void); -int check_quietlogin(Session *, const char *); - -static void do_authenticated2(struct ssh *, Authctxt *); - -static int session_pty_req(struct ssh *, Session *); +static void session_set_fds(struct ssh *, Session *, int, int, int, int, int); +static void session_pty_cleanup(Session *); +static void session_proctitle(Session *); +static int session_setup_x11fwd(struct ssh *, Session *); +static void do_login(struct ssh *, Session *, const char *); +static void do_child(struct ssh *, Session *, const char *); +static void do_motd(void); +static int check_quietlogin(Session *, const char *); +static void do_authenticated2(struct ssh *, Authctxt *); +static int session_pty_req(struct ssh *, Session *); /* import */ extern ServerOptions options; extern char *__progname; +extern int log_stderr; extern int debug_flag; extern u_int utmp_len; extern int startup_pipe; @@ -195,7 +187,13 @@ temporarily_use_uid(pw); /* Allocate a buffer for the socket name, and format the name. */ - auth_sock_dir = xstrdup("/tmp/ssh-XXXXXXXXXX"); +{ char *template = mkdtemp_template("ssh-"); + if (template == NULL) { + restore_uid(); + goto authsock_err; + } + auth_sock_dir = template; +} /* Create private directory for socket */ if (mkdtemp(auth_sock_dir) == NULL) { @@ -265,7 +263,13 @@ return; temporarily_use_uid(pw); - auth_info_file = xstrdup("/tmp/sshauth.XXXXXXXXXXXXXXX"); +{ char *template = mkdtemp_template("sshauth."); + if (template == NULL) { + error_f("error in template string"); + goto out; + } + auth_info_file = template; +} if ((fd = mkstemp(auth_info_file)) == -1) { error_f("mkstemp: %s", strerror(errno)); goto out; @@ -275,7 +279,7 @@ error_f("write: %s", strerror(errno)); goto out; } - if (close(fd) != 0) { + if (close(fd) == -1) { error_f("close: %s", strerror(errno)); goto out; } @@ -297,12 +301,13 @@ int port; size_t i; + UNUSED(opts); if ((options.allow_tcp_forwarding & FORWARD_LOCAL) != 0) { channel_clear_permission(ssh, FORWARD_USER, FORWARD_LOCAL); for (i = 0; i < auth_opts->npermitopen; i++) { tmp = cp = xstrdup(auth_opts->permitopen[i]); /* This shouldn't fail as it has already been checked */ - if ((host = hpdelim2(&cp, NULL)) == NULL) + if ((host = hpdelim(&cp)) == NULL) fatal_f("internal error: hpdelim"); host = cleanhostname(host); if (cp == NULL || (port = permitopen_port(cp)) < 0) @@ -384,7 +389,7 @@ * will call do_child from the child, and server_loop from the parent after * setting up file descriptors and such. */ -int +static int do_exec_no_pty(struct ssh *ssh, Session *s, const char *command) { pid_t pid; @@ -392,7 +397,7 @@ int pin[2], pout[2], perr[2]; if (s == NULL) - fatal("do_exec_no_pty: no session"); + fatal_f("no session"); /* Allocate pipes for communicating with the program. */ if (pipe(pin) == -1) { @@ -417,7 +422,7 @@ int inout[2], err[2]; if (s == NULL) - fatal("do_exec_no_pty: no session"); + fatal_f("no session"); /* Uses socket pairs to communicate with the program. */ if (socketpair(AF_UNIX, SOCK_STREAM, 0, inout) == -1) { @@ -455,6 +460,10 @@ case 0: is_child = 1; + /* Child. Reinitialize the log since the pid has changed. */ + log_init(__progname, options.log_level, + options.log_facility, log_stderr); + /* * Create a new session and process group since the 4.4BSD * setlogin() affects the entire process group. @@ -468,19 +477,19 @@ * pair, and make the child side the standard input. */ close(pin[1]); - if (dup2(pin[0], 0) == -1) + if (dup2(pin[0], STDIN_FILENO) == -1) perror("dup2 stdin"); close(pin[0]); /* Redirect stdout. */ close(pout[0]); - if (dup2(pout[1], 1) == -1) + if (dup2(pout[1], STDOUT_FILENO) == -1) perror("dup2 stdout"); close(pout[1]); /* Redirect stderr. */ close(perr[0]); - if (dup2(perr[1], 2) == -1) + if (dup2(perr[1], STDERR_FILENO) == -1) perror("dup2 stderr"); close(perr[1]); #else @@ -491,12 +500,12 @@ */ close(inout[1]); close(err[1]); - if (dup2(inout[0], 0) == -1) /* stdin */ + if (dup2(inout[0], STDIN_FILENO) == -1) perror("dup2 stdin"); - if (dup2(inout[0], 1) == -1) /* stdout (same as stdin) */ + if (dup2(inout[0], STDOUT_FILENO) == -1) perror("dup2 stdout"); close(inout[0]); - if (dup2(err[0], 2) == -1) /* stderr */ + if (dup2(err[0], STDERR_FILENO) == -1) perror("dup2 stderr"); close(err[0]); #endif @@ -553,14 +562,14 @@ * setting up file descriptors, controlling tty, updating wtmp, utmp, * lastlog, and other such operations. */ -int +static int do_exec_pty(struct ssh *ssh, Session *s, const char *command) { int fdout, ptyfd, ttyfd, ptymaster; pid_t pid; if (s == NULL) - fatal("do_exec_pty: no session"); + fatal_f("no session"); ptyfd = s->ptyfd; ttyfd = s->ttyfd; @@ -601,6 +610,9 @@ close(fdout); close(ptymaster); + /* Child. Reinitialize the log because the pid has changed. */ + log_init(__progname, options.log_level, + options.log_facility, log_stderr); /* Close the master side of the pseudo tty. */ close(ptyfd); @@ -608,11 +620,11 @@ pty_make_controlling_tty(&ttyfd, s->tty); /* Redirect stdin/stdout/stderr from the pseudo tty. */ - if (dup2(ttyfd, 0) == -1) + if (dup2(ttyfd, STDIN_FILENO) == -1) error("dup2 stdin: %s", strerror(errno)); - if (dup2(ttyfd, 1) == -1) + if (dup2(ttyfd, STDOUT_FILENO) == -1) error("dup2 stdout: %s", strerror(errno)); - if (dup2(ttyfd, 2) == -1) + if (dup2(ttyfd, STDERR_FILENO) == -1) error("dup2 stderr: %s", strerror(errno)); /* Close the extra descriptor for the pseudo tty. */ @@ -653,7 +665,7 @@ * This is called to fork and execute a command. If another command is * to be forced, execute that instead. */ -int +static int do_exec(struct ssh *ssh, Session *s, const char *command) { int ret; @@ -733,7 +745,7 @@ } /* administrative, login(1)-like work */ -void +static void do_login(struct ssh *ssh, Session *s, const char *command) { socklen_t fromlen; @@ -786,7 +798,7 @@ /* * Display the message of the day. */ -void +static void do_motd(void) { FILE *f; @@ -811,7 +823,7 @@ /* * Check for quiet login, either .hushlogin or command given. */ -int +static int check_quietlogin(Session *s, const char *command) { char buf[256]; @@ -823,10 +835,10 @@ return 1; snprintf(buf, sizeof(buf), "%.200s/.hushlogin", pw->pw_dir); #ifdef HAVE_LOGIN_CAP - if (login_getcapbool(lc, "hushlogin", 0) || stat(buf, &st) >= 0) + if (login_getcapbool(lc, "hushlogin", 0) || stat(buf, &st) != -1) return 1; #else - if (stat(buf, &st) >= 0) + if (stat(buf, &st) != -1) return 1; #endif return 0; @@ -842,8 +854,9 @@ */ static void read_environment_file(char ***env, u_int *envsize, - const char *filename, const char *allowlist) + const char *filename) { + const char *allowlist = options.permit_user_env_allowlist; FILE *f; char *line = NULL, *cp, *value; size_t linesize = 0; @@ -917,8 +930,7 @@ * so we use a temporary environment and copy the variables we're * interested in. */ - read_environment_file(&tmpenv, &tmpenvsize, "/etc/default/login", - options.permit_user_env_allowlist); + read_environment_file(&tmpenv, &tmpenvsize, "/etc/default/login"); if (tmpenv == NULL) return; @@ -970,21 +982,13 @@ } #endif /* defined(USE_PAM) || defined(HAVE_CYGWIN) */ -#ifdef HAVE_CYGWIN -static void -copy_environment(char **source, char ***env, u_int *envsize) -{ - copy_environment_denylist(source, env, envsize, NULL); -} -#endif - static char ** do_setup_env(struct ssh *ssh, Session *s, const char *shell) { char buf[256]; size_t n; u_int i, envsize; - char *ocp, *cp, *value, **env, *laddr; + char *ocp, *cp, **env, *laddr; struct passwd *pw = s->pw; #if !defined (HAVE_LOGIN_CAP) && !defined (HAVE_CYGWIN) char *path = NULL; @@ -1004,7 +1008,7 @@ char **p; p = fetch_windows_environment(); - copy_environment(p, &env, &envsize); + copy_environment_denylist(p, &env, &envsize, NULL); free_windows_environment(p); } #endif @@ -1050,21 +1054,23 @@ # endif /* HAVE_CYGWIN */ #endif /* HAVE_LOGIN_CAP */ +#ifdef __ANDROID__ +/* _PATH_MAILDIR is defined in platform headers but not in unified */ +# undef _PATH_MAILDIR +#endif +#ifdef _PATH_MAILDIR if (!options.use_pam) { snprintf(buf, sizeof buf, "%.200s/%.50s", _PATH_MAILDIR, pw->pw_name); child_set_env(&env, &envsize, "MAIL", buf); } +#endif /* Normal systems set SHELL by default. */ child_set_env(&env, &envsize, "SHELL", shell); if (getenv("TZ")) child_set_env(&env, &envsize, "TZ", getenv("TZ")); - if (s->term) - child_set_env(&env, &envsize, "TERM", s->term); - if (s->display) - child_set_env(&env, &envsize, "DISPLAY", s->display); /* * Since we clear KRB5CCNAME at startup, if it's set now then it @@ -1072,20 +1078,15 @@ * SIA), so copy it to the child. */ { - char *cp; - if ((cp = getenv("KRB5CCNAME")) != NULL) child_set_env(&env, &envsize, "KRB5CCNAME", cp); } #ifdef _AIX { - char *cp; - if ((cp = getenv("AUTHSTATE")) != NULL) child_set_env(&env, &envsize, "AUTHSTATE", cp); - read_environment_file(&env, &envsize, "/etc/environment", - options.permit_user_env_allowlist); + read_environment_file(&env, &envsize, "/etc/environment"); } #endif #ifdef KRB5 @@ -1093,37 +1094,6 @@ child_set_env(&env, &envsize, "KRB5CCNAME", s->authctxt->krb5_ccname); #endif - if (auth_sock_name != NULL) - child_set_env(&env, &envsize, SSH_AUTHSOCKET_ENV_NAME, - auth_sock_name); - - - /* Set custom environment options from pubkey authentication. */ - if (options.permit_user_env) { - for (n = 0 ; n < auth_opts->nenv; n++) { - ocp = xstrdup(auth_opts->env[n]); - cp = strchr(ocp, '='); - if (cp != NULL) { - *cp = '\0'; - /* Apply PermitUserEnvironment allowlist */ - if (options.permit_user_env_allowlist == NULL || - match_pattern_list(ocp, - options.permit_user_env_allowlist, 0) == 1) - child_set_env(&env, &envsize, - ocp, cp + 1); - } - free(ocp); - } - } - - /* read $HOME/.ssh/environment. */ - if (options.permit_user_env) { - snprintf(buf, sizeof buf, "%.200s/%s/environment", - pw->pw_dir, _PATH_SSH_USER_DIR); - read_environment_file(&env, &envsize, buf, - options.permit_user_env_allowlist); - } - #ifdef USE_PAM /* * Pull in any environment variables that may have @@ -1149,16 +1119,43 @@ } #endif /* USE_PAM */ + /* Set custom environment options from pubkey authentication. */ + if (options.permit_user_env) { + for (n = 0 ; n < auth_opts->nenv; n++) { + ocp = xstrdup(auth_opts->env[n]); + cp = strchr(ocp, '='); + if (cp != NULL) { + *cp = '\0'; + /* Apply PermitUserEnvironment allowlist */ + if (options.permit_user_env_allowlist == NULL || + match_pattern_list(ocp, + options.permit_user_env_allowlist, 0) == 1) + child_set_env(&env, &envsize, + ocp, cp + 1); + } + free(ocp); + } + } + /* read $HOME/.ssh/environment. */ + if (options.permit_user_env) { + snprintf(buf, sizeof buf, "%.200s/%s/environment", + strcmp(pw->pw_dir, "/") ? pw->pw_dir : "", + _PATH_SSH_USER_DIR + ); + read_environment_file(&env, &envsize, buf); + } + /* Environment specified by admin */ for (i = 0; i < options.num_setenv; i++) { - cp = xstrdup(options.setenv[i]); - if ((value = strchr(cp, '=')) == NULL) { + ocp = xstrdup(options.setenv[i]); + cp = strchr(ocp, '='); + if (cp == NULL) { /* shouldn't happen; vars are checked in servconf.c */ fatal("Invalid config SetEnv: %s", options.setenv[i]); } - *value++ = '\0'; - child_set_env(&env, &envsize, cp, value); - free(cp); + *cp = '\0'; + child_set_env(&env, &envsize, ocp, cp + 1); + free(ocp); } /* SSH_CLIENT deprecated */ @@ -1180,10 +1177,58 @@ child_set_env(&env, &envsize, "SSH_USER_AUTH", auth_info_file); if (s->ttyfd != -1) child_set_env(&env, &envsize, "SSH_TTY", s->tty); + if (s->term) + child_set_env(&env, &envsize, "TERM", s->term); + if (s->display) + child_set_env(&env, &envsize, "DISPLAY", s->display); if (original_command) child_set_env(&env, &envsize, "SSH_ORIGINAL_COMMAND", original_command); + if (auth_sock_name != NULL) + child_set_env(&env, &envsize, SSH_AUTHSOCKET_ENV_NAME, + auth_sock_name); + +#ifdef __ANDROID__ +{ +#define COPY_ANDROID_ENV(name) { \ + if ((cp = getenv(name)) != NULL) \ + child_set_env(&env, &envsize, name, cp); } + + /* from /init.rc (or /init.environ.rc) */ + COPY_ANDROID_ENV("ANDROID_BOOTLOGO"); + COPY_ANDROID_ENV("ANDROID_ROOT"); + COPY_ANDROID_ENV("ANDROID_ASSETS"); + COPY_ANDROID_ENV("ANDROID_DATA"); + COPY_ANDROID_ENV("ANDROID_STORAGE"); + COPY_ANDROID_ENV("ANDROID_ART_ROOT"); + COPY_ANDROID_ENV("ANDROID_I18N_ROOT"); + COPY_ANDROID_ENV("ANDROID_TZDATA_ROOT"); + COPY_ANDROID_ENV("EXTERNAL_STORAGE"); + COPY_ANDROID_ENV("ASEC_MOUNTPOINT"); + COPY_ANDROID_ENV("BOOTCLASSPATH"); + COPY_ANDROID_ENV("DEX2OATBOOTCLASSPATH"); + COPY_ANDROID_ENV("SYSTEMSERVERCLASSPATH"); + + /* on Android Q(10.0, API level 29) "am" requires ANDROID_RUNTIME_ROOT to run */ + COPY_ANDROID_ENV("ANDROID_RUNTIME_ROOT"); + + COPY_ANDROID_ENV("LOOP_MOUNTPOINT"); /* ??? */ + + /* FIXME: keep android property workspace open + * (see openbsd-compat/bsd-closefrom.c) + */ + COPY_ANDROID_ENV("ANDROID_PROPERTY_WORKSPACE"); + + COPY_ANDROID_ENV("SECONDARY_STORAGE"); /* ??? */ + COPY_ANDROID_ENV("SD_EXT_DIRECTORY"); /* ??? */ + + /* may contain path to custom libraries */ + COPY_ANDROID_ENV("LD_LIBRARY_PATH"); +#undef COPY_ANDROID_ENV +} +#endif + if (debug_flag) { /* dump the environment */ fprintf(stderr, "Environment:\n"); @@ -1205,17 +1250,17 @@ int do_xauth; struct stat st; + UNUSED(ssh); do_xauth = s->display != NULL && s->auth_proto != NULL && s->auth_data != NULL; xasprintf(&user_rc, "%s/%s", s->pw->pw_dir, _PATH_SSH_USER_RC); - /* ignore _PATH_SSH_USER_RC for subsystems and admin forced commands */ + /* ignore "user ssh rc" for subsystems and admin forced commands */ if (!s->is_subsystem && options.adm_forced_command == NULL && auth_opts->permit_user_rc && options.permit_user_rc && - stat(user_rc, &st) >= 0) { - if (xasprintf(&cmd, "%s -c '%s %s'", shell, _PATH_BSHELL, - user_rc) == -1) - fatal_f("xasprintf: %s", strerror(errno)); + stat(user_rc, &st) != -1) { + xasprintf(&cmd, "%s -c '%s %s'", + shell, _PATH_BSHELL, user_rc); if (debug_flag) fprintf(stderr, "Running %s\n", cmd); f = popen(cmd, "w"); @@ -1227,7 +1272,7 @@ } else fprintf(stderr, "Could not run %s\n", user_rc); - } else if (stat(_PATH_SSH_SYSTEM_RC, &st) >= 0) { + } else if (stat(_PATH_SSH_SYSTEM_RC, &st) != -1) { if (debug_flag) fprintf(stderr, "Running %s %s\n", _PATH_BSHELL, _PATH_SSH_SYSTEM_RC); @@ -1251,8 +1296,7 @@ options.xauth_location, s->auth_display, s->auth_proto, s->auth_data); } - if (xasprintf(&cmd, "%s -q -", options.xauth_location) == -1) - fatal_f("xasprintf: %s", strerror(errno)); + xasprintf(&cmd, "%s -q -", options.xauth_location); f = popen(cmd, "w"); if (f) { fprintf(f, "remove %s\n", @@ -1274,13 +1318,20 @@ do_nologin(struct passwd *pw) { FILE *f = NULL; - char buf[1024], *nl, *def_nl = _PATH_NOLOGIN; + const char *nl, *def_nl = _PATH_NOLOGIN; struct stat sb; #ifdef HAVE_LOGIN_CAP if (login_getcapbool(lc, "ignorenologin", 0) || pw->pw_uid == 0) return; nl = login_getcapstr(lc, "nologin", def_nl, def_nl); + /* Do not free string returned by login_getcapstr(3)! + Some BSD variants require the caller to free strings returned by the + login_* functions. Others like FreeBSD require that callers do not. + + Note it is harmless memory leak as the process is about to exec the + shell/command. + */ #else if (pw->pw_uid == 0) return; @@ -1292,6 +1343,7 @@ /* /etc/nologin exists. Print its contents if we can and exit. */ logit("User %.100s not allowed because %s exists", pw->pw_name, nl); if ((f = fopen(nl, "r")) != NULL) { + char buf[1024]; while (fgets(buf, sizeof(buf), f)) fputs(buf, stderr); fclose(f); @@ -1310,6 +1362,7 @@ char component[PATH_MAX]; struct stat st; + UNUSED(uid); if (!path_absolute(path)) fatal("chroot path does not begin at root"); if (strlen(path) >= sizeof(component)) @@ -1327,10 +1380,10 @@ memcpy(component, path, cp - path); component[cp - path] = '\0'; } - + debug3_f("checking '%s'", component); - if (stat(component, &st) != 0) + if (stat(component, &st) == -1) fatal_f("stat(\"%s\"): %s", component, strerror(errno)); if (st.st_uid != 0 || (st.st_mode & 022) != 0) @@ -1376,7 +1429,7 @@ exit(1); } /* Initialize the group list. */ - if (initgroups(pw->pw_name, pw->pw_gid) < 0) { + if (initgroups(pw->pw_name, pw->pw_gid) == -1) { perror("initgroups"); exit(1); } @@ -1407,7 +1460,7 @@ perror("unable to set user context (setuser)"); exit(1); } - /* + /* * FreeBSD's setusercontext() will not apply the user's * own umask setting unless running with the user's UID. */ @@ -1510,7 +1563,7 @@ * ids, and executing the command or shell. */ #define ARGV_MAX 10 -void +static void do_child(struct ssh *ssh, Session *s, const char *command) { extern char **environ; @@ -1635,7 +1688,9 @@ exit(1); } +#if 0 /* done in child_close_fds() above */ closefrom(STDERR_FILENO + 1); +#endif do_rc_files(ssh, s, shell); @@ -1770,7 +1825,7 @@ sessions_first_unused = s->next_unused; s->used = 1; s->next_unused = -1; - debug("session_new: session %d", s->self); + debug_f("session %d", s->self); return s; } @@ -1796,7 +1851,7 @@ session_open(Authctxt *authctxt, int chanid) { Session *s = session_new(); - debug("session_open: channel %d", chanid); + debug_f("channel %d", chanid); if (s == NULL) { error("no more sessions"); return 0; @@ -1805,7 +1860,7 @@ s->pw = authctxt->pw; if (s->pw == NULL || !authctxt->valid) fatal("no user for session %d", s->self); - debug("session_open: session %d: link with channel %d", s->self, chanid); + debug_f("session %d: link with channel %d", s->self, chanid); s->chanid = chanid; return 1; } @@ -1817,11 +1872,11 @@ for (i = 0; i < sessions_nalloc; i++) { Session *s = &sessions[i]; if (s->used && s->ttyfd != -1 && strcmp(s->tty, tty) == 0) { - debug("session_by_tty: session %d tty %s", i, tty); + debug_f("session %d tty %s", i, tty); return s; } } - debug("session_by_tty: unknown tty %.100s", tty); + debug_f("unknown tty %.100s", tty); session_dump(); return NULL; } @@ -1833,12 +1888,11 @@ for (i = 0; i < sessions_nalloc; i++) { Session *s = &sessions[i]; if (s->used && s->chanid == id) { - debug("session_by_channel: session %d channel %d", - i, id); + debug_f("session %d channel %d", i, id); return s; } } - debug("session_by_channel: unknown channel %d", id); + debug_f("unknown channel %d", id); session_dump(); return NULL; } @@ -1855,13 +1909,12 @@ continue; for (j = 0; s->x11_chanids[j] != -1; j++) { if (s->x11_chanids[j] == id) { - debug("session_by_x11_channel: session %d " - "channel %d", s->self, id); + debug_f("session %d channel %d", s->self, id); return s; } } } - debug("session_by_x11_channel: unknown channel %d", id); + debug_f("unknown channel %d", id); session_dump(); return NULL; } @@ -1870,13 +1923,13 @@ session_by_pid(pid_t pid) { int i; - debug("session_by_pid: pid %ld", (long)pid); + debug_f("pid %ld", (long)pid); for (i = 0; i < sessions_nalloc; i++) { Session *s = &sessions[i]; if (s->used && s->pid == pid) return s; } - error("session_by_pid: unknown pid %ld", (long)pid); + error_f("unknown pid %ld", (long)pid); session_dump(); return NULL; } @@ -1886,12 +1939,22 @@ { int r; - if ((r = sshpkt_get_u32(ssh, &s->col)) != 0 || - (r = sshpkt_get_u32(ssh, &s->row)) != 0 || - (r = sshpkt_get_u32(ssh, &s->xpixel)) != 0 || - (r = sshpkt_get_u32(ssh, &s->ypixel)) != 0 || - (r = sshpkt_get_end(ssh)) != 0) +{ u_int32_t col, row, x, y; + + if ((r = sshpkt_get_u32(ssh, &col)) != 0 || + (r = sshpkt_get_u32(ssh, &row)) != 0 || + (r = sshpkt_get_u32(ssh, &x)) != 0 || + (r = sshpkt_get_u32(ssh, &y)) != 0 || + (r = sshpkt_get_end(ssh)) != 0) { sshpkt_fatal(ssh, r, "%s: parse packet", __func__); + return 0; /*unreachable code*/ + } + + s->col = col; + s->row = row; + s->xpixel = x; + s->ypixel = y; +} pty_change_window_size(s->ptyfd, s->row, s->col, s->xpixel, s->ypixel); return 1; } @@ -1910,13 +1973,22 @@ return 0; } +{ u_int32_t col, row, x, y; + if ((r = sshpkt_get_cstring(ssh, &s->term, NULL)) != 0 || - (r = sshpkt_get_u32(ssh, &s->col)) != 0 || - (r = sshpkt_get_u32(ssh, &s->row)) != 0 || - (r = sshpkt_get_u32(ssh, &s->xpixel)) != 0 || - (r = sshpkt_get_u32(ssh, &s->ypixel)) != 0) + (r = sshpkt_get_u32(ssh, &col)) != 0 || + (r = sshpkt_get_u32(ssh, &row)) != 0 || + (r = sshpkt_get_u32(ssh, &x)) != 0 || + (r = sshpkt_get_u32(ssh, &y)) != 0) { sshpkt_fatal(ssh, r, "%s: parse packet", __func__); + return 0; /*unreachable code*/ + } + s->col = col; + s->row = row; + s->xpixel = x; + s->ypixel = y; +} if (strcmp(s->term, "") == 0) { free(s->term); s->term = NULL; @@ -1930,15 +2002,17 @@ s->term = NULL; s->ptyfd = -1; s->ttyfd = -1; - error("session_pty_req: session %d alloc failed", s->self); + error_f("session %d alloc failed", s->self); return 0; } - debug("session_pty_req: session %d alloc %s", s->self, s->tty); + debug_f("session %d alloc %s", s->self, s->tty); ssh_tty_parse_modes(ssh, s->ttyfd); - if ((r = sshpkt_get_end(ssh)) != 0) + if ((r = sshpkt_get_end(ssh)) != 0) { sshpkt_fatal(ssh, r, "%s: parse packet", __func__); + return 0; /*unreachable code*/ + } if (!use_privsep) pty_setowner(s->pw, s->tty); @@ -1955,12 +2029,13 @@ { struct stat st; int r, success = 0; - char *prog, *cmd, *type; + char *prog, *cmd; u_int i; if ((r = sshpkt_get_cstring(ssh, &s->subsys, NULL)) != 0 || (r = sshpkt_get_end(ssh)) != 0) sshpkt_fatal(ssh, r, "%s: parse packet", __func__); + debug2("subsystem request for %.100s by user %s", s->subsys, s->pw->pw_name); @@ -1978,10 +2053,12 @@ s->is_subsystem = SUBSYSTEM_EXT; debug("subsystem: exec() %s", cmd); } + { char *type; xasprintf(&type, "session:subsystem:%s", options.subsystem_name[i]); channel_set_xtype(ssh, s->chanid, type); free(type); + } success = do_exec(ssh, s, cmd) == 0; break; } @@ -1998,21 +2075,28 @@ session_x11_req(struct ssh *ssh, Session *s) { int r, success; - u_char single_connection = 0; if (s->auth_proto != NULL || s->auth_data != NULL) { error("session_x11_req: session %d: " "x11 forwarding already active", s->self); return 0; } + +{ u_char single_connection; + u_int32_t screen; + if ((r = sshpkt_get_u8(ssh, &single_connection)) != 0 || (r = sshpkt_get_cstring(ssh, &s->auth_proto, NULL)) != 0 || (r = sshpkt_get_cstring(ssh, &s->auth_data, NULL)) != 0 || - (r = sshpkt_get_u32(ssh, &s->screen)) != 0 || - (r = sshpkt_get_end(ssh)) != 0) + (r = sshpkt_get_u32(ssh, &screen)) != 0 || + (r = sshpkt_get_end(ssh)) != 0) { sshpkt_fatal(ssh, r, "%s: parse packet", __func__); + return 0; /*unreachable code*/ + } s->single_connection = single_connection; + s->screen = screen; +} if (xauth_valid_string(s->auth_proto) && xauth_valid_string(s->auth_data)) @@ -2046,8 +2130,7 @@ static int session_exec_req(struct ssh *ssh, Session *s) { - u_int success; - int r; + int r, success; char *command = NULL; if ((r = sshpkt_get_cstring(ssh, &command, NULL)) != 0 || @@ -2078,14 +2161,17 @@ static int session_env_req(struct ssh *ssh, Session *s) { - char *name, *val; + char *name = NULL, *val = NULL; u_int i; int r; if ((r = sshpkt_get_cstring(ssh, &name, NULL)) != 0 || (r = sshpkt_get_cstring(ssh, &val, NULL)) != 0 || - (r = sshpkt_get_end(ssh)) != 0) + (r = sshpkt_get_end(ssh)) != 0) { + free(name); + free(val); sshpkt_fatal(ssh, r, "%s: parse packet", __func__); + } /* Don't set too many environment variables */ if (s->num_env > 128) { @@ -2113,14 +2199,14 @@ } /* - * Conversion of signals from ssh channel request names. + * Allowed signals for ssh channel "signal" request. * Subset of signals from RFC 4254 section 6.10C, with SIGINFO as * local extension. */ static int -name2sig(char *name) +allowed_signal(int code) { -#define SSH_SIG(x) if (strcmp(name, #x) == 0) return SIG ## x +#define SSH_SIG(x) if (code == SIG ## x) return 1; SSH_SIG(HUP); SSH_SIG(INT); SSH_SIG(KILL); @@ -2128,12 +2214,11 @@ SSH_SIG(TERM); SSH_SIG(USR1); SSH_SIG(USR2); -#undef SSH_SIG #ifdef SIGINFO - if (strcmp(name, "INFO@openssh.com") == 0) - return SIGINFO; + SSH_SIG(INFO); #endif - return -1; +#undef SSH_SIG + return 0; } static int @@ -2147,7 +2232,12 @@ error_fr(r, "parse"); goto out; } - if ((sig = name2sig(signame)) == -1) { + sig = ssh_signame2code(signame); + if (sig == -1) { + error_f("unknown signal \"%s\"", signame); + goto out; + } + if (!allowed_signal(sig)) { error_f("unsupported signal \"%s\"", signame); goto out; } @@ -2210,7 +2300,7 @@ Session *s; if ((s = session_by_channel(c->self)) == NULL) { - logit_f("no session %d req %.100s", c->self, rtype); + error_f("no session %d req %.100s", c->self, rtype); return 0; } debug_f("session %d req %s", s->self, rtype); @@ -2247,7 +2337,7 @@ return success; } -void +static void session_set_fds(struct ssh *ssh, Session *s, int fdin, int fdout, int fderr, int ignore_fderr, int is_tty) { @@ -2300,7 +2390,7 @@ s->ttyfd = -1; } -void +static void session_pty_cleanup(Session *s) { PRIVSEP(session_pty_cleanup2(s)); @@ -2349,6 +2439,8 @@ Session *s; u_int i; + UNUSED(force); + UNUSED(arg); debug3_f("channel %d", id); channel_cancel_cleanup(ssh, id); if ((s = session_by_x11_channel(id)) == NULL) @@ -2483,6 +2575,7 @@ Session *s = session_by_channel(id); u_int i; + UNUSED(arg); if (s == NULL) { debug_f("no session for id %d", id); return; @@ -2491,9 +2584,8 @@ if (s->pid != 0) { debug_f("channel %d: has child, ttyfd %d", id, s->ttyfd); /* - * delay detach of session (unless this is a forced close), - * but release pty, since the fd's to the child are already - * closed + * delay detach of session, but release pty, since + * the fd's to the child are already closed */ if (s->ttyfd != -1) session_pty_cleanup(s); @@ -2558,7 +2650,7 @@ return buf; } -void +static void session_proctitle(Session *s) { if (s->pw == NULL) @@ -2567,7 +2659,7 @@ setproctitle("%s@%s", s->pw->pw_name, session_tty_list()); } -int +static int session_setup_x11fwd(struct ssh *ssh, Session *s) { struct stat st; diff -ruN openssh-9.4p1/session.h openssh-9.4p1+x509-14.2.1/session.h --- openssh-9.4p1/session.h 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/session.h 2023-08-20 10:07:00.000000000 +0300 @@ -1,4 +1,4 @@ -/* $OpenBSD: session.h,v 1.37 2023/01/06 02:39:59 djm Exp $ */ +/* $OpenBSD: session.h,v 1.36 2018/10/02 12:40:07 djm Exp $ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. diff -ruN openssh-9.4p1/sftp.0 openssh-9.4p1+x509-14.2.1/sftp.0 --- openssh-9.4p1/sftp.0 2023-08-10 04:11:19.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/sftp.0 2023-08-20 10:07:00.000000000 +0300 @@ -1,7 +1,7 @@ -SFTP(1) General Commands Manual SFTP(1) +SFTP(1) BSD General Commands Manual SFTP(1) NAME - sftp M-bM-^@M-^S OpenSSH secure file transfer + sftp -- Secure file transfer program SYNOPSIS sftp [-46AaCfNpqrv] [-B buffer_size] [-b batchfile] [-c cipher] @@ -12,16 +12,16 @@ DESCRIPTION sftp is a file transfer program, similar to ftp(1), which performs all - operations over an encrypted ssh(1) transport. It may also use many - features of ssh, such as public key authentication and compression. + operations over an encrypted ssh(1) transport. It may also use many fea- + tures of ssh, such as public key authentication and compression. The destination may be specified either as [user@]host[:path] or as a URI in the form sftp://[user@]host[:port][/path]. If the destination includes a path and it is not a directory, sftp will retrieve files automatically if a non-interactive authentication method - is used; otherwise it will do so after successful interactive - authentication. + is used; otherwise it will do so after successful interactive authentica- + tion. If no path is specified, or if the path is a directory, sftp will log in to the specified host and enter interactive command mode, changing to the @@ -38,8 +38,8 @@ -6 Forces sftp to use IPv6 addresses only. - -A Allows forwarding of ssh-agent(1) to the remote system. The - default is not to forward an authentication agent. + -A Allows forwarding of ssh-agent(1) to the remote system. The de- + fault is not to forward an authentication agent. -a Attempt to continue interrupted transfers rather than overwriting existing partial or complete copies of files. If the partial @@ -52,22 +52,22 @@ higher memory consumption. The default is 32768 bytes. -b batchfile - Batch mode reads a series of commands from an input batchfile - instead of stdin. Since it lacks user interaction, it should be - used in conjunction with non-interactive authentication to - obviate the need to enter a password at connection time (see - sshd(8) and ssh-keygen(1) for details). + Batch mode reads a series of commands from an input batchfile in- + stead of stdin. Since it lacks user interaction, it should be + used in conjunction with non-interactive authentication to obvi- + ate the need to enter a password at connection time (see sshd(8) + and ssh-keygen(1) for details). - A batchfile of M-bM-^@M-^X-M-bM-^@M-^Y may be used to indicate standard input. sftp + A batchfile of '-' may be used to indicate standard input. sftp will abort if any of the following commands fail: get, put, - reget, reput, rename, ln, rm, mkdir, chdir, ls, lchdir, copy, cp, - chmod, chown, chgrp, lpwd, df, symlink, and lmkdir. + reget, reput, rename, ln, rm, mkdir, chdir, ls, lchdir, chmod, + chown, chgrp, lpwd, df, symlink, and lmkdir. Termination on error can be suppressed on a command by command - basis by prefixing the command with a M-bM-^@M-^X-M-bM-^@M-^Y character (for example, - -rm /tmp/blah*). Echo of the command may be suppressed by - prefixing the command with a M-bM-^@M-^X@M-bM-^@M-^Y character. These two prefixes - may be combined in any order, for example -@ls /bsd. + basis by prefixing the command with a '-' character (for example, + -rm /tmp/blah*). Echo of the command may be suppressed by pre- + fixing the command with a '@' character. These two prefixes may + be combined in any order, for example -@ls /bsd. -C Enables compression (via ssh's -C flag). @@ -78,16 +78,16 @@ -D sftp_server_command Connect directly to a local sftp server (rather than via ssh(1)). A command and arguments may be specified, for example - "/path/sftp-server -el debug3". This option may be useful in - debugging the client and server. + "/path/sftp-server -el debug3". This option may be useful in de- + bugging the client and server. -F ssh_config Specifies an alternative per-user configuration file for ssh(1). This option is directly passed to ssh(1). - -f Requests that files be flushed to disk immediately after - transfer. When uploading files, this feature is only enabled if - the server implements the "fsync@openssh.com" extension. + -f Requests that files be flushed to disk immediately after trans- + fer. When uploading files, this feature is only enabled if the + server implements the "fsync@openssh.com" extension. -i identity_file Selects the file from which the identity (private key) for public @@ -113,70 +113,7 @@ ssh_config(5). This is useful for specifying options for which there is no separate sftp command-line flag. For example, to specify an alternate port use: sftp -oPort=24. For full details - of the options listed below, and their possible values, see - ssh_config(5). - - AddressFamily - BatchMode - BindAddress - BindInterface - CanonicalDomains - CanonicalizeFallbackLocal - CanonicalizeHostname - CanonicalizeMaxDots - CanonicalizePermittedCNAMEs - CASignatureAlgorithms - CertificateFile - CheckHostIP - Ciphers - Compression - ConnectionAttempts - ConnectTimeout - ControlMaster - ControlPath - ControlPersist - GlobalKnownHostsFile - GSSAPIAuthentication - GSSAPIDelegateCredentials - HashKnownHosts - Host - HostbasedAcceptedAlgorithms - HostbasedAuthentication - HostKeyAlgorithms - HostKeyAlias - Hostname - IdentitiesOnly - IdentityAgent - IdentityFile - IPQoS - KbdInteractiveAuthentication - KbdInteractiveDevices - KexAlgorithms - KnownHostsCommand - LogLevel - MACs - NoHostAuthenticationForLocalhost - NumberOfPasswordPrompts - PasswordAuthentication - PKCS11Provider - Port - PreferredAuthentications - ProxyCommand - ProxyJump - PubkeyAcceptedAlgorithms - PubkeyAuthentication - RekeyLimit - RequiredRSASize - SendEnv - ServerAliveInterval - ServerAliveCountMax - SetEnv - StrictHostKeyChecking - TCPKeepAlive - UpdateHostKeys - User - UserKnownHostsFile - VerifyHostKeyDNS + of the options and their possible values, see ssh_config(5). -P port Specifies the port to connect to on the remote host. @@ -192,9 +129,9 @@ Increasing this may slightly improve file transfer speed but will increase memory usage. The default is 64 outstanding requests. - -r Recursively copy entire directories when uploading and - downloading. Note that sftp does not follow symbolic links - encountered in the tree traversal. + -r Recursively copy entire directories when uploading and download- + ing. Note that sftp does not follow symbolic links encountered + in the tree traversal. -S program Name of the program to use for the encrypted connection. The @@ -208,26 +145,28 @@ -v Raise logging level. This option is also passed to ssh. -X sftp_option - Specify an option that controls aspects of SFTP protocol - behaviour. The valid options are: + Specify an option that controls aspects of SFTP protocol behav- + iour. The valid options are: nrequests=value Controls how many concurrent SFTP read or write requests may be in progress at any point in time during a download - or upload. By default 64 requests may be active - concurrently. + or upload. By default 64 requests may be active concur- + rently. Maximum accepted value is 1024. Option replaces + -R. buffer=value Controls the maximum buffer size for a single SFTP read/write operation used during download or upload. By - default a 32KB buffer is used. + default a 32KB buffer is used. Maximum accepted value is + 256K. Option replaces -B. INTERACTIVE COMMANDS Once in interactive mode, sftp understands a set of commands similar to those of ftp(1). Commands are case insensitive. Pathnames that contain spaces must be enclosed in quotes. Any special characters contained - within pathnames that are recognized by glob(3) must be escaped with - backslashes (M-bM-^@M-^X\M-bM-^@M-^Y). + within pathnames that are recognized by glob(7) must be escaped with + backslashes ('\'). bye Quit sftp. @@ -236,9 +175,8 @@ change directory to the one the session started in. chgrp [-h] grp path - Change group of file path to grp. path may contain glob(7) - characters and may match multiple files. grp must be a numeric - GID. + Change group of file path to grp. path may contain glob(7) char- + acters and may match multiple files. grp must be a numeric GID. If the -h flag is specified, then symlinks will not be followed. Note that this is only supported by servers that implement the @@ -253,30 +191,20 @@ "lsetstat@openssh.com" extension. chown [-h] own path - Change owner of file path to own. path may contain glob(7) - characters and may match multiple files. own must be a numeric - UID. + Change owner of file path to own. path may contain glob(7) char- + acters and may match multiple files. own must be a numeric UID. If the -h flag is specified, then symlinks will not be followed. Note that this is only supported by servers that implement the "lsetstat@openssh.com" extension. - copy oldpath newpath - Copy remote file from oldpath to newpath. - - Note that this is only supported by servers that implement the - "copy-data" extension. - - cp oldpath newpath - Alias to copy command. - df [-hi] [path] Display usage information for the filesystem holding the current directory (or path if specified). If the -h flag is specified, the capacity information will be displayed using "human-readable" suffixes. The -i flag requests display of inode information in addition to capacity information. This command is only supported - on servers that implement the M-bM-^@M-^\statvfs@openssh.comM-bM-^@M-^] extension. + on servers that implement the "statvfs@openssh.com" extension. exit Quit sftp. @@ -285,8 +213,8 @@ the local path name is not specified, it is given the same name it has on the remote machine. remote-path may contain glob(7) characters and may match multiple files. If it does and - local-path is specified, then local-path must specify a - directory. + local-path is specified, then local-path must specify a direc- + tory. If the -a flag is specified, then attempt to resume partial transfers of existing files. Note that resumption assumes that @@ -297,12 +225,12 @@ If the -f flag is specified, then fsync(2) will be called after the file transfer has completed to flush the file to disk. - If the -p flag is specified, then full file permissions and - access times are copied too. + If the -p or redundant alias -P flag is specified, then full file + permissions and access times are copied too. - If the -R flag is specified then directories will be copied - recursively. Note that sftp does not follow symbolic links when - performing recursive transfers. + If the -R or deprecated alias -r flag is specified then directo- + ries will be copied recursively. Note that sftp does not follow + symbolic links when performing recursive transfers. help Display help text. @@ -311,18 +239,18 @@ change directory to the local user's home directory. lls [ls-options [path]] - Display local directory listing of either path or current - directory if path is not specified. ls-options may contain any - flags supported by the local system's ls(1) command. path may - contain glob(7) characters and may match multiple files. + Display local directory listing of either path or current direc- + tory if path is not specified. ls-options may contain any flags + supported by the local system's ls(1) command. path may contain + glob(7) characters and may match multiple files. lmkdir path Create local directory specified by path. ln [-s] oldpath newpath - Create a link from oldpath to newpath. If the -s flag is - specified the created link is a symbolic link, otherwise it is a - hard link. + Create a link from oldpath to newpath. If the -s flag is speci- + fied the created link is a symbolic link, otherwise it is a hard + link. lpwd Print local working directory. @@ -336,10 +264,10 @@ -1 Produce single columnar output. - -a List files beginning with a dot (M-bM-^@M-^X.M-bM-^@M-^Y). + -a List files beginning with a dot ('.'). - -f Do not sort the listing. The default sort order is - lexicographical. + -f Do not sort the listing. The default sort order is lexi- + cographical. -h When used with a long format option, use unit suffixes: Byte, Kilobyte, Megabyte, Gigabyte, Terabyte, Petabyte, @@ -347,8 +275,8 @@ four or fewer using powers of 2 for sizes (K=1024, M=1048576, etc.). - -l Display additional details including permissions and - ownership information. + -l Display additional details including permissions and own- + ership information. -n Produce a long listing with user and group information presented numerically. @@ -369,12 +297,11 @@ Toggle display of progress meter. put [-afpR] local-path [remote-path] - Upload local-path and store it on the remote machine. If the - remote path name is not specified, it is given the same name it - has on the local machine. local-path may contain glob(7) - characters and may match multiple files. If it does and - remote-path is specified, then remote-path must specify a - directory. + Upload local-path and store it on the remote machine. If the re- + mote path name is not specified, it is given the same name it has + on the local machine. local-path may contain glob(7) characters + and may match multiple files. If it does and remote-path is + specified, then remote-path must specify a directory. If the -a flag is specified, then attempt to resume partial transfers of existing files. Note that resumption assumes that @@ -387,12 +314,12 @@ Note that this is only supported by servers that implement the "fsync@openssh.com" extension. - If the -p flag is specified, then full file permissions and - access times are copied too. + If the -p or redundant alias -P flag is specified, then full file + permissions and access times are copied too. - If the -R flag is specified then directories will be copied - recursively. Note that sftp does not follow symbolic links when - performing recursive transfers. + If the -R or deprecated alias -r flag is specified then directo- + ries will be copied recursively. Note that sftp does not follow + symbolic links when performing recursive transfers. pwd Display remote working directory. @@ -432,7 +359,8 @@ ftp(1), ls(1), scp(1), ssh(1), ssh-add(1), ssh-keygen(1), ssh_config(5), glob(7), sftp-server(8), sshd(8) - T. Ylonen and S. Lehtinen, SSH File Transfer Protocol, draft-ietf-secsh- - filexfer-00.txt, January 2001, work in progress material. +CONFORMING TO + 1. T. Ylonen and S. Lehtinen, SSH File Transfer Protocol, draft-ietf- + secsh-filexfer-02.txt, January 2001, work in progress material. -OpenBSD 7.3 December 16, 2022 OpenBSD 7.3 +BSD 10 January 2023 BSD diff -ruN openssh-9.4p1/sftp.1 openssh-9.4p1+x509-14.2.1/sftp.1 --- openssh-9.4p1/sftp.1 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/sftp.1 2023-08-20 10:07:00.000000000 +0300 @@ -1,6 +1,7 @@ .\" $OpenBSD: sftp.1,v 1.143 2022/12/16 03:40:03 djm Exp $ .\" .\" Copyright (c) 2001 Damien Miller. All rights reserved. +.\" Copyright (c) 2011-2023 Roumen Petrov. All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions @@ -22,12 +23,20 @@ .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.Dd $Mdocdate: December 16 2022 $ +.\" Implement .Dd with the Mdocdate RCS keyword +.rn Dd xD +.de Dd +.ie \\$1$Mdocdate: \{\ +. xD \\$3 \\$2 \\$4 +.\} +.el .xD \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 +.. +.Dd $Mdocdate: January 10 2023 $ .Dt SFTP 1 .Os .Sh NAME .Nm sftp -.Nd OpenSSH secure file transfer +.Nd Secure file transfer program .Sh SYNOPSIS .Nm sftp .Op Fl 46AaCfNpqrv @@ -145,7 +154,7 @@ commands fail: .Ic get , put , reget , reput , rename , ln , .Ic rm , mkdir , chdir , ls , -.Ic lchdir , copy , cp , chmod , chown , +.Ic lchdir , chmod , chown , .Ic chgrp , lpwd , df , symlink , and .Ic lmkdir . @@ -220,72 +229,8 @@ command-line flag. For example, to specify an alternate port use: .Ic sftp -oPort=24 . -For full details of the options listed below, and their possible values, see +For full details of the options and their possible values, see .Xr ssh_config 5 . -.Pp -.Bl -tag -width Ds -offset indent -compact -.It AddressFamily -.It BatchMode -.It BindAddress -.It BindInterface -.It CanonicalDomains -.It CanonicalizeFallbackLocal -.It CanonicalizeHostname -.It CanonicalizeMaxDots -.It CanonicalizePermittedCNAMEs -.It CASignatureAlgorithms -.It CertificateFile -.It CheckHostIP -.It Ciphers -.It Compression -.It ConnectionAttempts -.It ConnectTimeout -.It ControlMaster -.It ControlPath -.It ControlPersist -.It GlobalKnownHostsFile -.It GSSAPIAuthentication -.It GSSAPIDelegateCredentials -.It HashKnownHosts -.It Host -.It HostbasedAcceptedAlgorithms -.It HostbasedAuthentication -.It HostKeyAlgorithms -.It HostKeyAlias -.It Hostname -.It IdentitiesOnly -.It IdentityAgent -.It IdentityFile -.It IPQoS -.It KbdInteractiveAuthentication -.It KbdInteractiveDevices -.It KexAlgorithms -.It KnownHostsCommand -.It LogLevel -.It MACs -.It NoHostAuthenticationForLocalhost -.It NumberOfPasswordPrompts -.It PasswordAuthentication -.It PKCS11Provider -.It Port -.It PreferredAuthentications -.It ProxyCommand -.It ProxyJump -.It PubkeyAcceptedAlgorithms -.It PubkeyAuthentication -.It RekeyLimit -.It RequiredRSASize -.It SendEnv -.It ServerAliveInterval -.It ServerAliveCountMax -.It SetEnv -.It StrictHostKeyChecking -.It TCPKeepAlive -.It UpdateHostKeys -.It User -.It UserKnownHostsFile -.It VerifyHostKeyDNS -.El .It Fl P Ar port Specifies the port to connect to on the remote host. .It Fl p @@ -329,10 +274,16 @@ Controls how many concurrent SFTP read or write requests may be in progress at any point in time during a download or upload. By default 64 requests may be active concurrently. +Maximum accepted value is 1024. +Option replaces +.Fl R . .It Cm buffer Ns = Ns Ar value Controls the maximum buffer size for a single SFTP read/write operation used during download or upload. By default a 32KB buffer is used. +Maximum accepted value is 256K. +Option replaces +.Fl B . .El .El .Sh INTERACTIVE COMMANDS @@ -343,7 +294,7 @@ Commands are case insensitive. Pathnames that contain spaces must be enclosed in quotes. Any special characters contained within pathnames that are recognized by -.Xr glob 3 +.Xr glob 7 must be escaped with backslashes .Pq Sq \e . .Bl -tag -width Ds @@ -417,18 +368,6 @@ flag is specified, then symlinks will not be followed. Note that this is only supported by servers that implement the "lsetstat@openssh.com" extension. -.It Ic copy Ar oldpath Ar newpath -Copy remote file from -.Ar oldpath -to -.Ar newpath . -.Pp -Note that this is only supported by servers that implement the "copy-data" -extension. -.It Ic cp Ar oldpath Ar newpath -Alias to -.Ic copy -command. .It Xo Ic df .Op Fl hi .Op Ar path @@ -488,17 +427,15 @@ .Pp If the .Fl p -.\" undocumented redundant alias -.\" or -.\" .Fl P +or redundant alias +.Fl P flag is specified, then full file permissions and access times are copied too. .Pp If the .Fl R -.\" undocumented redundant alias -.\" or -.\" .Fl r +or deprecated alias +.Fl r flag is specified then directories will be copied recursively. Note that .Nm @@ -634,17 +571,15 @@ .Pp If the .Fl p -.\" undocumented redundant alias -.\" or -.\" .Fl P +or redundant alias +.Fl P flag is specified, then full file permissions and access times are copied too. .Pp If the .Fl R -.\" undocumented redundant alias -.\" or -.\" .Fl r +or deprecated alias +.Fl r flag is specified then directories will be copied recursively. Note that .Nm @@ -718,11 +653,15 @@ .Xr glob 7 , .Xr sftp-server 8 , .Xr sshd 8 +.Sh CONFORMING TO +.Bl -enum +.It .Rs .%A T. Ylonen .%A S. Lehtinen .%T "SSH File Transfer Protocol" -.%N draft-ietf-secsh-filexfer-00.txt +.%N draft-ietf-secsh-filexfer-02.txt .%D January 2001 .%O work in progress material .Re +.El diff -ruN openssh-9.4p1/sftp.c openssh-9.4p1+x509-14.2.1/sftp.c --- openssh-9.4p1/sftp.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/sftp.c 2023-08-20 10:07:01.000000000 +0300 @@ -1,6 +1,7 @@ /* $OpenBSD: sftp.c,v 1.234 2023/04/12 08:53:54 jsg Exp $ */ /* * Copyright (c) 2001-2004 Damien Miller + * Copyright (c) 2013-2021 Roumen Petrov. All rights reserved. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -17,7 +18,6 @@ #include "includes.h" -#include #include #ifdef HAVE_SYS_STAT_H # include @@ -64,12 +64,13 @@ #include "utf8.h" #include "sftp.h" -#include "ssherr.h" #include "sshbuf.h" #include "sftp-common.h" #include "sftp-client.h" #include "sftp-usergroup.h" +#define NCMP(a,b) (a == b ? 0 : (a < b ? -1 : 1)) + /* File to read commands from */ FILE* infile; @@ -138,7 +139,6 @@ I_CHGRP, I_CHMOD, I_CHOWN, - I_COPY, I_DF, I_GET, I_HELP, @@ -183,8 +183,6 @@ { "chgrp", I_CHGRP, REMOTE, NOARGS }, { "chmod", I_CHMOD, REMOTE, NOARGS }, { "chown", I_CHOWN, REMOTE, NOARGS }, - { "copy", I_COPY, REMOTE, LOCAL }, - { "cp", I_COPY, REMOTE, LOCAL }, { "df", I_DF, REMOTE, NOARGS }, { "dir", I_LS, REMOTE, NOARGS }, { "exit", I_QUIT, NOARGS, NOARGS }, @@ -222,8 +220,11 @@ { pid_t pid; + UNUSED(signo); pid = sshpid; if (pid > 1) { + /* may receive SIGCHLD signal here,i.e. sshpid = -1, + so use cached value */ kill(pid, SIGTERM); (void)waitpid(pid, NULL, 0); } @@ -248,6 +249,7 @@ const char msg[] = "\rInterrupt \n"; int olderrno = errno; + UNUSED(signo); (void)write(STDERR_FILENO, msg, sizeof(msg) - 1); interrupted = 1; errno = olderrno; @@ -256,6 +258,7 @@ static void read_interrupt(int signo) { + UNUSED(signo); interrupted = 1; } @@ -266,6 +269,7 @@ pid_t pid; const char msg[] = "\rConnection closed. \n"; + UNUSED(sig); /* Report if ssh transport process dies. */ while ((pid = waitpid(sshpid, NULL, WNOHANG)) == -1 && errno == EINTR) continue; @@ -287,8 +291,6 @@ "chgrp [-h] grp path Change group of file 'path' to 'grp'\n" "chmod [-h] mode path Change permissions of file 'path' to 'mode'\n" "chown [-h] own path Change owner of file 'path' to 'own'\n" - "copy oldpath newpath Copy remote file\n" - "cp oldpath newpath Copy remote file\n" "df [-hi] [path] Display statistics for current directory or\n" " filesystem containing 'path'\n" "exit Quit sftp\n" @@ -819,7 +821,6 @@ SFTP_DIRENT *b = *(SFTP_DIRENT **)bb; int rmul = sort_flag & LS_REVERSE_SORT ? -1 : 1; -#define NCMP(a,b) (a == b ? 0 : (a < b ? 1 : -1)) if (sort_flag & LS_NAME_SORT) return (rmul * strcmp(a->filename, b->filename)); else if (sort_flag & LS_TIME_SORT) @@ -920,33 +921,41 @@ return (0); } +static inline int +ssh_ts_cmp(const struct timespec *t1, const struct timespec *t2) +{ + if (t1->tv_sec == t2->tv_sec) + return NCMP(t1->tv_nsec, t2->tv_nsec); + else + return (t1->tv_sec < t2->tv_sec) ? -1: 1; +} + static int sglob_comp(const void *aa, const void *bb) { u_int a = *(const u_int *)aa; u_int b = *(const u_int *)bb; - const char *ap = sort_glob->gl_pathv[a]; - const char *bp = sort_glob->gl_pathv[b]; - const struct stat *as = sort_glob->gl_statv[a]; - const struct stat *bs = sort_glob->gl_statv[b]; int rmul = sort_flag & LS_REVERSE_SORT ? -1 : 1; -#define NCMP(a,b) (a == b ? 0 : (a < b ? 1 : -1)) - if (sort_flag & LS_NAME_SORT) + if (sort_flag & LS_NAME_SORT) { + const char *ap = sort_glob->gl_pathv[a]; + const char *bp = sort_glob->gl_pathv[b]; return (rmul * strcmp(ap, bp)); - else if (sort_flag & LS_TIME_SORT) { + } else if (sort_flag & LS_TIME_SORT) { + const struct stat *as = sort_glob->gl_statv[a]; + const struct stat *bs = sort_glob->gl_statv[b]; #if defined(HAVE_STRUCT_STAT_ST_MTIM) - if (timespeccmp(&as->st_mtim, &bs->st_mtim, ==)) - return 0; - return timespeccmp(&as->st_mtim, &bs->st_mtim, <) ? - rmul : -rmul; + return (rmul * ssh_ts_cmp(&as->st_mtim, &bs->st_mtim)); #elif defined(HAVE_STRUCT_STAT_ST_MTIME) return (rmul * NCMP(as->st_mtime, bs->st_mtime)); #else return rmul * 1; #endif - } else if (sort_flag & LS_SIZE_SORT) + } else if (sort_flag & LS_SIZE_SORT) { + const struct stat *as = sort_glob->gl_statv[a]; + const struct stat *bs = sort_glob->gl_statv[b]; return (rmul * NCMP(as->st_size, bs->st_size)); + } fatal("Unknown ls sort type"); } @@ -1349,12 +1358,14 @@ for (;*cp != '\0'; cp++) { if (*cp == '-') { *ignore_errors = 1; - } else if (*cp == '@') { + continue; + } + if (*cp == '@') { *disable_echo = 1; - } else { - /* all other characters terminate prefix processing */ - break; + continue; } + /* all other characters terminate prefix processing */ + break; } cp = cp + strspn(cp, WHITESPACE); @@ -1413,10 +1424,6 @@ if ((optidx = parse_link_flags(cmd, argv, argc, sflag)) == -1) return -1; goto parse_two_paths; - case I_COPY: - if ((optidx = parse_no_flags(cmd, argv, argc)) == -1) - return -1; - goto parse_two_paths; case I_RENAME: if ((optidx = parse_rename_flags(cmd, argv, argc, lflag)) == -1) return -1; @@ -1584,11 +1591,6 @@ err = process_put(conn, path1, path2, *pwd, pflag, rflag, aflag, fflag); break; - case I_COPY: - path1 = make_absolute(path1, *pwd); - path2 = make_absolute(path2, *pwd); - err = do_copy(conn, path1, path2); - break; case I_RENAME: path1 = make_absolute(path1, *pwd); path2 = make_absolute(path2, *pwd); @@ -1809,6 +1811,7 @@ static char * prompt(EditLine *el) { + UNUSED(el); return ("sftp> "); } @@ -2118,6 +2121,7 @@ const LineInfo *lf; struct complete_ctx *complete_ctx; + UNUSED(ch); lf = el_line(el); if (el_get(el, EL_CLIENTDATA, (void**)&complete_ctx) != 0) fatal_f("el_get failed"); @@ -2155,7 +2159,7 @@ ret = CC_REDISPLAY; } else if (carg >= 1) { /* Handle file parsing */ - int remote = 0; + int remote; int i = 0, cmdarg = 0; char *filematch = NULL; @@ -2278,6 +2282,7 @@ interactive = !batchmode && isatty(STDIN_FILENO); err = 0; for (;;) { + { /* manage command line interrupts */ struct sigaction sa; interrupted = 0; @@ -2288,6 +2293,7 @@ strerror(errno)); break; } + } if (el == NULL) { if (interactive) printf("sftp> "); @@ -2317,9 +2323,10 @@ } #endif /* USE_LIBEDIT */ } - - cmd[strcspn(cmd, "\n")] = '\0'; - + { + char *cp = strrchr(cmd, '\n'); + if (cp != NULL) *cp = '\0'; + } /* Handle user interrupts gracefully during commands */ interrupted = 0; ssh_signal(SIGINT, cmd_interrupt); @@ -2344,9 +2351,11 @@ } static void -connect_to_server(char *path, char **args, int *in, int *out) +connect_to_server(const char *path, char **args, int *in, int *out) { int c_in, c_out; + +{ /* get connection in/out hanldes */ #ifdef USE_PIPES int pin[2], pout[2]; @@ -2364,7 +2373,7 @@ *in = *out = inout[0]; c_in = c_out = inout[1]; #endif /* USE_PIPES */ - +} if ((sshpid = fork()) == -1) fatal("fork: %s", strerror(errno)); else if (sshpid == 0) { @@ -2374,9 +2383,11 @@ _exit(1); } close(*in); - close(*out); + if (*in != *out) + close(*out); close(c_in); - close(c_out); + if (c_in != c_out) + close(c_out); /* * The underlying ssh is in the same process group, so we must @@ -2400,7 +2411,8 @@ ssh_signal(SIGTTOU, suspchild); ssh_signal(SIGCHLD, sigchld_handler); close(c_in); - close(c_out); + if (c_in != c_out) + close(c_out); } static void @@ -2422,10 +2434,10 @@ main(int argc, char **argv) { int r, in, out, ch, err, tmp, port = -1, noisy = 0; - char *host = NULL, *user, *cp, **cpp, *file2 = NULL; + char *host = NULL, *user, *file2 = NULL; int debug_level = 0; char *file1 = NULL, *sftp_server = NULL; - char *ssh_program = _PATH_SSH_PROGRAM, *sftp_direct = NULL; + const char *ssh_program = _PATH_SSH_PROGRAM, *sftp_direct = NULL; const char *errstr; LogLevel ll = SYSLOG_LEVEL_INFO; arglist args; @@ -2436,11 +2448,17 @@ size_t num_requests = 0; long long llv, limit_kbps = 0; + ssh_malloc_init(); /* must be called before any mallocs */ /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ sanitise_stdfd(); msetlocale(); __progname = ssh_get_progname(argv[0]); +#ifdef __ANDROID__ +{ static char pathbuf[PATH_MAX]; + ssh_program = relocate_path(ssh_program, pathbuf, sizeof(pathbuf)); +} +#endif memset(&args, '\0', sizeof(args)); args.list = NULL; addargs(&args, "%s", ssh_program); @@ -2455,9 +2473,9 @@ "1246AafhNpqrvCc:D:i:l:o:s:S:b:B:F:J:P:R:X:")) != -1) { switch (ch) { /* Passed through to ssh(1) */ - case 'A': case '4': case '6': + case 'A': case 'C': addargs(&args, "-%c", ch); break; @@ -2483,25 +2501,18 @@ break; case 'v': if (debug_level < 3) { - addargs(&args, "-v"); ll = SYSLOG_LEVEL_DEBUG1 + debug_level; } debug_level++; break; - case '1': - fatal("SSH protocol v.1 is no longer supported"); - break; - case '2': - /* accept silently */ + case '1': /* obsolete */ + case '2': /* obsolete */ break; case 'a': global_aflag = 1; break; case 'B': - copy_buffer_len = strtol(optarg, &cp, 10); - if (copy_buffer_len == 0 || *cp != '\0') - fatal("Invalid buffer size \"%s\"", optarg); - break; + goto parse_copy_buffer_len; case 'b': if (batchmode) fatal("Batch file already specified."); @@ -2537,11 +2548,7 @@ global_rflag = 1; break; case 'R': - num_requests = strtol(optarg, &cp, 10); - if (num_requests == 0 || *cp != '\0') - fatal("Invalid number of requests \"%s\"", - optarg); - break; + goto parse_num_requests; case 's': sftp_server = optarg; break; @@ -2550,24 +2557,28 @@ replacearg(&args, 0, "%s", ssh_program); break; case 'X': - /* Please keep in sync with ssh.c -X */ + /* Please keep in sync with scp.c -X */ if (strncmp(optarg, "buffer=", 7) == 0) { - r = scan_scaled(optarg + 7, &llv); + optarg += 7; +parse_copy_buffer_len: + r = scan_scaled(optarg, &llv); if (r == 0 && (llv <= 0 || llv > 256 * 1024)) { r = -1; errno = EINVAL; } if (r == -1) { fatal("Invalid buffer size \"%s\": %s", - optarg + 7, strerror(errno)); + optarg, strerror(errno)); } copy_buffer_len = (size_t)llv; } else if (strncmp(optarg, "nrequests=", 10) == 0) { - llv = strtonum(optarg + 10, 1, 256 * 1024, + optarg += 10; +parse_num_requests: + llv = strtonum(optarg, 1, 1024/*RLIMIT_NOFILE?*/, &errstr); if (errstr != NULL) { fatal("Invalid number of requests " - "\"%s\": %s", optarg + 10, errstr); + "\"%s\": %s", optarg, errstr); } num_requests = (size_t)llv; } else { @@ -2580,6 +2591,13 @@ } } + if (debug_level > 0) { + addargs(&args, "-v"); // ssh starts from verbose level + if (debug_level > 0) addargs(&args, "-v"); + if (debug_level > 1) addargs(&args, "-v"); + if (debug_level > 2) addargs(&args, "-v"); + } + /* Do this last because we want the user to be able to override it */ addargs(&args, "-oForwardAgent no"); @@ -2589,7 +2607,7 @@ if (noisy) quiet = 0; - log_init(argv[0], ll, SYSLOG_FACILITY_USER, 1); + log_init(__progname, ll, SYSLOG_FACILITY_USER, 1); if (sftp_direct == NULL) { if (optind == argc || argc > (optind + 2)) @@ -2643,6 +2661,7 @@ connect_to_server(ssh_program, args.list, &in, &out); } else { + char **cpp; if ((r = argv_split(sftp_direct, &tmp, &cpp, 1)) != 0) fatal_r(r, "Parse -D arguments"); if (cpp[0] == 0) @@ -2667,18 +2686,22 @@ #if !defined(USE_PIPES) shutdown(in, SHUT_RDWR); - shutdown(out, SHUT_RDWR); + if (in != out) + shutdown(out, SHUT_RDWR); #endif close(in); - close(out); + if (in != out) + close(out); if (batchmode) fclose(infile); - while (waitpid(sshpid, NULL, 0) == -1 && sshpid > 1) + if (sshpid > 1) while (waitpid(sshpid, NULL, 0) == -1) { + if (errno == ECHILD) break; if (errno != EINTR) fatal("Couldn't wait for ssh process: %s", strerror(errno)); + } exit(err == 0 ? 0 : 1); } diff -ruN openssh-9.4p1/sftp-client.c openssh-9.4p1+x509-14.2.1/sftp-client.c --- openssh-9.4p1/sftp-client.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/sftp-client.c 2023-08-20 10:07:01.000000000 +0300 @@ -1,6 +1,8 @@ /* $OpenBSD: sftp-client.c,v 1.171 2023/04/30 22:54:22 djm Exp $ */ /* * Copyright (c) 2001-2004 Damien Miller + * Copyright (c) 2018-2022 Roumen Petrov. All rights reserved. + * Copyright (c) 2021 Mike Frysinger. All rights reserved. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -38,7 +40,7 @@ #include #include #ifdef HAVE_POLL_H -#include +# include #else # ifdef HAVE_SYS_POLL_H # include @@ -53,7 +55,6 @@ #include #include "xmalloc.h" -#include "ssherr.h" #include "sshbuf.h" #include "log.h" #include "atomicio.h" @@ -64,16 +65,47 @@ #include "sftp.h" #include "sftp-common.h" #include "sftp-client.h" +#include "ssherr.h" extern volatile sig_atomic_t interrupted; extern int showprogress; +/* Used for limits response on the wire from the server */ +struct sftp_limits { + u_int64_t packet_length; + u_int64_t read_length; + u_int64_t write_length; + u_int64_t open_handles; +}; + /* Default size of buffer for up/download (fix sftp.1 scp.1 if changed) */ #define DEFAULT_COPY_BUFLEN 32768 /* Default number of concurrent xfer requests (fix sftp.1 scp.1 if changed) */ #define DEFAULT_NUM_REQUESTS 64 +#ifdef __ANDROID__ +/* Inconsistency in android headers: writev return integer in "platform" + * headers and ssize_t in "unified" header. + * Quote from :" + * Traditionally, bionic's ssize_t was "long int". This caused GCC to emit warnings when you + * pass a ssize_t to a printf-style function. The correct type is __kernel_ssize_t, which is + * "int", which isn't an ABI change for C code (because they're the same size) but is an ABI + * change for C++ because "int" and "long int" mangle to "i" and "l" respectively. So until + * we can fix the ABI, this change should not be propagated to the NDK. http://b/8253769. + * typedef __kernel_ssize_t ssize_t; + * " + * On top on this declares writev and int ;). + * NOTE: readv is not used. + */ +static inline ssize_t +__android__writev(int fd, const struct iovec *iov, int iovcnt) { +/*FIXME*/ + return (ssize_t)writev(fd, iov, iovcnt); +} +#define writev __android__writev +#endif + /* Minimum amount of data to read at a time */ #define MIN_READ_SIZE 512 @@ -103,7 +135,6 @@ #define SFTP_EXT_LSETSTAT 0x00000020 #define SFTP_EXT_LIMITS 0x00000040 #define SFTP_EXT_PATH_EXPAND 0x00000080 -#define SFTP_EXT_COPY_DATA 0x00000100 #define SFTP_EXT_GETUSERSGROUPS_BY_ID 0x00000200 u_int exts; u_int64_t limit_kbps; @@ -133,7 +164,9 @@ req->id = id; req->len = len; req->offset = offset; + TAILQ_INSERT_TAIL(requests, req, tq); + return req; } @@ -146,6 +179,7 @@ req != NULL && req->id != id; req = TAILQ_NEXT(req, tq)) ; + return req; } @@ -173,7 +207,7 @@ put_u32(mlen, sshbuf_len(m)); iov[0].iov_base = mlen; iov[0].iov_len = sizeof(mlen); - iov[1].iov_base = (u_char *)sshbuf_ptr(m); + iov[1].iov_base = sshbuf_mutable_ptr(m); iov[1].iov_len = sshbuf_len(m); if (atomiciov6(writev, conn->fd_out, iov, 2, sftpio, @@ -310,8 +344,7 @@ int r; va_start(args, errfmt); - if (errfmt != NULL) - vsnprintf(errmsg, sizeof(errmsg), errfmt, args); + vsnprintf(errmsg, sizeof(errmsg), errfmt, args); va_end(args); if ((msg = sshbuf_new()) == NULL) @@ -323,17 +356,16 @@ if (id != expected_id) fatal("%s: ID mismatch (%u != %u)", - errfmt == NULL ? __func__ : errmsg, id, expected_id); + errmsg, id, expected_id); if (type == SSH2_FXP_STATUS) { if ((r = sshbuf_get_u32(msg, &status)) != 0) fatal_fr(r, "parse status"); - if (errfmt != NULL) - error("%s: %s", errmsg, fx2txt(status)); + error("%s: %s", errmsg, fx2txt(status)); sshbuf_free(msg); return(NULL); } else if (type != SSH2_FXP_HANDLE) fatal("%s: Expected SSH2_FXP_HANDLE(%u) packet, got %u", - errfmt == NULL ? __func__ : errmsg, SSH2_FXP_HANDLE, type); + errmsg, SSH2_FXP_HANDLE, type); if ((r = sshbuf_get_string(msg, &handle, len)) != 0) fatal_fr(r, "parse handle"); @@ -368,9 +400,9 @@ if ((r = sshbuf_get_u32(msg, &status)) != 0) fatal_fr(r, "parse status"); if (quiet) - debug("stat remote: %s", fx2txt(status)); + debug("remote stat: %s", fx2txt(status)); else - error("stat remote: %s", fx2txt(status)); + error("remote stat: %s", fx2txt(status)); sshbuf_free(msg); return(NULL); } else if (type != SSH2_FXP_ATTRS) { @@ -448,6 +480,69 @@ return 0; } +/* Query server limits */ +static int +do_limits(struct sftp_conn *conn, struct sftp_limits *limits) +{ + u_int32_t id, msg_id; + u_char type; + struct sshbuf *msg; + int r; + + if ((conn->exts & SFTP_EXT_LIMITS) == 0) { + error("Server does not support limits@openssh.com extension"); + return -1; + } + + if ((msg = sshbuf_new()) == NULL) + fatal_f("sshbuf_new failed"); + + id = conn->msg_id++; + if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 || + (r = sshbuf_put_u32(msg, id)) != 0 || + (r = sshbuf_put_cstring(msg, "limits@openssh.com")) != 0) + fatal_fr(r, "compose"); + send_msg(conn, msg); + debug3("Sent message limits@openssh.com I:%u", (u_int)id); + + get_msg(conn, msg); + + if ((r = sshbuf_get_u8(msg, &type)) != 0 || + (r = sshbuf_get_u32(msg, &msg_id)) != 0) + fatal_fr(r, "parse"); + + debug3("Received limits reply T:%u I:%u", (u_int)type, (u_int)msg_id); + if (id != msg_id) + fatal("ID mismatch (%u != %u)", (u_int)msg_id, (u_int)id); + if (type == SSH2_FXP_STATUS) { + u_int32_t status; + if ((r = sshbuf_get_u32(msg, &status)) != 0) + fatal_fr(r, "parse status"); + error("Server refuse use of limits@openssh.com extension: %s", + fx2txt(status)); + return 0; + } + if (type != SSH2_FXP_EXTENDED_REPLY) { + debug_f("Expected SSH2_FXP_EXTENDED_REPLY(%u) packet, got %u", + SSH2_FXP_EXTENDED_REPLY, (u_int)type); + /* Disable the limits extension */ + conn->exts &= ~SFTP_EXT_LIMITS; + sshbuf_free(msg); + return 0; + } + + memset(limits, 0, sizeof(*limits)); + if ((r = sshbuf_get_u64(msg, &limits->packet_length)) != 0 || + (r = sshbuf_get_u64(msg, &limits->read_length)) != 0 || + (r = sshbuf_get_u64(msg, &limits->write_length)) != 0 || + (r = sshbuf_get_u64(msg, &limits->open_handles)) != 0) + fatal_fr(r, "parse limits"); + + sshbuf_free(msg); + + return 1; +} + struct sftp_conn * do_init(int fd_in, int fd_out, u_int transfer_buflen, u_int num_requests, u_int64_t limit_kbps) @@ -535,10 +630,6 @@ strcmp((char *)value, "1") == 0) { ret->exts |= SFTP_EXT_PATH_EXPAND; known = 1; - } else if (strcmp(name, "copy-data") == 0 && - strcmp((char *)value, "1") == 0) { - ret->exts |= SFTP_EXT_COPY_DATA; - known = 1; } else if (strcmp(name, "users-groups-by-id@openssh.com") == 0 && strcmp((char *)value, "1") == 0) { @@ -557,12 +648,12 @@ sshbuf_free(msg); - /* Query the server for its limits */ - if (ret->exts & SFTP_EXT_LIMITS) { - struct sftp_limits limits; - if (do_limits(ret, &limits) != 0) - fatal_f("limits failed"); - +{ /* Query the server for its limits */ + struct sftp_limits limits; + if ((ret->exts & SFTP_EXT_LIMITS) && + (transfer_buflen == 0 || num_requests == 0) && + do_limits(ret, &limits) == 1 + ) { /* If the caller did not specify, find a good value */ if (transfer_buflen == 0) { ret->download_buflen = MINIMUM(limits.read_length, @@ -589,6 +680,7 @@ ret->num_requests); } } +} /* Some filexfer v.0 servers don't support large packets */ if (ret->version == 0) { @@ -614,60 +706,6 @@ } int -do_limits(struct sftp_conn *conn, struct sftp_limits *limits) -{ - u_int id, msg_id; - u_char type; - struct sshbuf *msg; - int r; - - if ((conn->exts & SFTP_EXT_LIMITS) == 0) { - error("Server does not support limits@openssh.com extension"); - return -1; - } - - if ((msg = sshbuf_new()) == NULL) - fatal_f("sshbuf_new failed"); - - id = conn->msg_id++; - if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 || - (r = sshbuf_put_u32(msg, id)) != 0 || - (r = sshbuf_put_cstring(msg, "limits@openssh.com")) != 0) - fatal_fr(r, "compose"); - send_msg(conn, msg); - debug3("Sent message limits@openssh.com I:%u", id); - - get_msg(conn, msg); - - if ((r = sshbuf_get_u8(msg, &type)) != 0 || - (r = sshbuf_get_u32(msg, &msg_id)) != 0) - fatal_fr(r, "parse"); - - debug3("Received limits reply T:%u I:%u", type, msg_id); - if (id != msg_id) - fatal("ID mismatch (%u != %u)", msg_id, id); - if (type != SSH2_FXP_EXTENDED_REPLY) { - debug_f("expected SSH2_FXP_EXTENDED_REPLY(%u) packet, got %u", - SSH2_FXP_EXTENDED_REPLY, type); - /* Disable the limits extension */ - conn->exts &= ~SFTP_EXT_LIMITS; - sshbuf_free(msg); - return 0; - } - - memset(limits, 0, sizeof(*limits)); - if ((r = sshbuf_get_u64(msg, &limits->packet_length)) != 0 || - (r = sshbuf_get_u64(msg, &limits->read_length)) != 0 || - (r = sshbuf_get_u64(msg, &limits->write_length)) != 0 || - (r = sshbuf_get_u64(msg, &limits->open_handles)) != 0) - fatal_fr(r, "parse limits"); - - sshbuf_free(msg); - - return 0; -} - -int do_close(struct sftp_conn *conn, const u_char *handle, u_int handle_len) { u_int id, status; @@ -687,7 +725,7 @@ status = get_status(conn, id); if (status != SSH2_FX_OK) - error("close remote: %s", fx2txt(status)); + error("remote close: %s", fx2txt(status)); sshbuf_free(msg); @@ -869,7 +907,7 @@ send_string_request(conn, id, SSH2_FXP_REMOVE, path, strlen(path)); status = get_status(conn, id); if (status != SSH2_FX_OK) - error("remote delete %s: %s", path, fx2txt(status)); + error("remote delete \"%s\": %s", path, fx2txt(status)); return status == SSH2_FX_OK ? 0 : -1; } @@ -1011,8 +1049,6 @@ int r; const char *what = "SSH2_FXP_REALPATH"; - if (expand) - what = "expand-path@openssh.com"; if ((msg = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); @@ -1020,10 +1056,11 @@ if (expand) { debug2("Sending SSH2_FXP_EXTENDED(expand-path@openssh.com) " "\"%s\"", path); + what = "expand-path@openssh.com"; if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 || (r = sshbuf_put_u32(msg, id)) != 0 || (r = sshbuf_put_cstring(msg, - "expand-path@openssh.com")) != 0 || + "expand-path@openssh.com")) != 0 || (r = sshbuf_put_cstring(msg, path)) != 0) fatal_fr(r, "compose %s", what); send_msg(conn, msg); @@ -1042,13 +1079,19 @@ if (type == SSH2_FXP_STATUS) { u_int status; - char *errmsg; + char *errmsg = NULL; - if ((r = sshbuf_get_u32(msg, &status)) != 0 || - (r = sshbuf_get_cstring(msg, &errmsg, NULL)) != 0) + if ((r = sshbuf_get_u32(msg, &status)) != 0) fatal_fr(r, "parse status"); + if ((conn->version >= 3) && + (r = sshbuf_get_cstring(msg, &errmsg, NULL)) != 0) + fatal_fr(r, "parse message"); + if (errmsg != NULL && *errmsg == '\0') { + free(errmsg); + errmsg = NULL; + } error("%s %s: %s", expand ? "expand" : "realpath", - path, *errmsg == '\0' ? fx2txt(status) : errmsg); + path, (errmsg != NULL ? errmsg : fx2txt(status))); free(errmsg); sshbuf_free(msg); return NULL; @@ -1098,121 +1141,6 @@ } int -do_copy(struct sftp_conn *conn, const char *oldpath, const char *newpath) -{ - Attrib junk, *a; - struct sshbuf *msg; - u_char *old_handle, *new_handle; - u_int mode, status, id; - size_t old_handle_len, new_handle_len; - int r; - - /* Return if the extension is not supported */ - if ((conn->exts & SFTP_EXT_COPY_DATA) == 0) { - error("Server does not support copy-data extension"); - return -1; - } - - /* Make sure the file exists, and we can copy its perms */ - if ((a = do_stat(conn, oldpath, 0)) == NULL) - return -1; - - /* Do not preserve set[ug]id here, as we do not preserve ownership */ - if (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) { - mode = a->perm & 0777; - - if (!S_ISREG(a->perm)) { - error("Cannot copy non-regular file: %s", oldpath); - return -1; - } - } else { - /* NB: The user's umask will apply to this */ - mode = 0666; - } - - /* Set up the new perms for the new file */ - attrib_clear(a); - a->perm = mode; - a->flags |= SSH2_FILEXFER_ATTR_PERMISSIONS; - - if ((msg = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new failed", __func__); - - attrib_clear(&junk); /* Send empty attributes */ - - /* Open the old file for reading */ - id = conn->msg_id++; - if ((r = sshbuf_put_u8(msg, SSH2_FXP_OPEN)) != 0 || - (r = sshbuf_put_u32(msg, id)) != 0 || - (r = sshbuf_put_cstring(msg, oldpath)) != 0 || - (r = sshbuf_put_u32(msg, SSH2_FXF_READ)) != 0 || - (r = encode_attrib(msg, &junk)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); - send_msg(conn, msg); - debug3("Sent message SSH2_FXP_OPEN I:%u P:%s", id, oldpath); - - sshbuf_reset(msg); - - old_handle = get_handle(conn, id, &old_handle_len, - "remote open(\"%s\")", oldpath); - if (old_handle == NULL) { - sshbuf_free(msg); - return -1; - } - - /* Open the new file for writing */ - id = conn->msg_id++; - if ((r = sshbuf_put_u8(msg, SSH2_FXP_OPEN)) != 0 || - (r = sshbuf_put_u32(msg, id)) != 0 || - (r = sshbuf_put_cstring(msg, newpath)) != 0 || - (r = sshbuf_put_u32(msg, SSH2_FXF_WRITE|SSH2_FXF_CREAT| - SSH2_FXF_TRUNC)) != 0 || - (r = encode_attrib(msg, a)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); - send_msg(conn, msg); - debug3("Sent message SSH2_FXP_OPEN I:%u P:%s", id, newpath); - - sshbuf_reset(msg); - - new_handle = get_handle(conn, id, &new_handle_len, - "remote open(\"%s\")", newpath); - if (new_handle == NULL) { - sshbuf_free(msg); - free(old_handle); - return -1; - } - - /* Copy the file data */ - id = conn->msg_id++; - if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 || - (r = sshbuf_put_u32(msg, id)) != 0 || - (r = sshbuf_put_cstring(msg, "copy-data")) != 0 || - (r = sshbuf_put_string(msg, old_handle, old_handle_len)) != 0 || - (r = sshbuf_put_u64(msg, 0)) != 0 || - (r = sshbuf_put_u64(msg, 0)) != 0 || - (r = sshbuf_put_string(msg, new_handle, new_handle_len)) != 0 || - (r = sshbuf_put_u64(msg, 0)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); - send_msg(conn, msg); - debug3("Sent message copy-data \"%s\" 0 0 -> \"%s\" 0", - oldpath, newpath); - - status = get_status(conn, id); - if (status != SSH2_FX_OK) - error("Couldn't copy file \"%s\" to \"%s\": %s", oldpath, - newpath, fx2txt(status)); - - /* Clean up everything */ - sshbuf_free(msg); - do_close(conn, old_handle, old_handle_len); - do_close(conn, new_handle, new_handle_len); - free(old_handle); - free(new_handle); - - return status == SSH2_FX_OK ? 0 : -1; -} - -int do_rename(struct sftp_conn *conn, const char *oldpath, const char *newpath, int force_legacy) { @@ -1325,7 +1253,7 @@ status = get_status(conn, id); if (status != SSH2_FX_OK) - error("remote symlink file \"%s\" to \"%s\": %s", oldpath, + error("remote symlink \"%s\" to \"%s\": %s", oldpath, newpath, fx2txt(status)); return status == SSH2_FX_OK ? 0 : -1; @@ -1569,9 +1497,11 @@ sshbuf_free(msg); debug3("Sent %s message SSH2_FXP_OPEN I:%u P:%s M:0x%04x", tag, id, path, openmode); + if ((handle = get_handle(conn, id, &handle_len, "%s open \"%s\"", tag, path)) == NULL) return -1; + /* success */ *handlep = handle; *handle_lenp = handle_len; @@ -1625,7 +1555,7 @@ if ((a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) && (!S_ISREG(a->perm))) { - error("download %s: not a regular file", remote_path); + error("download \"%s\": not a regular file", remote_path); return(-1); } @@ -1644,12 +1574,12 @@ local_fd = open(local_path, O_WRONLY | O_CREAT | ((resume_flag || inplace_flag) ? 0 : O_TRUNC), mode | S_IWUSR); if (local_fd == -1) { - error("open local \"%s\": %s", local_path, strerror(errno)); + error("local open \"%s\": %s", local_path, strerror(errno)); goto fail; } if (resume_flag) { if (fstat(local_fd, &st) == -1) { - error("stat local \"%s\": %s", + error("local stat \"%s\": %s", local_path, strerror(errno)); goto fail; } @@ -1754,15 +1684,19 @@ * Track both the highest offset acknowledged * and the highest *contiguous* offset * acknowledged. - * We'll need the latter for ftruncate()ing - * interrupted transfers. + * Letter is needed to truncate interrupted + * transfers. */ if (maxack < req->offset + len) maxack = req->offset + len; - if (!reordered && req->offset <= highwater) - highwater = maxack; - else if (!reordered && req->offset > highwater) - reordered = 1; + if (!reordered) { + if (req->offset <= highwater) + highwater = maxack; + else { + debug3_f("server reordered ACKs"); + reordered = 1; + } + } } progress_counter += len; free(data); @@ -1814,7 +1748,7 @@ fatal("Transfer complete, but requests still in queue"); if (!read_error && !write_error && !interrupted) { - /* we got everything */ + /* if got everything */ highwater = maxack; } @@ -1834,11 +1768,11 @@ strerror(errno)); } if (read_error) { - error("read remote \"%s\" : %s", remote_path, fx2txt(status)); + error("remote read \"%s\" : %s", remote_path, fx2txt(status)); status = -1; do_close(conn, handle, handle_len); } else if (write_error) { - error("write local \"%s\": %s", local_path, + error("local write \"%s\": %s", local_path, strerror(write_errno)); status = SSH2_FX_FAILURE; do_close(conn, handle, handle_len); @@ -1900,11 +1834,11 @@ if (dirattrib == NULL && (dirattrib = do_stat(conn, src, 1)) == NULL) { - error("stat remote \"%s\" directory failed", src); + error("remote stat \"%s\" failed", src); return -1; } if (!S_ISDIR(dirattrib->perm)) { - error("\"%s\" is not a directory", src); + error("remote \"%s\": not a directory", src); return -1; } if (print_flag && print_flag != SFTP_PROGRESS_ONLY) @@ -2022,7 +1956,7 @@ u_char type, *handle, *data; struct sshbuf *msg; struct stat sb; - Attrib a, t, *c = NULL; + Attrib a, *c = NULL; u_int32_t startid, ackid; u_int64_t highwater = 0, maxack = 0; struct request *ack = NULL; @@ -2035,16 +1969,16 @@ TAILQ_INIT(&acks); if ((local_fd = open(local_path, O_RDONLY)) == -1) { - error("open local \"%s\": %s", local_path, strerror(errno)); + error("local open \"%s\": %s", local_path, strerror(errno)); return(-1); } if (fstat(local_fd, &sb) == -1) { - error("fstat local \"%s\": %s", local_path, strerror(errno)); + error("local fstat \"%s\": %s", local_path, strerror(errno)); close(local_fd); return(-1); } if (!S_ISREG(sb.st_mode)) { - error("local \"%s\" is not a regular file", local_path); + error("local \"%s\": not a regular file", local_path); close(local_fd); return(-1); } @@ -2103,7 +2037,7 @@ if ((msg = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); for (;;) { - int len; + ssize_t len; /* * Can't use atomicio here because it returns 0 on EOF, @@ -2119,7 +2053,7 @@ (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK)); if (len == -1) { - fatal("read local \"%s\": %s", + fatal("local read \"%s\": %s", local_path, strerror(errno)); } else if (len != 0) { ack = request_enqueue(&acks, ++id, len, offset); @@ -2132,7 +2066,7 @@ (r = sshbuf_put_string(msg, data, len)) != 0) fatal_fr(r, "compose"); send_msg(conn, msg); - debug3("Sent message SSH2_FXP_WRITE I:%u O:%llu S:%u", + debug3("Sent message SSH2_FXP_WRITE I:%u O:%llu S:%zi", id, (unsigned long long)offset, len); } else if (TAILQ_FIRST(&acks) == NULL) break; @@ -2161,24 +2095,26 @@ /* Find the request in our queue */ if ((ack = request_find(&acks, rid)) == NULL) fatal("Can't find request for ID %u", rid); + TAILQ_REMOVE(&acks, ack, tq); - debug3("In write loop, ack for %u %zu bytes at %lld", + debug3("In write loop, ack for %u %zi bytes at %llu", ack->id, ack->len, (unsigned long long)ack->offset); ++ackid; progress_counter += ack->len; /* * Track both the highest offset acknowledged and the * highest *contiguous* offset acknowledged. - * We'll need the latter for ftruncate()ing - * interrupted transfers. + * Letter is needed to truncate interrupted transfers. */ if (maxack < ack->offset + ack->len) maxack = ack->offset + ack->len; - if (!reordered && ack->offset <= highwater) - highwater = maxack; - else if (!reordered && ack->offset > highwater) { - debug3_f("server reordered ACKs"); - reordered = 1; + if (!reordered) { + if (ack->offset <= highwater) + highwater = maxack; + else { + debug3_f("server reordered ACKs"); + reordered = 1; + } } free(ack); } @@ -2193,15 +2129,16 @@ free(data); if (status == SSH2_FX_OK && !interrupted) { - /* we got everything */ + /* if got everything */ highwater = maxack; } if (status != SSH2_FX_OK) { - error("write remote \"%s\": %s", remote_path, fx2txt(status)); + error("remote write \"%s\": %s", remote_path, fx2txt(status)); status = SSH2_FX_FAILURE; } if (inplace_flag || (resume && (status != SSH2_FX_OK || interrupted))) { + Attrib t; debug("truncating at %llu", (unsigned long long)highwater); attrib_clear(&t); t.flags = SSH2_FILEXFER_ATTR_SIZE; @@ -2210,7 +2147,7 @@ } if (close(local_fd) == -1) { - error("close local \"%s\": %s", local_path, strerror(errno)); + error("local close \"%s\": %s", local_path, strerror(errno)); status = SSH2_FX_FAILURE; } @@ -2240,7 +2177,6 @@ char *filename, *new_src = NULL, *new_dst = NULL; struct stat sb; Attrib a, *dirattrib; - u_int32_t saved_perm; debug2_f("upload local dir \"%s\" to remote \"%s\"", src, dst); @@ -2250,11 +2186,11 @@ } if (stat(src, &sb) == -1) { - error("stat local \"%s\": %s", src, strerror(errno)); + error("local stat \"%s\": %s", src, strerror(errno)); return -1; } if (!S_ISDIR(sb.st_mode)) { - error("\"%s\" is not a directory", src); + error("local \"%s\": not a directory", src); return -1; } if (print_flag && print_flag != SFTP_PROGRESS_ONLY) @@ -2273,7 +2209,7 @@ * the path already existed and is a directory. Ensure we can * write to the directory we create for the duration of the transfer. */ - saved_perm = a.perm; +{ u_int32_t saved_perm = a.perm; a.perm |= (S_IWUSR|S_IXUSR); if (do_mkdir(conn, dst, &a, 0) != 0) { if ((dirattrib = do_stat(conn, dst, 0)) == NULL) @@ -2284,6 +2220,7 @@ } } a.perm = saved_perm; +} if ((dirp = opendir(src)) == NULL) { error("local opendir \"%s\": %s", src, strerror(errno)); @@ -2322,7 +2259,7 @@ ret = -1; } } else - logit("%s: not a regular file", filename); + logit("local \"%s\": not a regular file", filename); } free(new_dst); free(new_src); @@ -2363,6 +2300,7 @@ int r; struct pollfd pfd; + UNUSED(to_path); if ((msg = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); @@ -2632,13 +2570,13 @@ } } if (read_error) { - error("read origin \"%s\": %s", from_path, fx2txt(status)); + error("origin read \"%s\": %s", from_path, fx2txt(status)); status = -1; do_close(from, from_handle, from_handle_len); if (to_handle != NULL) do_close(to, to_handle, to_handle_len); } else if (write_error) { - error("write dest \"%s\": %s", to_path, fx2txt(write_error)); + error("dest write \"%s\": %s", to_path, fx2txt(write_error)); status = SSH2_FX_FAILURE; do_close(from, from_handle, from_handle_len); if (to_handle != NULL) @@ -2684,11 +2622,11 @@ if (dirattrib == NULL && (dirattrib = do_stat(from, from_path, 1)) == NULL) { - error("stat remote \"%s\" failed", from_path); + error("remote stat \"%s\" failed", from_path); return -1; } if (!S_ISDIR(dirattrib->perm)) { - error("\"%s\" is not a directory", from_path); + error("remote \"%s\": not a directory", from_path); return -1; } if (print_flag && print_flag != SFTP_PROGRESS_ONLY) @@ -2813,8 +2751,10 @@ int r; *usernamesp = *groupnamesp = NULL; - if (!can_get_users_groups_by_id(conn)) - return SSH_ERR_FEATURE_UNSUPPORTED; + if (!can_get_users_groups_by_id(conn)) { + debug3("Server does not support users-groups-by-id@openssh.com extension"); + return -1; + } if ((msg = sshbuf_new()) == NULL || (uidbuf = sshbuf_new()) == NULL || @@ -2954,7 +2894,6 @@ return(S_ISDIR(a->perm)); } - int local_is_dir(const char *path) { @@ -2975,4 +2914,3 @@ return l > 0 && pathname[l - 1] == '/'; } - diff -ruN openssh-9.4p1/sftp-client.h openssh-9.4p1+x509-14.2.1/sftp-client.h --- openssh-9.4p1/sftp-client.h 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/sftp-client.h 2023-08-20 10:07:00.000000000 +0300 @@ -1,5 +1,4 @@ /* $OpenBSD: sftp-client.h,v 1.38 2022/09/19 10:43:12 djm Exp $ */ - /* * Copyright (c) 2001-2004 Damien Miller * @@ -53,14 +52,6 @@ u_int64_t f_namemax; }; -/* Used for limits response on the wire from the server */ -struct sftp_limits { - u_int64_t packet_length; - u_int64_t read_length; - u_int64_t write_length; - u_int64_t open_handles; -}; - /* print flag values */ #define SFTP_QUIET 0 /* be quiet during transfers */ #define SFTP_PRINT 1 /* list files and show progress bar */ @@ -74,9 +65,6 @@ u_int sftp_proto_version(struct sftp_conn *); -/* Query server limits */ -int do_limits(struct sftp_conn *, struct sftp_limits *); - /* Close file referred to by 'handle' */ int do_close(struct sftp_conn *, const u_char *, u_int); @@ -125,9 +113,6 @@ /* Rename 'oldpath' to 'newpath' */ int do_rename(struct sftp_conn *, const char *, const char *, int); -/* Copy 'oldpath' to 'newpath' */ -int do_copy(struct sftp_conn *, const char *, const char *); - /* Link 'oldpath' to 'newpath' */ int do_hardlink(struct sftp_conn *, const char *, const char *); diff -ruN openssh-9.4p1/sftp-common.c openssh-9.4p1+x509-14.2.1/sftp-common.c --- openssh-9.4p1/sftp-common.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/sftp-common.c 2023-08-20 10:07:01.000000000 +0300 @@ -36,7 +36,6 @@ #include #include #include -#include #ifdef HAVE_UTIL_H #include #endif @@ -211,7 +210,7 @@ } /* - * drwxr-xr-x 5 markus markus 1024 Jan 13 18:39 .ssh + * drwxr-xr-x 5 roumen roumen 1024 Jan 13 18:39 .ssh */ char * ls_file(const char *name, const struct stat *st, int remote, int si_units, @@ -226,11 +225,11 @@ strmode(st->st_mode, mode); if (remote) { if (user == NULL) { - snprintf(ubuf, sizeof ubuf, "%u", (u_int)st->st_uid); + snprintf(ubuf, sizeof ubuf, "%lu", (u_long)st->st_uid); user = ubuf; } if (group == NULL) { - snprintf(gbuf, sizeof gbuf, "%u", (u_int)st->st_gid); + snprintf(gbuf, sizeof gbuf, "%lu", (u_long)st->st_gid); group = gbuf; } strlcpy(lc, "?", sizeof(lc)); diff -ruN openssh-9.4p1/sftp.h openssh-9.4p1+x509-14.2.1/sftp.h --- openssh-9.4p1/sftp.h 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/sftp.h 2023-08-20 10:07:00.000000000 +0300 @@ -25,7 +25,7 @@ */ /* - * draft-ietf-secsh-filexfer-01.txt + * draft-ietf-secsh-filexfer-02.txt */ /* version */ diff -ruN openssh-9.4p1/sftp-realpath.c openssh-9.4p1+x509-14.2.1/sftp-realpath.c --- openssh-9.4p1/sftp-realpath.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/sftp-realpath.c 1970-01-01 02:00:00.000000000 +0200 @@ -1,225 +0,0 @@ -/* $OpenBSD: sftp-realpath.c,v 1.2 2021/09/02 21:03:54 deraadt Exp $ */ -/* - * Copyright (c) 2003 Constantin S. Svintsoff - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The names of the authors may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include "includes.h" - -#include -#include - -#include -#include -#include -#include -#include -#include - -#ifndef SYMLOOP_MAX -# define SYMLOOP_MAX 32 -#endif - -/* XXX rewrite sftp-server to use POSIX realpath and remove this hack */ - -char *sftp_realpath(const char *path, char *resolved); - -/* - * char *realpath(const char *path, char resolved[PATH_MAX]); - * - * Find the real name of path, by removing all ".", ".." and symlink - * components. Returns (resolved) on success, or (NULL) on failure, - * in which case the path which caused trouble is left in (resolved). - */ -char * -sftp_realpath(const char *path, char *resolved) -{ - struct stat sb; - char *p, *q, *s; - size_t left_len, resolved_len; - unsigned symlinks; - int serrno, slen, mem_allocated; - char left[PATH_MAX], next_token[PATH_MAX], symlink[PATH_MAX]; - - if (path[0] == '\0') { - errno = ENOENT; - return (NULL); - } - - serrno = errno; - - if (resolved == NULL) { - resolved = malloc(PATH_MAX); - if (resolved == NULL) - return (NULL); - mem_allocated = 1; - } else - mem_allocated = 0; - - symlinks = 0; - if (path[0] == '/') { - resolved[0] = '/'; - resolved[1] = '\0'; - if (path[1] == '\0') - return (resolved); - resolved_len = 1; - left_len = strlcpy(left, path + 1, sizeof(left)); - } else { - if (getcwd(resolved, PATH_MAX) == NULL) { - if (mem_allocated) - free(resolved); - else - strlcpy(resolved, ".", PATH_MAX); - return (NULL); - } - resolved_len = strlen(resolved); - left_len = strlcpy(left, path, sizeof(left)); - } - if (left_len >= sizeof(left) || resolved_len >= PATH_MAX) { - errno = ENAMETOOLONG; - goto err; - } - - /* - * Iterate over path components in `left'. - */ - while (left_len != 0) { - /* - * Extract the next path component and adjust `left' - * and its length. - */ - p = strchr(left, '/'); - s = p ? p : left + left_len; - if (s - left >= (ptrdiff_t)sizeof(next_token)) { - errno = ENAMETOOLONG; - goto err; - } - memcpy(next_token, left, s - left); - next_token[s - left] = '\0'; - left_len -= s - left; - if (p != NULL) - memmove(left, s + 1, left_len + 1); - if (resolved[resolved_len - 1] != '/') { - if (resolved_len + 1 >= PATH_MAX) { - errno = ENAMETOOLONG; - goto err; - } - resolved[resolved_len++] = '/'; - resolved[resolved_len] = '\0'; - } - if (next_token[0] == '\0') - continue; - else if (strcmp(next_token, ".") == 0) - continue; - else if (strcmp(next_token, "..") == 0) { - /* - * Strip the last path component except when we have - * single "/" - */ - if (resolved_len > 1) { - resolved[resolved_len - 1] = '\0'; - q = strrchr(resolved, '/') + 1; - *q = '\0'; - resolved_len = q - resolved; - } - continue; - } - - /* - * Append the next path component and lstat() it. If - * lstat() fails we still can return successfully if - * there are no more path components left. - */ - resolved_len = strlcat(resolved, next_token, PATH_MAX); - if (resolved_len >= PATH_MAX) { - errno = ENAMETOOLONG; - goto err; - } - if (lstat(resolved, &sb) != 0) { - if (errno == ENOENT && p == NULL) { - errno = serrno; - return (resolved); - } - goto err; - } - if (S_ISLNK(sb.st_mode)) { - if (symlinks++ > SYMLOOP_MAX) { - errno = ELOOP; - goto err; - } - slen = readlink(resolved, symlink, sizeof(symlink) - 1); - if (slen < 0) - goto err; - symlink[slen] = '\0'; - if (symlink[0] == '/') { - resolved[1] = 0; - resolved_len = 1; - } else if (resolved_len > 1) { - /* Strip the last path component. */ - resolved[resolved_len - 1] = '\0'; - q = strrchr(resolved, '/') + 1; - *q = '\0'; - resolved_len = q - resolved; - } - - /* - * If there are any path components left, then - * append them to symlink. The result is placed - * in `left'. - */ - if (p != NULL) { - if (symlink[slen - 1] != '/') { - if (slen + 1 >= - (ptrdiff_t)sizeof(symlink)) { - errno = ENAMETOOLONG; - goto err; - } - symlink[slen] = '/'; - symlink[slen + 1] = 0; - } - left_len = strlcat(symlink, left, sizeof(symlink)); - if (left_len >= sizeof(symlink)) { - errno = ENAMETOOLONG; - goto err; - } - } - left_len = strlcpy(left, symlink, sizeof(left)); - } - } - - /* - * Remove trailing slash except when the resolved pathname - * is a single "/". - */ - if (resolved_len > 1 && resolved[resolved_len - 1] == '/') - resolved[resolved_len - 1] = '\0'; - return (resolved); - -err: - if (mem_allocated) - free(resolved); - return (NULL); -} diff -ruN openssh-9.4p1/sftp-server.0 openssh-9.4p1+x509-14.2.1/sftp-server.0 --- openssh-9.4p1/sftp-server.0 2023-08-10 04:11:18.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/sftp-server.0 2023-08-20 10:07:00.000000000 +0300 @@ -1,7 +1,7 @@ -SFTP-SERVER(8) System Manager's Manual SFTP-SERVER(8) +SFTP-SERVER(8) BSD System Manager's Manual SFTP-SERVER(8) NAME - sftp-server M-bM-^@M-^S OpenSSH SFTP server subsystem + sftp-server -- Secure FTP server subsystem SYNOPSIS sftp-server [-ehR] [-d start_directory] [-f log_facility] [-l log_level] @@ -10,9 +10,9 @@ DESCRIPTION sftp-server is a program that speaks the server side of SFTP protocol to - stdout and expects client requests from stdin. sftp-server is not - intended to be called directly, but from sshd(8) using the Subsystem - option. + stdout and expects client requests from stdin. sftp-server is not in- + tended to be called directly, but from sshd(8) using the Subsystem op- + tion. Command-line flags to sftp-server should be specified in the Subsystem declaration. See sshd_config(5) for more information. @@ -20,13 +20,13 @@ Valid options are: -d start_directory - Specifies an alternate starting directory for users. The - pathname may contain the following tokens that are expanded at - runtime: %% is replaced by a literal '%', %d is replaced by the - home directory of the user being authenticated, and %u is - replaced by the username of that user. The default is to use the - user's home directory. This option is useful in conjunction with - the sshd_config(5) ChrootDirectory option. + Specifies an alternate starting directory for users. The path- + name may contain the following tokens that are expanded at run- + time: %% is replaced by a literal '%', %d is replaced by the home + directory of the user being authenticated, and %u is replaced by + the username of that user. The default is to use the user's home + directory. This option is useful in conjunction with the + sshd_config(5) ChrootDirectory option. -e Causes sftp-server to print logging information to stderr instead of syslog for debugging. @@ -40,12 +40,12 @@ -h Displays sftp-server usage information. -l log_level - Specifies which messages will be logged by sftp-server. The - possible values are: QUIET, FATAL, ERROR, INFO, VERBOSE, DEBUG, - DEBUG1, DEBUG2, and DEBUG3. INFO and VERBOSE log transactions - that sftp-server performs on behalf of the client. DEBUG and - DEBUG1 are equivalent. DEBUG2 and DEBUG3 each specify higher - levels of debugging output. The default is ERROR. + Specifies which messages will be logged by sftp-server. The pos- + sible values are: QUIET, FATAL, ERROR, INFO, VERBOSE, DEBUG, DE- + BUG1, DEBUG2, and DEBUG3. INFO and VERBOSE log transactions that + sftp-server performs on behalf of the client. DEBUG and DEBUG1 + are equivalent. DEBUG2 and DEBUG3 each specify higher levels of + debugging output. The default is ERROR. -P denied_requests Specifies a comma-separated list of SFTP protocol requests that @@ -61,17 +61,17 @@ the allowed list will be logged and replied to with a failure message. - Care must be taken when using this feature to ensure that - requests made implicitly by SFTP clients are permitted. + Care must be taken when using this feature to ensure that re- + quests made implicitly by SFTP clients are permitted. -Q protocol_feature Queries protocol features supported by sftp-server. At present - the only feature that may be queried is M-bM-^@M-^\requestsM-bM-^@M-^], which may be - used to deny or allow specific requests (flags -P and -p - respectively). + the only feature that may be queried is "requests", which may be + used to deny or allow specific requests (flags -P and -p respec- + tively). - -R Places this instance of sftp-server into a read-only mode. - Attempts to open files for writing, as well as other operations + -R Places this instance of sftp-server into a read-only mode. At- + tempts to open files for writing, as well as other operations that change the state of the filesystem, will be denied. -u umask @@ -79,20 +79,18 @@ and directories, instead of the user's default mask. On some systems, sftp-server must be able to access /dev/log for logging - to work, and use of sftp-server in a chroot configuration therefore - requires that syslogd(8) establish a logging socket inside the chroot - directory. + to work, and use of sftp-server in a chroot configuration therefore re- + quires that syslogd(8) establish a logging socket inside the chroot di- + rectory. SEE ALSO sftp(1), ssh(1), sshd_config(5), sshd(8) - T. Ylonen and S. Lehtinen, SSH File Transfer Protocol, draft-ietf-secsh- - filexfer-02.txt, October 2001, work in progress material. - -HISTORY - sftp-server first appeared in OpenBSD 2.8. +CONFORMING TO + 1. T. Ylonen and S. Lehtinen, SSH File Transfer Protocol, draft-ietf- + secsh-filexfer-02.txt, October 2001, work in progress material. AUTHORS Markus Friedl -OpenBSD 7.3 July 27, 2021 OpenBSD 7.3 +BSD 27 July 2021 BSD diff -ruN openssh-9.4p1/sftp-server.8 openssh-9.4p1+x509-14.2.1/sftp-server.8 --- openssh-9.4p1/sftp-server.8 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/sftp-server.8 2023-08-20 10:07:00.000000000 +0300 @@ -22,12 +22,20 @@ .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" +.\" Implement .Dd with the Mdocdate RCS keyword +.rn Dd xD +.de Dd +.ie \\$1$Mdocdate: \{\ +. xD \\$3 \\$2 \\$4 +.\} +.el .xD \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 +.. .Dd $Mdocdate: July 27 2021 $ .Dt SFTP-SERVER 8 .Os .Sh NAME .Nm sftp-server -.Nd OpenSSH SFTP server subsystem +.Nd Secure FTP server subsystem .Sh SYNOPSIS .Nm sftp-server .Bk -words @@ -154,6 +162,9 @@ .Xr ssh 1 , .Xr sshd_config 5 , .Xr sshd 8 +.Sh CONFORMING TO +.Bl -enum +.It .Rs .%A T. Ylonen .%A S. Lehtinen @@ -162,9 +173,6 @@ .%D October 2001 .%O work in progress material .Re -.Sh HISTORY -.Nm -first appeared in -.Ox 2.8 . +.El .Sh AUTHORS .An Markus Friedl Aq Mt markus@openbsd.org diff -ruN openssh-9.4p1/sftp-server.c openssh-9.4p1+x509-14.2.1/sftp-server.c --- openssh-9.4p1/sftp-server.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/sftp-server.c 2023-08-20 10:07:01.000000000 +0300 @@ -1,6 +1,7 @@ /* $OpenBSD: sftp-server.c,v 1.147 2023/04/12 08:53:54 jsg Exp $ */ /* * Copyright (c) 2000-2004 Markus Friedl. All rights reserved. + * Copyright (c) 2021 Roumen Petrov. All rights reserved. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -34,7 +35,11 @@ #include #include #ifdef HAVE_POLL_H -#include +# include +#else +# ifdef HAVE_SYS_POLL_H +# include +# endif #endif #include #include @@ -45,22 +50,40 @@ #include #include -#include "atomicio.h" #include "xmalloc.h" #include "sshbuf.h" #include "ssherr.h" #include "log.h" #include "misc.h" #include "match.h" -#include "uidswap.h" #include "sftp.h" #include "sftp-common.h" -char *sftp_realpath(const char *, char *); /* sftp-realpath.c */ +/* + * Broken realpath: return path as is if does not exist. + * Goal is to use it (temporary?) in sftp related code that relies + * on broken OpenBSD implemenation. + * NOTE: there is no such requirement in filexfer-03 draft. + */ +static char* +sftp_realpath(const char *path, char *resolved_path) { + char *ret; + + ret = realpath(path, resolved_path); + if (ret != NULL) return ret; + if (errno != ENOENT) return ret /*= NULL*/; + + if (resolved_path == NULL) + resolved_path = xstrdup(path); + else + strcpy(resolved_path, path); + return resolved_path; +} /* Maximum data read that we are willing to accept */ #define SFTP_MAX_READ_LENGTH (SFTP_MAX_MSG_LENGTH - 1024) +#define SFTP_INIT_READ_LENGTH (SFTP_MAX_MSG_LENGTH >> 1) /* Our verbosity */ static LogLevel log_level = SYSLOG_LEVEL_ERROR; @@ -121,7 +144,6 @@ static void process_extended_lsetstat(u_int32_t id); static void process_extended_limits(u_int32_t id); static void process_extended_expand(u_int32_t id); -static void process_extended_copy_data(u_int32_t id); static void process_extended_home_directory(u_int32_t id); static void process_extended_get_users_groups_by_id(u_int32_t id); static void process_extended(u_int32_t id); @@ -169,7 +191,6 @@ { "limits", "limits@openssh.com", 0, process_extended_limits, 0 }, { "expand-path", "expand-path@openssh.com", 0, process_extended_expand, 0 }, - { "copy-data", "copy-data", 0, process_extended_copy_data, 1 }, { "home-directory", "home-directory", 0, process_extended_home_directory, 0 }, { "users-groups-by-id", "users-groups-by-id@openssh.com", 0, @@ -549,12 +570,14 @@ send_status_errmsg(u_int32_t id, u_int32_t status, const char *errmsg) { struct sshbuf *msg; + const char *statmsg = status_to_message(status); int r; + if (errmsg == NULL) errmsg = statmsg; debug3("request %u: sent status %u", id, status); if (log_level > SYSLOG_LEVEL_VERBOSE || (status != SSH2_FX_OK && status != SSH2_FX_EOF)) - logit("sent status %s", status_to_message(status)); + logit("sent status %s", statmsg); if ((msg = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); if ((r = sshbuf_put_u8(msg, SSH2_FXP_STATUS)) != 0 || @@ -562,8 +585,7 @@ (r = sshbuf_put_u32(msg, status)) != 0) fatal_fr(r, "compose"); if (version >= 3) { - if ((r = sshbuf_put_cstring(msg, errmsg == NULL ? - status_to_message(status) : errmsg)) != 0 || + if ((r = sshbuf_put_cstring(msg, errmsg)) != 0 || (r = sshbuf_put_cstring(msg, "")) != 0) fatal_fr(r, "compose message"); } @@ -684,20 +706,12 @@ /* * Prepare SSH2_FXP_VERSION extension advertisement for a single extension. - * The extension is checked for permission prior to advertisement. */ static int compose_extension(struct sshbuf *msg, const char *name, const char *ver) { int r; - const struct sftp_handler *exthnd; - if ((exthnd = extended_handler_byname(name)) == NULL) - fatal_f("internal error: no handler for %s", name); - if (!request_permitted(exthnd)) { - debug2_f("refusing to advertise disallowed extension %s", name); - return 0; - } if ((r = sshbuf_put_cstring(msg, name)) != 0 || (r = sshbuf_put_cstring(msg, ver)) != 0) fatal_fr(r, "compose %s", name); @@ -730,7 +744,6 @@ compose_extension(msg, "lsetstat@openssh.com", "1"); compose_extension(msg, "limits@openssh.com", "1"); compose_extension(msg, "expand-path@openssh.com", "1"); - compose_extension(msg, "copy-data", "1"); compose_extension(msg, "home-directory", "1"); compose_extension(msg, "users-groups-by-id@openssh.com", "1"); @@ -798,7 +811,7 @@ static void process_read(u_int32_t id) { - static u_char *buf; + static u_char *buf = NULL; static size_t buflen; u_int32_t len; int r, handle, fd, ret, status = SSH2_FX_FAILURE; @@ -810,43 +823,58 @@ fatal_fr(r, "parse"); debug("request %u: read \"%s\" (handle %d) off %llu len %u", - id, handle_to_name(handle), handle, (unsigned long long)off, len); - if ((fd = handle_to_fd(handle)) == -1) - goto out; + id, handle_to_name(handle), handle, (unsigned long long)off, (u_int)len); + + fd = handle_to_fd(handle); + if (fd == -1) goto out; + if (len > SFTP_MAX_READ_LENGTH) { - debug2("read change len %u to %u", len, SFTP_MAX_READ_LENGTH); + debug2("read change len %u to %u", (u_int)len, SFTP_MAX_READ_LENGTH); len = SFTP_MAX_READ_LENGTH; } + if (buf == NULL) { + buf = malloc(SFTP_INIT_READ_LENGTH); + if (buf == NULL) fatal_f("malloc failed"); + buflen = SFTP_INIT_READ_LENGTH; + } if (len > buflen) { - debug3_f("allocate %zu => %u", buflen, len); - if ((buf = realloc(buf, len)) == NULL) - fatal_f("realloc failed"); + debug3_f("reallocate %zu => %u", buflen, (u_int)len); + buf = realloc(buf, len); + if (buf == NULL) fatal_f("realloc failed"); buflen = len; } + if (lseek(fd, off, SEEK_SET) == -1) { status = errno_to_portable(errno); error_f("seek \"%.100s\": %s", handle_to_name(handle), strerror(errno)); goto out; } + if (len == 0) { /* weird, but not strictly disallowed */ ret = 0; - } else if ((ret = read(fd, buf, len)) == -1) { - status = errno_to_portable(errno); - error_f("read \"%.100s\": %s", handle_to_name(handle), - strerror(errno)); - goto out; - } else if (ret == 0) { - status = SSH2_FX_EOF; - goto out; + } else { + ret = read(fd, buf, len); + if (ret == -1) { + status = errno_to_portable(errno); + error_f("read \"%.100s\": %s", handle_to_name(handle), + strerror(errno)); + goto out; + } + if (ret == 0) { + status = SSH2_FX_EOF; + goto out; + } } - send_data(id, buf, ret); - handle_update_read(handle, ret); /* success */ status = SSH2_FX_OK; + out: - if (status != SSH2_FX_OK) + if (status == SSH2_FX_OK) { + send_data(id, buf, ret); + handle_update_read(handle, ret); + } else send_status(id, status); } @@ -1254,6 +1282,7 @@ debug3("request %u: realpath", id); verbose("realpath \"%s\"", path); if (sftp_realpath(path, resolvedname) == NULL) { + debug3_f("sftp_realpath: %s", strerror(errno)); send_status(id, errno_to_portable(errno)); } else { Stat s; @@ -1281,37 +1310,9 @@ if (lstat(oldpath, &sb) == -1) status = errno_to_portable(errno); else if (S_ISREG(sb.st_mode)) { - /* Race-free rename of regular files */ - if (link(oldpath, newpath) == -1) { - if (errno == EOPNOTSUPP || errno == ENOSYS -#ifdef EXDEV - || errno == EXDEV -#endif -#ifdef LINK_OPNOTSUPP_ERRNO - || errno == LINK_OPNOTSUPP_ERRNO -#endif - ) { - struct stat st; - - /* - * fs doesn't support links, so fall back to - * stat+rename. This is racy. - */ - if (stat(newpath, &st) == -1) { - if (rename(oldpath, newpath) == -1) - status = - errno_to_portable(errno); - else - status = SSH2_FX_OK; - } - } else { - status = errno_to_portable(errno); - } - } else if (unlink(oldpath) == -1) { + if (xrename(oldpath, newpath) == -1) status = errno_to_portable(errno); - /* clean spare link */ - unlink(newpath); - } else + else status = SSH2_FX_OK; } else if (stat(newpath, &sb) == -1) { if (rename(oldpath, newpath) == -1) @@ -1519,15 +1520,22 @@ struct sshbuf *msg; int r; uint64_t nfiles = 0; -#if defined(HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE) - struct rlimit rlim; -#endif debug("request %u: limits", id); + /* + * Minimum file descriptors: + * stdio (3) + syslog (1 maybe) + + * a few spare for libc / stack protectors / sanitisers, etc. + */ +#define SSH_SFTP_SERVER_MIN_FDS (3+1+4) #if defined(HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE) - if (getrlimit(RLIMIT_NOFILE, &rlim) != -1 && rlim.rlim_cur > 5) - nfiles = rlim.rlim_cur - 5; /* stdio(3) + syslog + spare */ +{ struct rlimit rlim; + + if (getrlimit(RLIMIT_NOFILE, &rlim) != -1 && + rlim.rlim_cur > SSH_SFTP_SERVER_MIN_FDS) + nfiles = rlim.rlim_cur - SSH_SFTP_SERVER_MIN_FDS; +} #endif if ((msg = sshbuf_new()) == NULL) @@ -1553,7 +1561,6 @@ char cwd[PATH_MAX], resolvedname[PATH_MAX]; char *path, *npath; int r; - Stat s; if ((r = sshbuf_get_cstring(iqueue, &path, NULL)) != 0) fatal_fr(r, "parse"); @@ -1574,10 +1581,9 @@ free(path); path = xstrdup(cwd); } else if (strncmp(path, "~/", 2) == 0) { - npath = xstrdup(path + 2); + xasprintf(&npath, "%s/%s", cwd, path + 2); free(path); - xasprintf(&path, "%s/%s", cwd, npath); - free(npath); + path = npath; } else { /* ~user expansions */ if (tilde_expand(path, pw->pw_uid, &npath) != 0) { @@ -1596,105 +1602,19 @@ } verbose("expand \"%s\"", path); if (sftp_realpath(path, resolvedname) == NULL) { + debug3_f("sftp_realpath: %s", strerror(errno)); send_status(id, errno_to_portable(errno)); - goto out; + } else { + Stat s; + attrib_clear(&s.attrib); + s.name = s.long_name = resolvedname; + send_names(id, 1, &s); } - attrib_clear(&s.attrib); - s.name = s.long_name = resolvedname; - send_names(id, 1, &s); out: free(path); } static void -process_extended_copy_data(u_int32_t id) -{ - u_char buf[64*1024]; - int read_handle, read_fd, write_handle, write_fd; - u_int64_t len, read_off, read_len, write_off; - int r, copy_until_eof, status = SSH2_FX_OP_UNSUPPORTED; - size_t ret; - - if ((r = get_handle(iqueue, &read_handle)) != 0 || - (r = sshbuf_get_u64(iqueue, &read_off)) != 0 || - (r = sshbuf_get_u64(iqueue, &read_len)) != 0 || - (r = get_handle(iqueue, &write_handle)) != 0 || - (r = sshbuf_get_u64(iqueue, &write_off)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); - - debug("request %u: copy-data from \"%s\" (handle %d) off %llu len %llu " - "to \"%s\" (handle %d) off %llu", - id, handle_to_name(read_handle), read_handle, - (unsigned long long)read_off, (unsigned long long)read_len, - handle_to_name(write_handle), write_handle, - (unsigned long long)write_off); - - /* For read length of 0, we read until EOF. */ - if (read_len == 0) { - read_len = (u_int64_t)-1 - read_off; - copy_until_eof = 1; - } else - copy_until_eof = 0; - - read_fd = handle_to_fd(read_handle); - write_fd = handle_to_fd(write_handle); - - /* Disallow reading & writing to the same handle or same path or dirs */ - if (read_handle == write_handle || read_fd < 0 || write_fd < 0 || - !strcmp(handle_to_name(read_handle), handle_to_name(write_handle))) { - status = SSH2_FX_FAILURE; - goto out; - } - - if (lseek(read_fd, read_off, SEEK_SET) < 0) { - status = errno_to_portable(errno); - error("%s: read_seek failed", __func__); - goto out; - } - - if ((handle_to_flags(write_handle) & O_APPEND) == 0 && - lseek(write_fd, write_off, SEEK_SET) < 0) { - status = errno_to_portable(errno); - error("%s: write_seek failed", __func__); - goto out; - } - - /* Process the request in chunks. */ - while (read_len > 0 || copy_until_eof) { - len = MINIMUM(sizeof(buf), read_len); - read_len -= len; - - ret = atomicio(read, read_fd, buf, len); - if (ret == 0 && errno == EPIPE) { - status = copy_until_eof ? SSH2_FX_OK : SSH2_FX_EOF; - break; - } else if (ret == 0) { - status = errno_to_portable(errno); - error("%s: read failed: %s", __func__, strerror(errno)); - break; - } - len = ret; - handle_update_read(read_handle, len); - - ret = atomicio(vwrite, write_fd, buf, len); - if (ret != len) { - status = errno_to_portable(errno); - error("%s: write failed: %llu != %llu: %s", __func__, - (unsigned long long)ret, (unsigned long long)len, - strerror(errno)); - break; - } - handle_update_write(write_handle, len); - } - - if (read_len == 0) - status = SSH2_FX_OK; - - out: - send_status(id, status); -} - -static void process_extended_home_directory(u_int32_t id) { char *username; @@ -1910,6 +1830,7 @@ extern char *optarg; extern char *__progname; + ssh_malloc_init(); /* must be called before any mallocs */ __progname = ssh_get_progname(argv[0]); log_init(__progname, log_level, log_facility, log_stderr); diff -ruN openssh-9.4p1/sftp-server-main.c openssh-9.4p1+x509-14.2.1/sftp-server-main.c --- openssh-9.4p1/sftp-server-main.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/sftp-server-main.c 2023-08-20 10:07:01.000000000 +0300 @@ -39,6 +39,7 @@ { struct passwd *user_pw; + ssh_malloc_init(); /* must be called before any mallocs */ /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ sanitise_stdfd(); diff -ruN openssh-9.4p1/sftp-usergroup.c openssh-9.4p1+x509-14.2.1/sftp-usergroup.c --- openssh-9.4p1/sftp-usergroup.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/sftp-usergroup.c 2023-08-20 10:07:01.000000000 +0300 @@ -108,7 +108,7 @@ if ((r = do_get_users_groups_by_id(conn, uids, nuids, gids, ngids, &usernames, &groupnames)) != 0) { - debug_fr(r, "do_get_users_groups_by_id"); + debug3_f("do_get_users_groups_by_id fail"); return; } for (i = 0; i < nuids; i++) { @@ -236,4 +236,3 @@ { return idname_lookup(&group_idname, (u_int)gid); } - diff -ruN openssh-9.4p1/sk-api.h openssh-9.4p1+x509-14.2.1/sk-api.h --- openssh-9.4p1/sk-api.h 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/sk-api.h 1970-01-01 02:00:00.000000000 +0200 @@ -1,103 +0,0 @@ -/* $OpenBSD: sk-api.h,v 1.15 2022/07/20 03:29:14 djm Exp $ */ -/* - * Copyright (c) 2019 Google LLC - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#ifndef _SK_API_H -#define _SK_API_H 1 - -#include -#ifdef HAVE_STDINT_H -#include -#endif - -/* Flags */ -#define SSH_SK_USER_PRESENCE_REQD 0x01 -#define SSH_SK_USER_VERIFICATION_REQD 0x04 -#define SSH_SK_FORCE_OPERATION 0x10 -#define SSH_SK_RESIDENT_KEY 0x20 - -/* Algs */ -#define SSH_SK_ECDSA 0x00 -#define SSH_SK_ED25519 0x01 - -/* Error codes */ -#define SSH_SK_ERR_GENERAL -1 -#define SSH_SK_ERR_UNSUPPORTED -2 -#define SSH_SK_ERR_PIN_REQUIRED -3 -#define SSH_SK_ERR_DEVICE_NOT_FOUND -4 -#define SSH_SK_ERR_CREDENTIAL_EXISTS -5 - -struct sk_enroll_response { - uint8_t flags; - uint8_t *public_key; - size_t public_key_len; - uint8_t *key_handle; - size_t key_handle_len; - uint8_t *signature; - size_t signature_len; - uint8_t *attestation_cert; - size_t attestation_cert_len; - uint8_t *authdata; - size_t authdata_len; -}; - -struct sk_sign_response { - uint8_t flags; - uint32_t counter; - uint8_t *sig_r; - size_t sig_r_len; - uint8_t *sig_s; - size_t sig_s_len; -}; - -struct sk_resident_key { - uint32_t alg; - size_t slot; - char *application; - struct sk_enroll_response key; - uint8_t flags; - uint8_t *user_id; - size_t user_id_len; -}; - -struct sk_option { - char *name; - char *value; - uint8_t required; -}; - -#define SSH_SK_VERSION_MAJOR 0x000a0000 /* current API version */ -#define SSH_SK_VERSION_MAJOR_MASK 0xffff0000 - -/* Return the version of the middleware API */ -uint32_t sk_api_version(void); - -/* Enroll a U2F key (private key generation) */ -int sk_enroll(uint32_t alg, const uint8_t *challenge, size_t challenge_len, - const char *application, uint8_t flags, const char *pin, - struct sk_option **options, struct sk_enroll_response **enroll_response); - -/* Sign a challenge */ -int sk_sign(uint32_t alg, const uint8_t *data, size_t data_len, - const char *application, const uint8_t *key_handle, size_t key_handle_len, - uint8_t flags, const char *pin, struct sk_option **options, - struct sk_sign_response **sign_response); - -/* Enumerate all resident keys */ -int sk_load_resident_keys(const char *pin, struct sk_option **options, - struct sk_resident_key ***rks, size_t *nrks); - -#endif /* _SK_API_H */ diff -ruN openssh-9.4p1/.skipped-commit-ids openssh-9.4p1+x509-14.2.1/.skipped-commit-ids --- openssh-9.4p1/.skipped-commit-ids 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/.skipped-commit-ids 1970-01-01 02:00:00.000000000 +0200 @@ -1,55 +0,0 @@ -5317f294d63a876bfc861e19773b1575f96f027d remove libssh from makefiles -a337e886a49f96701ccbc4832bed086a68abfa85 Makefile changes -f2c9feb26963615c4fece921906cf72e248b61ee more Makefile -fa728823ba21c4b45212750e1d3a4b2086fd1a62 more Makefile refactoring -1de0e85522051eb2ffa00437e1885e9d7b3e0c2e moduli update -814b2f670df75759e1581ecef530980b2b3d7e0f remove redundant make defs -04431e8e7872f49a2129bf080a6b73c19d576d40 moduli update -c07772f58028fda683ee6abd41c73da3ff70d403 moduli update -db6375fc302e3bdf07d96430c63c991b2c2bd3ff moduli update -5ea3d63ab972691f43e9087ab5fd8376d48e898f uuencode.c Makefile accident -99dd10e72c04e93849981d43d64c946619efa474 include sshbuf-misc.c -9e1c23476bb845f3cf3d15d9032da3ed0cb2fcf5 sshbuf-misc.c in regress -569f08445c27124ec7c7f6c0268d844ec56ac061 Makefile tweaks for !openssl -58ec755be4e51978ecfee73539090eb68652a987 moduli update -4bd5551b306df55379afe17d841207990eb773bf Makefile.inc -14806a59353152f843eb349e618abbf6f4dd3ada Makefile.inc -8ea4455a2d9364a0a04f9e4a2cbfa4c9fcefe77e Makefile.inc -d9b910e412d139141b072a905e66714870c38ac0 Makefile.inc -7b7b619c1452a459310b0cf4391c5757c6bdbc0f moduli update -5010ff08f7ad92082e87dde098b20f5c24921a8f moduli regen script update -3bcae7a754db3fc5ad3cab63dd46774edb35b8ae moduli regen script update -52ff0e3205036147b2499889353ac082e505ea54 moduli update -07b5031e9f49f2b69ac5e85b8da4fc9e393992a0 Makefile.inc -cc12a9029833d222043aecd252d654965c351a69 moduli-gen Makefile -7ac6c252d2a5be8fbad4c66d9d35db507c9dac5b moduli update -6b52cd2b637f3d29ef543f0ce532a2bce6d86af5 makefile change -f9a0726d957cf10692a231996a1f34e7f9cdfeb0 moduli update -1e0a2692b7e20b126dda60bf04999d1d30d959d8 sshd relinking makefile changes -e1dc11143f83082e3154d6094f9136d0dc2637ad more relinking makefile tweaks - -Old upstream tree: - -321065a95a7ccebdd5fd08482a1e19afbf524e35 Update DH groups -d4f699a421504df35254cf1c6f1a7c304fb907ca Remove 1k bit groups -aafe246655b53b52bc32c8a24002bc262f4230f7 Remove intermediate moduli -8fa9cd1dee3c3339ae329cf20fb591db6d605120 put back SSH1 for 6.9 -f31327a48dd4103333cc53315ec53fe65ed8a17a Generate new moduli -edbfde98c40007b7752a4ac106095e060c25c1ef Regen moduli -052fd565e3ff2d8cec3bc957d1788f50c827f8e2 Switch to tame-based sandbox -7cf73737f357492776223da1c09179fa6ba74660 Remove moduli <2k -180d84674be1344e45a63990d60349988187c1ae Update moduli -f6ae971186ba68d066cd102e57d5b0b2c211a5ee systrace is dead. -96c5054e3e1f170c6276902d5bc65bb3b87a2603 remove DEBUGLIBS from Makefile -6da9a37f74aef9f9cc639004345ad893cad582d8 Update moduli file -77bcb50e47b68c7209c7f0a5a020d73761e5143b unset REGRESS_FAIL_EARLY -38c2133817cbcae75c88c63599ac54228f0fa384 Change COMPILER_VERSION tests -30c20180c87cbc99fa1020489fe7fd8245b6420c resync integrity.sh shell -1e6b51ddf767cbad0a4e63eb08026c127e654308 integrity.sh reliability -fe5b31f69a60d47171836911f144acff77810217 Makefile.inc bits -5781670c0578fe89663c9085ed3ba477cf7e7913 Delete sshconnect1.c -ea80f445e819719ccdcb237022cacfac990fdc5c Makefile.inc warning flags -b92c93266d8234d493857bb822260dacf4366157 moduli-gen.sh tweak -b25bf747544265b39af74fe0716dc8d9f5b63b95 Updated moduli -1bd41cba06a7752de4df304305a8153ebfb6b0ac rsa.[ch] already removed -e39b3902fe1d6c4a7ba6a3c58e072219f3c1e604 Makefile changes diff -ruN openssh-9.4p1/sk-usbhid.c openssh-9.4p1+x509-14.2.1/sk-usbhid.c --- openssh-9.4p1/sk-usbhid.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/sk-usbhid.c 1970-01-01 02:00:00.000000000 +0200 @@ -1,1479 +0,0 @@ -/* $OpenBSD: sk-usbhid.c,v 1.46 2023/03/28 06:12:38 dtucker Exp $ */ -/* - * Copyright (c) 2019 Markus Friedl - * Copyright (c) 2020 Pedro Martelletto - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include "includes.h" - -#ifdef ENABLE_SK_INTERNAL - -#ifdef HAVE_STDINT_H -# include -#endif -#include -#include -#include -#include -#include -#include -#ifdef HAVE_SHA2_H -#include -#endif - -/* - * Almost every use of OpenSSL in this file is for ECDSA-NISTP256. - * This is strictly a larger hammer than necessary, but it reduces changes - * with upstream. - */ -#ifndef OPENSSL_HAS_ECC -# undef WITH_OPENSSL -#endif - -#ifdef WITH_OPENSSL -#include -#include -#include -#include -#include -#include -#endif /* WITH_OPENSSL */ - -#include -#include - -/* backwards compat for libfido2 */ -#ifndef HAVE_FIDO_CRED_PROT -#define fido_cred_prot(x) (0) -#endif -#ifndef HAVE_FIDO_CRED_SET_PROT -#define fido_cred_set_prot(x, y) (FIDO_ERR_UNSUPPORTED_OPTION) -#endif -#ifndef HAVE_FIDO_DEV_SUPPORTS_CRED_PROT -#define fido_dev_supports_cred_prot(x) (0) -#endif -#ifndef HAVE_FIDO_DEV_GET_TOUCH_BEGIN -#define fido_dev_get_touch_begin(x) (FIDO_ERR_UNSUPPORTED_OPTION) -#endif -#ifndef HAVE_FIDO_DEV_GET_TOUCH_STATUS -#define fido_dev_get_touch_status(x, y, z) (FIDO_ERR_UNSUPPORTED_OPTION) -#endif -#ifndef FIDO_CRED_PROT_UV_REQUIRED -#define FIDO_CRED_PROT_UV_REQUIRED 0 -#endif -#ifndef FIDO_CRED_PROT_UV_OPTIONAL_WITH_ID -#define FIDO_CRED_PROT_UV_OPTIONAL_WITH_ID 0 -#endif - -#ifndef SK_STANDALONE -# include "log.h" -# include "xmalloc.h" -# include "misc.h" -/* - * If building as part of OpenSSH, then rename exported functions. - * This must be done before including sk-api.h. - */ -# define sk_api_version ssh_sk_api_version -# define sk_enroll ssh_sk_enroll -# define sk_sign ssh_sk_sign -# define sk_load_resident_keys ssh_sk_load_resident_keys -#endif /* !SK_STANDALONE */ - -#include "sk-api.h" - -/* #define SK_DEBUG 1 */ - -#ifdef SK_DEBUG -#define SSH_FIDO_INIT_ARG FIDO_DEBUG -#else -#define SSH_FIDO_INIT_ARG 0 -#endif - -#define MAX_FIDO_DEVICES 8 -#define FIDO_POLL_MS 50 -#define SELECT_MS 15000 -#define POLL_SLEEP_NS 200000000 - -#ifndef FIDO_ERR_OPERATION_DENIED -#define FIDO_ERR_OPERATION_DENIED 0x27 -#endif - -struct sk_usbhid { - fido_dev_t *dev; - char *path; -}; - -/* Return the version of the middleware API */ -uint32_t sk_api_version(void); - -/* Enroll a U2F key (private key generation) */ -int sk_enroll(uint32_t alg, const uint8_t *challenge, size_t challenge_len, - const char *application, uint8_t flags, const char *pin, - struct sk_option **options, struct sk_enroll_response **enroll_response); - -/* Sign a challenge */ -int sk_sign(uint32_t alg, const uint8_t *data, size_t data_len, - const char *application, const uint8_t *key_handle, size_t key_handle_len, - uint8_t flags, const char *pin, struct sk_option **options, - struct sk_sign_response **sign_response); - -/* Load resident keys */ -int sk_load_resident_keys(const char *pin, struct sk_option **options, - struct sk_resident_key ***rks, size_t *nrks); - -static void skdebug(const char *func, const char *fmt, ...) - __attribute__((__format__ (printf, 2, 3))); - -static void -skdebug(const char *func, const char *fmt, ...) -{ -#if !defined(SK_STANDALONE) - char *msg; - va_list ap; - - va_start(ap, fmt); - xvasprintf(&msg, fmt, ap); - va_end(ap); - debug("%s: %s", func, msg); - free(msg); -#elif defined(SK_DEBUG) - va_list ap; - - va_start(ap, fmt); - fprintf(stderr, "%s: ", func); - vfprintf(stderr, fmt, ap); - fputc('\n', stderr); - va_end(ap); -#else - (void)func; /* XXX */ - (void)fmt; /* XXX */ -#endif -} - -uint32_t -sk_api_version(void) -{ - return SSH_SK_VERSION_MAJOR; -} - -static struct sk_usbhid * -sk_open(const char *path) -{ - struct sk_usbhid *sk; - int r; - - if (path == NULL) { - skdebug(__func__, "path == NULL"); - return NULL; - } - if ((sk = calloc(1, sizeof(*sk))) == NULL) { - skdebug(__func__, "calloc sk failed"); - return NULL; - } - if ((sk->path = strdup(path)) == NULL) { - skdebug(__func__, "strdup path failed"); - free(sk); - return NULL; - } - if ((sk->dev = fido_dev_new()) == NULL) { - skdebug(__func__, "fido_dev_new failed"); - free(sk->path); - free(sk); - return NULL; - } - if ((r = fido_dev_open(sk->dev, sk->path)) != FIDO_OK) { - skdebug(__func__, "fido_dev_open %s failed: %s", sk->path, - fido_strerr(r)); - fido_dev_free(&sk->dev); - free(sk->path); - free(sk); - return NULL; - } - return sk; -} - -static void -sk_close(struct sk_usbhid *sk) -{ - if (sk == NULL) - return; - fido_dev_cancel(sk->dev); /* cancel any pending operation */ - fido_dev_close(sk->dev); - fido_dev_free(&sk->dev); - free(sk->path); - free(sk); -} - -static struct sk_usbhid ** -sk_openv(const fido_dev_info_t *devlist, size_t ndevs, size_t *nopen) -{ - const fido_dev_info_t *di; - struct sk_usbhid **skv; - size_t i; - - *nopen = 0; - if ((skv = calloc(ndevs, sizeof(*skv))) == NULL) { - skdebug(__func__, "calloc skv failed"); - return NULL; - } - for (i = 0; i < ndevs; i++) { - if ((di = fido_dev_info_ptr(devlist, i)) == NULL) - skdebug(__func__, "fido_dev_info_ptr failed"); - else if ((skv[*nopen] = sk_open(fido_dev_info_path(di))) == NULL) - skdebug(__func__, "sk_open failed"); - else - (*nopen)++; - } - if (*nopen == 0) { - for (i = 0; i < ndevs; i++) - sk_close(skv[i]); - free(skv); - skv = NULL; - } - - return skv; -} - -static void -sk_closev(struct sk_usbhid **skv, size_t nsk) -{ - size_t i; - - for (i = 0; i < nsk; i++) - sk_close(skv[i]); - free(skv); -} - -static int -sk_touch_begin(struct sk_usbhid **skv, size_t nsk) -{ - size_t i, ok = 0; - int r; - - for (i = 0; i < nsk; i++) - if ((r = fido_dev_get_touch_begin(skv[i]->dev)) != FIDO_OK) - skdebug(__func__, "fido_dev_get_touch_begin %s failed:" - " %s", skv[i]->path, fido_strerr(r)); - else - ok++; - - return ok ? 0 : -1; -} - -static int -sk_touch_poll(struct sk_usbhid **skv, size_t nsk, int *touch, size_t *idx) -{ - struct timespec ts_pause; - size_t npoll, i; - int r; - - ts_pause.tv_sec = 0; - ts_pause.tv_nsec = POLL_SLEEP_NS; - nanosleep(&ts_pause, NULL); - npoll = nsk; - for (i = 0; i < nsk; i++) { - if (skv[i] == NULL) - continue; /* device discarded */ - skdebug(__func__, "polling %s", skv[i]->path); - if ((r = fido_dev_get_touch_status(skv[i]->dev, touch, - FIDO_POLL_MS)) != FIDO_OK) { - skdebug(__func__, "fido_dev_get_touch_status %s: %s", - skv[i]->path, fido_strerr(r)); - sk_close(skv[i]); /* discard device */ - skv[i] = NULL; - if (--npoll == 0) { - skdebug(__func__, "no device left to poll"); - return -1; - } - } else if (*touch) { - *idx = i; - return 0; - } - } - *touch = 0; - return 0; -} - -#if !defined(HAVE_FIDO_ASSERT_SET_CLIENTDATA) || \ - !defined(HAVE_FIDO_CRED_SET_CLIENTDATA) -/* Calculate SHA256(m) */ -static int -sha256_mem(const void *m, size_t mlen, u_char *d, size_t dlen) -{ -#ifdef WITH_OPENSSL - u_int mdlen; -#else - SHA2_CTX ctx; -#endif - - if (dlen != 32) - return -1; -#ifdef WITH_OPENSSL - mdlen = dlen; - if (!EVP_Digest(m, mlen, d, &mdlen, EVP_sha256(), NULL)) - return -1; -#else - SHA256Init(&ctx); - SHA256Update(&ctx, (const uint8_t *)m, mlen); - SHA256Final(d, &ctx); -#endif - return 0; -} -#endif /* !HAVE_FIDO_ASSERT_SET_CLIENTDATA || !HAVE_FIDO_CRED_SET_CLIENTDATA */ - -#ifndef HAVE_FIDO_CRED_SET_CLIENTDATA -static int -fido_cred_set_clientdata(fido_cred_t *cred, const u_char *ptr, size_t len) -{ - uint8_t d[32]; - int r; - - if (sha256_mem(ptr, len, d, sizeof(d)) != 0) { - skdebug(__func__, "hash challenge failed"); - return FIDO_ERR_INTERNAL; - } - r = fido_cred_set_clientdata_hash(cred, d, sizeof(d)); - explicit_bzero(d, sizeof(d)); - if (r != FIDO_OK) { - skdebug(__func__, "fido_cred_set_clientdata_hash failed: %s", - fido_strerr(r)); - } - return r; -} -#endif /* HAVE_FIDO_CRED_SET_CLIENTDATA */ - -#ifndef HAVE_FIDO_ASSERT_SET_CLIENTDATA -static int -fido_assert_set_clientdata(fido_assert_t *assert, const u_char *ptr, size_t len) -{ - uint8_t d[32]; - int r; - - if (sha256_mem(ptr, len, d, sizeof(d)) != 0) { - skdebug(__func__, "hash challenge failed"); - return FIDO_ERR_INTERNAL; - } - r = fido_assert_set_clientdata_hash(assert, d, sizeof(d)); - explicit_bzero(d, sizeof(d)); - if (r != FIDO_OK) { - skdebug(__func__, "fido_assert_set_clientdata_hash failed: %s", - fido_strerr(r)); - } - return r; -} -#endif /* HAVE_FIDO_ASSERT_SET_CLIENTDATA */ - -#ifndef HAVE_FIDO_DEV_IS_WINHELLO -static bool -fido_dev_is_winhello(const fido_dev_t *fdev) -{ - return 0; -} -#endif /* HAVE_FIDO_DEV_IS_WINHELLO */ - -/* Check if the specified key handle exists on a given sk. */ -static int -sk_try(const struct sk_usbhid *sk, const char *application, - const uint8_t *key_handle, size_t key_handle_len) -{ - fido_assert_t *assert = NULL; - int r = FIDO_ERR_INTERNAL; - uint8_t message[32]; - - memset(message, '\0', sizeof(message)); - if ((assert = fido_assert_new()) == NULL) { - skdebug(__func__, "fido_assert_new failed"); - goto out; - } - /* generate an invalid signature on FIDO2 tokens */ - if ((r = fido_assert_set_clientdata(assert, message, - sizeof(message))) != FIDO_OK) { - skdebug(__func__, "fido_assert_set_clientdata: %s", - fido_strerr(r)); - goto out; - } - if ((r = fido_assert_set_rp(assert, application)) != FIDO_OK) { - skdebug(__func__, "fido_assert_set_rp: %s", fido_strerr(r)); - goto out; - } - if ((r = fido_assert_allow_cred(assert, key_handle, - key_handle_len)) != FIDO_OK) { - skdebug(__func__, "fido_assert_allow_cred: %s", fido_strerr(r)); - goto out; - } - if ((r = fido_assert_set_up(assert, FIDO_OPT_FALSE)) != FIDO_OK) { - skdebug(__func__, "fido_assert_up: %s", fido_strerr(r)); - goto out; - } - r = fido_dev_get_assert(sk->dev, assert, NULL); - skdebug(__func__, "fido_dev_get_assert: %s", fido_strerr(r)); - if (r == FIDO_ERR_USER_PRESENCE_REQUIRED) { - /* U2F tokens may return this */ - r = FIDO_OK; - } - out: - fido_assert_free(&assert); - - return r != FIDO_OK ? -1 : 0; -} - -static int -check_sk_options(fido_dev_t *dev, const char *opt, int *ret) -{ - fido_cbor_info_t *info; - char * const *name; - const bool *value; - size_t len, i; - int r; - - *ret = -1; - - if (!fido_dev_is_fido2(dev)) { - skdebug(__func__, "device is not fido2"); - return 0; - } - if ((info = fido_cbor_info_new()) == NULL) { - skdebug(__func__, "fido_cbor_info_new failed"); - return -1; - } - if ((r = fido_dev_get_cbor_info(dev, info)) != FIDO_OK) { - skdebug(__func__, "fido_dev_get_cbor_info: %s", fido_strerr(r)); - fido_cbor_info_free(&info); - return -1; - } - name = fido_cbor_info_options_name_ptr(info); - value = fido_cbor_info_options_value_ptr(info); - len = fido_cbor_info_options_len(info); - for (i = 0; i < len; i++) { - if (!strcmp(name[i], opt)) { - *ret = value[i]; - break; - } - } - fido_cbor_info_free(&info); - if (*ret == -1) - skdebug(__func__, "option %s is unknown", opt); - else - skdebug(__func__, "option %s is %s", opt, *ret ? "on" : "off"); - - return 0; -} - -static struct sk_usbhid * -sk_select_by_cred(const fido_dev_info_t *devlist, size_t ndevs, - const char *application, const uint8_t *key_handle, size_t key_handle_len) -{ - struct sk_usbhid **skv, *sk; - size_t skvcnt, i; - int internal_uv; - - if ((skv = sk_openv(devlist, ndevs, &skvcnt)) == NULL) { - skdebug(__func__, "sk_openv failed"); - return NULL; - } - if (skvcnt == 1 && check_sk_options(skv[0]->dev, "uv", - &internal_uv) == 0 && internal_uv != -1) { - sk = skv[0]; - skv[0] = NULL; - goto out; - } - sk = NULL; - for (i = 0; i < skvcnt; i++) { - if (sk_try(skv[i], application, key_handle, - key_handle_len) == 0) { - sk = skv[i]; - skv[i] = NULL; - skdebug(__func__, "found key in %s", sk->path); - break; - } - } - out: - sk_closev(skv, skvcnt); - return sk; -} - -static struct sk_usbhid * -sk_select_by_touch(const fido_dev_info_t *devlist, size_t ndevs) -{ - struct sk_usbhid **skv, *sk; - struct timeval tv_start, tv_now, tv_delta; - size_t skvcnt, idx; - int touch, ms_remain; - - if ((skv = sk_openv(devlist, ndevs, &skvcnt)) == NULL) { - skdebug(__func__, "sk_openv failed"); - return NULL; - } - sk = NULL; - if (skvcnt < 2) { - if (skvcnt == 1) { - /* single candidate */ - sk = skv[0]; - skv[0] = NULL; - } - goto out; - } -#ifndef HAVE_FIDO_DEV_GET_TOUCH_STATUS - skdebug(__func__, "libfido2 version does not support a feature needed for multiple tokens. Please upgrade to >=1.5.0"); - goto out; -#endif - - if (sk_touch_begin(skv, skvcnt) == -1) { - skdebug(__func__, "sk_touch_begin failed"); - goto out; - } - monotime_tv(&tv_start); - do { - if (sk_touch_poll(skv, skvcnt, &touch, &idx) == -1) { - skdebug(__func__, "sk_touch_poll failed"); - goto out; - } - if (touch) { - sk = skv[idx]; - skv[idx] = NULL; - goto out; - } - monotime_tv(&tv_now); - timersub(&tv_now, &tv_start, &tv_delta); - ms_remain = SELECT_MS - tv_delta.tv_sec * 1000 - - tv_delta.tv_usec / 1000; - } while (ms_remain >= FIDO_POLL_MS); - skdebug(__func__, "timeout"); -out: - sk_closev(skv, skvcnt); - return sk; -} - -static struct sk_usbhid * -sk_probe(const char *application, const uint8_t *key_handle, - size_t key_handle_len, int probe_resident) -{ - struct sk_usbhid *sk; - fido_dev_info_t *devlist; - size_t ndevs; - int r; - -#ifdef HAVE_CYGWIN - if (!probe_resident && (sk = sk_open("windows://hello")) != NULL) - return sk; -#endif /* HAVE_CYGWIN */ - if ((devlist = fido_dev_info_new(MAX_FIDO_DEVICES)) == NULL) { - skdebug(__func__, "fido_dev_info_new failed"); - return NULL; - } - if ((r = fido_dev_info_manifest(devlist, MAX_FIDO_DEVICES, - &ndevs)) != FIDO_OK) { - skdebug(__func__, "fido_dev_info_manifest failed: %s", - fido_strerr(r)); - fido_dev_info_free(&devlist, MAX_FIDO_DEVICES); - return NULL; - } - skdebug(__func__, "%zu device(s) detected", ndevs); - if (ndevs == 0) { - sk = NULL; - } else if (application != NULL && key_handle != NULL) { - skdebug(__func__, "selecting sk by cred"); - sk = sk_select_by_cred(devlist, ndevs, application, key_handle, - key_handle_len); - } else { - skdebug(__func__, "selecting sk by touch"); - sk = sk_select_by_touch(devlist, ndevs); - } - fido_dev_info_free(&devlist, MAX_FIDO_DEVICES); - return sk; -} - -#ifdef WITH_OPENSSL -/* - * The key returned via fido_cred_pubkey_ptr() is in affine coordinates, - * but the API expects a SEC1 octet string. - */ -static int -pack_public_key_ecdsa(const fido_cred_t *cred, - struct sk_enroll_response *response) -{ - const uint8_t *ptr; - BIGNUM *x = NULL, *y = NULL; - EC_POINT *q = NULL; - EC_GROUP *g = NULL; - int ret = -1; - - response->public_key = NULL; - response->public_key_len = 0; - - if ((x = BN_new()) == NULL || - (y = BN_new()) == NULL || - (g = EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1)) == NULL || - (q = EC_POINT_new(g)) == NULL) { - skdebug(__func__, "libcrypto setup failed"); - goto out; - } - if ((ptr = fido_cred_pubkey_ptr(cred)) == NULL) { - skdebug(__func__, "fido_cred_pubkey_ptr failed"); - goto out; - } - if (fido_cred_pubkey_len(cred) != 64) { - skdebug(__func__, "bad fido_cred_pubkey_len %zu", - fido_cred_pubkey_len(cred)); - goto out; - } - - if (BN_bin2bn(ptr, 32, x) == NULL || - BN_bin2bn(ptr + 32, 32, y) == NULL) { - skdebug(__func__, "BN_bin2bn failed"); - goto out; - } - if (EC_POINT_set_affine_coordinates_GFp(g, q, x, y, NULL) != 1) { - skdebug(__func__, "EC_POINT_set_affine_coordinates_GFp failed"); - goto out; - } - response->public_key_len = EC_POINT_point2oct(g, q, - POINT_CONVERSION_UNCOMPRESSED, NULL, 0, NULL); - if (response->public_key_len == 0 || response->public_key_len > 2048) { - skdebug(__func__, "bad pubkey length %zu", - response->public_key_len); - goto out; - } - if ((response->public_key = malloc(response->public_key_len)) == NULL) { - skdebug(__func__, "malloc pubkey failed"); - goto out; - } - if (EC_POINT_point2oct(g, q, POINT_CONVERSION_UNCOMPRESSED, - response->public_key, response->public_key_len, NULL) == 0) { - skdebug(__func__, "EC_POINT_point2oct failed"); - goto out; - } - /* success */ - ret = 0; - out: - if (ret != 0 && response->public_key != NULL) { - memset(response->public_key, 0, response->public_key_len); - free(response->public_key); - response->public_key = NULL; - } - EC_POINT_free(q); - EC_GROUP_free(g); - BN_clear_free(x); - BN_clear_free(y); - return ret; -} -#endif /* WITH_OPENSSL */ - -static int -pack_public_key_ed25519(const fido_cred_t *cred, - struct sk_enroll_response *response) -{ - const uint8_t *ptr; - size_t len; - int ret = -1; - - response->public_key = NULL; - response->public_key_len = 0; - - if ((len = fido_cred_pubkey_len(cred)) != 32) { - skdebug(__func__, "bad fido_cred_pubkey_len len %zu", len); - goto out; - } - if ((ptr = fido_cred_pubkey_ptr(cred)) == NULL) { - skdebug(__func__, "fido_cred_pubkey_ptr failed"); - goto out; - } - response->public_key_len = len; - if ((response->public_key = malloc(response->public_key_len)) == NULL) { - skdebug(__func__, "malloc pubkey failed"); - goto out; - } - memcpy(response->public_key, ptr, len); - ret = 0; - out: - if (ret != 0) - free(response->public_key); - return ret; -} - -static int -pack_public_key(uint32_t alg, const fido_cred_t *cred, - struct sk_enroll_response *response) -{ - switch(alg) { -#ifdef WITH_OPENSSL - case SSH_SK_ECDSA: - return pack_public_key_ecdsa(cred, response); -#endif /* WITH_OPENSSL */ - case SSH_SK_ED25519: - return pack_public_key_ed25519(cred, response); - default: - return -1; - } -} - -static int -fidoerr_to_skerr(int fidoerr) -{ - switch (fidoerr) { - case FIDO_ERR_UNSUPPORTED_OPTION: - case FIDO_ERR_UNSUPPORTED_ALGORITHM: - return SSH_SK_ERR_UNSUPPORTED; - case FIDO_ERR_PIN_REQUIRED: - case FIDO_ERR_PIN_INVALID: - case FIDO_ERR_OPERATION_DENIED: - return SSH_SK_ERR_PIN_REQUIRED; - default: - return -1; - } -} - -static int -check_enroll_options(struct sk_option **options, char **devicep, - uint8_t *user_id, size_t user_id_len) -{ - size_t i; - - if (options == NULL) - return 0; - for (i = 0; options[i] != NULL; i++) { - if (strcmp(options[i]->name, "device") == 0) { - if ((*devicep = strdup(options[i]->value)) == NULL) { - skdebug(__func__, "strdup device failed"); - return -1; - } - skdebug(__func__, "requested device %s", *devicep); - } else if (strcmp(options[i]->name, "user") == 0) { - if (strlcpy(user_id, options[i]->value, user_id_len) >= - user_id_len) { - skdebug(__func__, "user too long"); - return -1; - } - skdebug(__func__, "requested user %s", - (char *)user_id); - } else { - skdebug(__func__, "requested unsupported option %s", - options[i]->name); - if (options[i]->required) { - skdebug(__func__, "unknown required option"); - return -1; - } - } - } - return 0; -} - -static int -key_lookup(fido_dev_t *dev, const char *application, const uint8_t *user_id, - size_t user_id_len, const char *pin) -{ - fido_assert_t *assert = NULL; - uint8_t message[32]; - int r = FIDO_ERR_INTERNAL; - int sk_supports_uv, uv; - size_t i; - - memset(message, '\0', sizeof(message)); - if ((assert = fido_assert_new()) == NULL) { - skdebug(__func__, "fido_assert_new failed"); - goto out; - } - /* generate an invalid signature on FIDO2 tokens */ - if ((r = fido_assert_set_clientdata(assert, message, - sizeof(message))) != FIDO_OK) { - skdebug(__func__, "fido_assert_set_clientdata: %s", - fido_strerr(r)); - goto out; - } - if ((r = fido_assert_set_rp(assert, application)) != FIDO_OK) { - skdebug(__func__, "fido_assert_set_rp: %s", fido_strerr(r)); - goto out; - } - if ((r = fido_assert_set_up(assert, FIDO_OPT_FALSE)) != FIDO_OK) { - skdebug(__func__, "fido_assert_set_up: %s", fido_strerr(r)); - goto out; - } - uv = FIDO_OPT_OMIT; - if (pin == NULL && check_sk_options(dev, "uv", &sk_supports_uv) == 0 && - sk_supports_uv != -1) - uv = FIDO_OPT_TRUE; - if ((r = fido_assert_set_uv(assert, uv)) != FIDO_OK) { - skdebug(__func__, "fido_assert_set_uv: %s", fido_strerr(r)); - goto out; - } - if ((r = fido_dev_get_assert(dev, assert, pin)) != FIDO_OK) { - skdebug(__func__, "fido_dev_get_assert: %s", fido_strerr(r)); - goto out; - } - r = FIDO_ERR_NO_CREDENTIALS; - skdebug(__func__, "%zu signatures returned", fido_assert_count(assert)); - for (i = 0; i < fido_assert_count(assert); i++) { - if (fido_assert_user_id_len(assert, i) == user_id_len && - memcmp(fido_assert_user_id_ptr(assert, i), user_id, - user_id_len) == 0) { - skdebug(__func__, "credential exists"); - r = FIDO_OK; - goto out; - } - } - out: - fido_assert_free(&assert); - - return r; -} - -int -sk_enroll(uint32_t alg, const uint8_t *challenge, size_t challenge_len, - const char *application, uint8_t flags, const char *pin, - struct sk_option **options, struct sk_enroll_response **enroll_response) -{ - fido_cred_t *cred = NULL; - const uint8_t *ptr; - uint8_t user_id[32]; - struct sk_usbhid *sk = NULL; - struct sk_enroll_response *response = NULL; - size_t len; - int credprot; - int cose_alg; - int ret = SSH_SK_ERR_GENERAL; - int r; - char *device = NULL; - - fido_init(SSH_FIDO_INIT_ARG); - - if (enroll_response == NULL) { - skdebug(__func__, "enroll_response == NULL"); - goto out; - } - *enroll_response = NULL; - memset(user_id, 0, sizeof(user_id)); - if (check_enroll_options(options, &device, user_id, - sizeof(user_id)) != 0) - goto out; /* error already logged */ - - switch(alg) { -#ifdef WITH_OPENSSL - case SSH_SK_ECDSA: - cose_alg = COSE_ES256; - break; -#endif /* WITH_OPENSSL */ - case SSH_SK_ED25519: - cose_alg = COSE_EDDSA; - break; - default: - skdebug(__func__, "unsupported key type %d", alg); - goto out; - } - if (device != NULL) - sk = sk_open(device); - else - sk = sk_probe(NULL, NULL, 0, 0); - if (sk == NULL) { - ret = SSH_SK_ERR_DEVICE_NOT_FOUND; - skdebug(__func__, "failed to find sk"); - goto out; - } - skdebug(__func__, "using device %s", sk->path); - if ((flags & SSH_SK_RESIDENT_KEY) != 0 && - (flags & SSH_SK_FORCE_OPERATION) == 0 && - (r = key_lookup(sk->dev, application, user_id, sizeof(user_id), - pin)) != FIDO_ERR_NO_CREDENTIALS) { - if (r != FIDO_OK) { - ret = fidoerr_to_skerr(r); - skdebug(__func__, "key_lookup failed"); - } else { - ret = SSH_SK_ERR_CREDENTIAL_EXISTS; - skdebug(__func__, "key exists"); - } - goto out; - } - if ((cred = fido_cred_new()) == NULL) { - skdebug(__func__, "fido_cred_new failed"); - goto out; - } - if ((r = fido_cred_set_type(cred, cose_alg)) != FIDO_OK) { - skdebug(__func__, "fido_cred_set_type: %s", fido_strerr(r)); - goto out; - } - if ((r = fido_cred_set_clientdata(cred, - challenge, challenge_len)) != FIDO_OK) { - skdebug(__func__, "fido_cred_set_clientdata: %s", - fido_strerr(r)); - goto out; - } - if ((r = fido_cred_set_rk(cred, (flags & SSH_SK_RESIDENT_KEY) != 0 ? - FIDO_OPT_TRUE : FIDO_OPT_OMIT)) != FIDO_OK) { - skdebug(__func__, "fido_cred_set_rk: %s", fido_strerr(r)); - goto out; - } - if ((r = fido_cred_set_user(cred, user_id, sizeof(user_id), - "openssh", "openssh", NULL)) != FIDO_OK) { - skdebug(__func__, "fido_cred_set_user: %s", fido_strerr(r)); - goto out; - } - if ((r = fido_cred_set_rp(cred, application, NULL)) != FIDO_OK) { - skdebug(__func__, "fido_cred_set_rp: %s", fido_strerr(r)); - goto out; - } - if ((flags & (SSH_SK_RESIDENT_KEY|SSH_SK_USER_VERIFICATION_REQD)) != 0) { -#if !defined(HAVE_FIDO_DEV_SUPPORTS_CRED_PROT) || \ - !defined(HAVE_FIDO_CRED_SET_PROT) - skdebug(__func__, "libfido2 version does not support a feature required for this operation. Please upgrade to >=1.5.0"); - ret = SSH_SK_ERR_UNSUPPORTED; - goto out; - credprot = 0; (void)credprot; /* avoid warning */ -#endif - if (!fido_dev_supports_cred_prot(sk->dev)) { - skdebug(__func__, "%s does not support credprot, " - "refusing to create unprotected " - "resident/verify-required key", sk->path); - ret = SSH_SK_ERR_UNSUPPORTED; - goto out; - } - if ((flags & SSH_SK_USER_VERIFICATION_REQD)) - credprot = FIDO_CRED_PROT_UV_REQUIRED; - else - credprot = FIDO_CRED_PROT_UV_OPTIONAL_WITH_ID; - - if ((r = fido_cred_set_prot(cred, credprot)) != FIDO_OK) { - skdebug(__func__, "fido_cred_set_prot: %s", - fido_strerr(r)); - ret = fidoerr_to_skerr(r); - goto out; - } - } - if ((r = fido_dev_make_cred(sk->dev, cred, pin)) != FIDO_OK) { - skdebug(__func__, "fido_dev_make_cred: %s", fido_strerr(r)); - ret = fidoerr_to_skerr(r); - goto out; - } - if (fido_cred_x5c_ptr(cred) != NULL) { - if ((r = fido_cred_verify(cred)) != FIDO_OK) { - skdebug(__func__, "fido_cred_verify: %s", - fido_strerr(r)); - goto out; - } - } else { - skdebug(__func__, "self-attested credential"); - if ((r = fido_cred_verify_self(cred)) != FIDO_OK) { - skdebug(__func__, "fido_cred_verify_self: %s", - fido_strerr(r)); - goto out; - } - } - if ((response = calloc(1, sizeof(*response))) == NULL) { - skdebug(__func__, "calloc response failed"); - goto out; - } - response->flags = flags; - if (pack_public_key(alg, cred, response) != 0) { - skdebug(__func__, "pack_public_key failed"); - goto out; - } - if ((ptr = fido_cred_id_ptr(cred)) != NULL) { - len = fido_cred_id_len(cred); - if ((response->key_handle = calloc(1, len)) == NULL) { - skdebug(__func__, "calloc key handle failed"); - goto out; - } - memcpy(response->key_handle, ptr, len); - response->key_handle_len = len; - } - if ((ptr = fido_cred_sig_ptr(cred)) != NULL) { - len = fido_cred_sig_len(cred); - if ((response->signature = calloc(1, len)) == NULL) { - skdebug(__func__, "calloc signature failed"); - goto out; - } - memcpy(response->signature, ptr, len); - response->signature_len = len; - } - if ((ptr = fido_cred_x5c_ptr(cred)) != NULL) { - len = fido_cred_x5c_len(cred); - skdebug(__func__, "attestation cert len=%zu", len); - if ((response->attestation_cert = calloc(1, len)) == NULL) { - skdebug(__func__, "calloc attestation cert failed"); - goto out; - } - memcpy(response->attestation_cert, ptr, len); - response->attestation_cert_len = len; - } - if ((ptr = fido_cred_authdata_ptr(cred)) != NULL) { - len = fido_cred_authdata_len(cred); - skdebug(__func__, "authdata len=%zu", len); - if ((response->authdata = calloc(1, len)) == NULL) { - skdebug(__func__, "calloc authdata failed"); - goto out; - } - memcpy(response->authdata, ptr, len); - response->authdata_len = len; - } - *enroll_response = response; - response = NULL; - ret = 0; - out: - free(device); - if (response != NULL) { - free(response->public_key); - free(response->key_handle); - free(response->signature); - free(response->attestation_cert); - free(response->authdata); - free(response); - } - sk_close(sk); - fido_cred_free(&cred); - return ret; -} - -#ifdef WITH_OPENSSL -static int -pack_sig_ecdsa(fido_assert_t *assert, struct sk_sign_response *response) -{ - ECDSA_SIG *sig = NULL; - const BIGNUM *sig_r, *sig_s; - const unsigned char *cp; - size_t sig_len; - int ret = -1; - - cp = fido_assert_sig_ptr(assert, 0); - sig_len = fido_assert_sig_len(assert, 0); - if ((sig = d2i_ECDSA_SIG(NULL, &cp, sig_len)) == NULL) { - skdebug(__func__, "d2i_ECDSA_SIG failed"); - goto out; - } - ECDSA_SIG_get0(sig, &sig_r, &sig_s); - response->sig_r_len = BN_num_bytes(sig_r); - response->sig_s_len = BN_num_bytes(sig_s); - if ((response->sig_r = calloc(1, response->sig_r_len)) == NULL || - (response->sig_s = calloc(1, response->sig_s_len)) == NULL) { - skdebug(__func__, "calloc signature failed"); - goto out; - } - BN_bn2bin(sig_r, response->sig_r); - BN_bn2bin(sig_s, response->sig_s); - ret = 0; - out: - ECDSA_SIG_free(sig); - if (ret != 0) { - free(response->sig_r); - free(response->sig_s); - response->sig_r = NULL; - response->sig_s = NULL; - } - return ret; -} -#endif /* WITH_OPENSSL */ - -static int -pack_sig_ed25519(fido_assert_t *assert, struct sk_sign_response *response) -{ - const unsigned char *ptr; - size_t len; - int ret = -1; - - ptr = fido_assert_sig_ptr(assert, 0); - len = fido_assert_sig_len(assert, 0); - if (len != 64) { - skdebug(__func__, "bad length %zu", len); - goto out; - } - response->sig_r_len = len; - if ((response->sig_r = calloc(1, response->sig_r_len)) == NULL) { - skdebug(__func__, "calloc signature failed"); - goto out; - } - memcpy(response->sig_r, ptr, len); - ret = 0; - out: - if (ret != 0) { - free(response->sig_r); - response->sig_r = NULL; - } - return ret; -} - -static int -pack_sig(uint32_t alg, fido_assert_t *assert, - struct sk_sign_response *response) -{ - switch(alg) { -#ifdef WITH_OPENSSL - case SSH_SK_ECDSA: - return pack_sig_ecdsa(assert, response); -#endif /* WITH_OPENSSL */ - case SSH_SK_ED25519: - return pack_sig_ed25519(assert, response); - default: - return -1; - } -} - -/* Checks sk_options for sk_sign() and sk_load_resident_keys() */ -static int -check_sign_load_resident_options(struct sk_option **options, char **devicep) -{ - size_t i; - - if (options == NULL) - return 0; - for (i = 0; options[i] != NULL; i++) { - if (strcmp(options[i]->name, "device") == 0) { - if ((*devicep = strdup(options[i]->value)) == NULL) { - skdebug(__func__, "strdup device failed"); - return -1; - } - skdebug(__func__, "requested device %s", *devicep); - } else { - skdebug(__func__, "requested unsupported option %s", - options[i]->name); - if (options[i]->required) { - skdebug(__func__, "unknown required option"); - return -1; - } - } - } - return 0; -} - -int -sk_sign(uint32_t alg, const uint8_t *data, size_t datalen, - const char *application, - const uint8_t *key_handle, size_t key_handle_len, - uint8_t flags, const char *pin, struct sk_option **options, - struct sk_sign_response **sign_response) -{ - fido_assert_t *assert = NULL; - char *device = NULL; - struct sk_usbhid *sk = NULL; - struct sk_sign_response *response = NULL; - int ret = SSH_SK_ERR_GENERAL, internal_uv; - int r; - - fido_init(SSH_FIDO_INIT_ARG); - - if (sign_response == NULL) { - skdebug(__func__, "sign_response == NULL"); - goto out; - } - *sign_response = NULL; - if (check_sign_load_resident_options(options, &device) != 0) - goto out; /* error already logged */ - if (device != NULL) - sk = sk_open(device); - else if (pin != NULL || (flags & SSH_SK_USER_VERIFICATION_REQD)) - sk = sk_probe(NULL, NULL, 0, 0); - else - sk = sk_probe(application, key_handle, key_handle_len, 0); - if (sk == NULL) { - ret = SSH_SK_ERR_DEVICE_NOT_FOUND; - skdebug(__func__, "failed to find sk"); - goto out; - } - if ((assert = fido_assert_new()) == NULL) { - skdebug(__func__, "fido_assert_new failed"); - goto out; - } - if ((r = fido_assert_set_clientdata(assert, - data, datalen)) != FIDO_OK) { - skdebug(__func__, "fido_assert_set_clientdata: %s", - fido_strerr(r)); - goto out; - } - if ((r = fido_assert_set_rp(assert, application)) != FIDO_OK) { - skdebug(__func__, "fido_assert_set_rp: %s", fido_strerr(r)); - goto out; - } - if ((r = fido_assert_allow_cred(assert, key_handle, - key_handle_len)) != FIDO_OK) { - skdebug(__func__, "fido_assert_allow_cred: %s", fido_strerr(r)); - goto out; - } - if ((r = fido_assert_set_up(assert, - (flags & SSH_SK_USER_PRESENCE_REQD) ? - FIDO_OPT_TRUE : FIDO_OPT_FALSE)) != FIDO_OK) { - skdebug(__func__, "fido_assert_set_up: %s", fido_strerr(r)); - goto out; - } - /* - * WinHello requests the PIN by default. Make "uv" request explicit - * to allow keys with and without -O verify-required to make sense. - */ - if (pin == NULL && fido_dev_is_winhello (sk->dev) && - (r = fido_assert_set_uv(assert, FIDO_OPT_FALSE)) != FIDO_OK) { - skdebug(__func__, "fido_assert_set_uv: %s", fido_strerr(r)); - } - if (pin == NULL && (flags & SSH_SK_USER_VERIFICATION_REQD)) { - if (check_sk_options(sk->dev, "uv", &internal_uv) < 0 || - internal_uv != 1) { - skdebug(__func__, "check_sk_options uv"); - ret = SSH_SK_ERR_PIN_REQUIRED; - goto out; - } - if ((r = fido_assert_set_uv(assert, - FIDO_OPT_TRUE)) != FIDO_OK) { - skdebug(__func__, "fido_assert_set_uv: %s", - fido_strerr(r)); - ret = fidoerr_to_skerr(r); - goto out; - } - } - if ((r = fido_dev_get_assert(sk->dev, assert, pin)) != FIDO_OK) { - skdebug(__func__, "fido_dev_get_assert: %s", fido_strerr(r)); - ret = fidoerr_to_skerr(r); - goto out; - } - if ((response = calloc(1, sizeof(*response))) == NULL) { - skdebug(__func__, "calloc response failed"); - goto out; - } - response->flags = fido_assert_flags(assert, 0); - response->counter = fido_assert_sigcount(assert, 0); - if (pack_sig(alg, assert, response) != 0) { - skdebug(__func__, "pack_sig failed"); - goto out; - } - *sign_response = response; - response = NULL; - ret = 0; - out: - free(device); - if (response != NULL) { - free(response->sig_r); - free(response->sig_s); - free(response); - } - sk_close(sk); - fido_assert_free(&assert); - return ret; -} - -static int -read_rks(struct sk_usbhid *sk, const char *pin, - struct sk_resident_key ***rksp, size_t *nrksp) -{ - int ret = SSH_SK_ERR_GENERAL, r = -1, internal_uv; - fido_credman_metadata_t *metadata = NULL; - fido_credman_rp_t *rp = NULL; - fido_credman_rk_t *rk = NULL; - size_t i, j, nrp, nrk, user_id_len; - const fido_cred_t *cred; - const char *rp_id, *rp_name, *user_name; - struct sk_resident_key *srk = NULL, **tmp; - const u_char *user_id; - - if (pin == NULL) { - skdebug(__func__, "no PIN specified"); - ret = SSH_SK_ERR_PIN_REQUIRED; - goto out; - } - if ((metadata = fido_credman_metadata_new()) == NULL) { - skdebug(__func__, "alloc failed"); - goto out; - } - if (check_sk_options(sk->dev, "uv", &internal_uv) != 0) { - skdebug(__func__, "check_sk_options failed"); - goto out; - } - - if ((r = fido_credman_get_dev_metadata(sk->dev, metadata, pin)) != 0) { - if (r == FIDO_ERR_INVALID_COMMAND) { - skdebug(__func__, "device %s does not support " - "resident keys", sk->path); - ret = 0; - goto out; - } - skdebug(__func__, "get metadata for %s failed: %s", - sk->path, fido_strerr(r)); - ret = fidoerr_to_skerr(r); - goto out; - } - skdebug(__func__, "existing %llu, remaining %llu", - (unsigned long long)fido_credman_rk_existing(metadata), - (unsigned long long)fido_credman_rk_remaining(metadata)); - if ((rp = fido_credman_rp_new()) == NULL) { - skdebug(__func__, "alloc rp failed"); - goto out; - } - if ((r = fido_credman_get_dev_rp(sk->dev, rp, pin)) != 0) { - skdebug(__func__, "get RPs for %s failed: %s", - sk->path, fido_strerr(r)); - goto out; - } - nrp = fido_credman_rp_count(rp); - skdebug(__func__, "Device %s has resident keys for %zu RPs", - sk->path, nrp); - - /* Iterate over RP IDs that have resident keys */ - for (i = 0; i < nrp; i++) { - rp_id = fido_credman_rp_id(rp, i); - rp_name = fido_credman_rp_name(rp, i); - skdebug(__func__, "rp %zu: name=\"%s\" id=\"%s\" hashlen=%zu", - i, rp_name == NULL ? "(none)" : rp_name, - rp_id == NULL ? "(none)" : rp_id, - fido_credman_rp_id_hash_len(rp, i)); - - /* Skip non-SSH RP IDs */ - if (rp_id == NULL || - strncasecmp(fido_credman_rp_id(rp, i), "ssh:", 4) != 0) - continue; - - fido_credman_rk_free(&rk); - if ((rk = fido_credman_rk_new()) == NULL) { - skdebug(__func__, "alloc rk failed"); - goto out; - } - if ((r = fido_credman_get_dev_rk(sk->dev, - fido_credman_rp_id(rp, i), rk, pin)) != 0) { - skdebug(__func__, "get RKs for %s slot %zu failed: %s", - sk->path, i, fido_strerr(r)); - goto out; - } - nrk = fido_credman_rk_count(rk); - skdebug(__func__, "RP \"%s\" has %zu resident keys", - fido_credman_rp_id(rp, i), nrk); - - /* Iterate over resident keys for this RP ID */ - for (j = 0; j < nrk; j++) { - if ((cred = fido_credman_rk(rk, j)) == NULL) { - skdebug(__func__, "no RK in slot %zu", j); - continue; - } - if ((user_name = fido_cred_user_name(cred)) == NULL) - user_name = ""; - user_id = fido_cred_user_id_ptr(cred); - user_id_len = fido_cred_user_id_len(cred); - skdebug(__func__, "Device %s RP \"%s\" user \"%s\" " - "uidlen %zu slot %zu: type %d flags 0x%02x " - "prot 0x%02x", sk->path, rp_id, user_name, - user_id_len, j, fido_cred_type(cred), - fido_cred_flags(cred), fido_cred_prot(cred)); - - /* build response entry */ - if ((srk = calloc(1, sizeof(*srk))) == NULL || - (srk->key.key_handle = calloc(1, - fido_cred_id_len(cred))) == NULL || - (srk->application = strdup(rp_id)) == NULL || - (user_id_len > 0 && - (srk->user_id = calloc(1, user_id_len)) == NULL)) { - skdebug(__func__, "alloc sk_resident_key"); - goto out; - } - - srk->key.key_handle_len = fido_cred_id_len(cred); - memcpy(srk->key.key_handle, fido_cred_id_ptr(cred), - srk->key.key_handle_len); - srk->user_id_len = user_id_len; - if (srk->user_id_len != 0) - memcpy(srk->user_id, user_id, srk->user_id_len); - - switch (fido_cred_type(cred)) { - case COSE_ES256: - srk->alg = SSH_SK_ECDSA; - break; - case COSE_EDDSA: - srk->alg = SSH_SK_ED25519; - break; - default: - skdebug(__func__, "unsupported key type %d", - fido_cred_type(cred)); - goto out; /* XXX free rk and continue */ - } - - if (fido_cred_prot(cred) == FIDO_CRED_PROT_UV_REQUIRED - && internal_uv == -1) - srk->flags |= SSH_SK_USER_VERIFICATION_REQD; - - if ((r = pack_public_key(srk->alg, cred, - &srk->key)) != 0) { - skdebug(__func__, "pack public key failed"); - goto out; - } - /* append */ - if ((tmp = recallocarray(*rksp, *nrksp, (*nrksp) + 1, - sizeof(**rksp))) == NULL) { - skdebug(__func__, "alloc rksp"); - goto out; - } - *rksp = tmp; - (*rksp)[(*nrksp)++] = srk; - srk = NULL; - } - } - /* Success */ - ret = 0; - out: - if (srk != NULL) { - free(srk->application); - freezero(srk->key.public_key, srk->key.public_key_len); - freezero(srk->key.key_handle, srk->key.key_handle_len); - freezero(srk->user_id, srk->user_id_len); - freezero(srk, sizeof(*srk)); - } - fido_credman_rp_free(&rp); - fido_credman_rk_free(&rk); - fido_credman_metadata_free(&metadata); - return ret; -} - -int -sk_load_resident_keys(const char *pin, struct sk_option **options, - struct sk_resident_key ***rksp, size_t *nrksp) -{ - int ret = SSH_SK_ERR_GENERAL, r = -1; - size_t i, nrks = 0; - struct sk_resident_key **rks = NULL; - struct sk_usbhid *sk = NULL; - char *device = NULL; - - *rksp = NULL; - *nrksp = 0; - - fido_init(SSH_FIDO_INIT_ARG); - - if (check_sign_load_resident_options(options, &device) != 0) - goto out; /* error already logged */ - if (device != NULL) - sk = sk_open(device); - else - sk = sk_probe(NULL, NULL, 0, 1); - if (sk == NULL) { - ret = SSH_SK_ERR_DEVICE_NOT_FOUND; - skdebug(__func__, "failed to find sk"); - goto out; - } - skdebug(__func__, "trying %s", sk->path); - if ((r = read_rks(sk, pin, &rks, &nrks)) != 0) { - skdebug(__func__, "read_rks failed for %s", sk->path); - ret = r; - goto out; - } - /* success, unless we have no keys but a specific error */ - if (nrks > 0 || ret == SSH_SK_ERR_GENERAL) - ret = 0; - *rksp = rks; - *nrksp = nrks; - rks = NULL; - nrks = 0; - out: - sk_close(sk); - for (i = 0; i < nrks; i++) { - free(rks[i]->application); - freezero(rks[i]->key.public_key, rks[i]->key.public_key_len); - freezero(rks[i]->key.key_handle, rks[i]->key.key_handle_len); - freezero(rks[i]->user_id, rks[i]->user_id_len); - freezero(rks[i], sizeof(*rks[i])); - } - free(device); - free(rks); - return ret; -} - -#endif /* ENABLE_SK_INTERNAL */ diff -ruN openssh-9.4p1/sntrup761.c openssh-9.4p1+x509-14.2.1/sntrup761.c --- openssh-9.4p1/sntrup761.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/sntrup761.c 2023-08-20 10:07:01.000000000 +0300 @@ -10,8 +10,6 @@ #include "includes.h" -#ifdef USE_SNTRUP761X25519 - #include #include "crypto_api.h" @@ -1163,6 +1161,7 @@ for (i = 0;i < Inputs_bytes;++i) x[i] = r[i]; for (i = 0;i < Hash_bytes;++i) x[Inputs_bytes+i] = cache[i]; #endif + UNUSED(pk); /* TODO */ Hash_prefix(h,2,x,sizeof x); } @@ -1270,4 +1269,3 @@ Decap(k,c,sk); return 0; } -#endif /* USE_SNTRUP761X25519 */ diff -ruN openssh-9.4p1/srclimit.c openssh-9.4p1+x509-14.2.1/srclimit.c --- openssh-9.4p1/srclimit.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/srclimit.c 2023-08-20 10:07:01.000000000 +0300 @@ -1,5 +1,6 @@ /* * Copyright (c) 2020 Darren Tucker + * Copyright (c) 2021 Roumen Petrov. All rights reserved. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -31,7 +32,7 @@ #include "srclimit.h" #include "xmalloc.h" -static int max_children, max_persource, ipv4_masklen, ipv6_masklen; +static int max_persource = -1, max_children, ipv4_masklen, ipv6_masklen; /* Per connection state, used to enforce unauthenticated connection limit. */ static struct child_info { @@ -48,12 +49,12 @@ ipv4_masklen = ipv4len; ipv6_masklen = ipv6len; max_persource = persource; - if (max_persource == INT_MAX) /* no limit */ - return; - debug("%s: max connections %d, per source %d, masks %d,%d", __func__, + if (max_persource < 0) return; /* no limit */ + + debug_f("max connections %d, per source %d, masks %d,%d", max, persource, ipv4len, ipv6len); if (max <= 0) - fatal("%s: invalid number of sockets: %d", __func__, max); + fatal_f("invalid number of sockets: %d", max); child = xcalloc(max_children, sizeof(*child)); for (i = 0; i < max_children; i++) child[i].id = -1; @@ -65,52 +66,56 @@ { struct xaddr xa, xb, xmask; struct sockaddr_storage addr; - socklen_t addrlen = sizeof(addr); - struct sockaddr *sa = (struct sockaddr *)&addr; - int i, bits, first_unused, count = 0; - char xas[NI_MAXHOST]; + int i, bits, first_unused, count; - if (max_persource == INT_MAX) /* no limit */ - return 1; + if (max_persource < 0) return 1; /* no limit */ + + debug_f("sock %d id %d limit %d", sock, id, max_persource); +{ + struct sockaddr *sa = (struct sockaddr *)&addr; + socklen_t addrlen = sizeof(addr); - debug("%s: sock %d id %d limit %d", __func__, sock, id, max_persource); if (getpeername(sock, sa, &addrlen) != 0) return 1; /* not remote socket? */ if (addr_sa_to_xaddr(sa, addrlen, &xa) != 0) return 1; /* unknown address family? */ +} /* Mask address off address to desired size. */ bits = xa.af == AF_INET ? ipv4_masklen : ipv6_masklen; if (addr_netmask(xa.af, bits, &xmask) != 0 || addr_and(&xb, &xa, &xmask) != 0) { - debug3("%s: invalid mask %d bits", __func__, bits); - return 1; + debug3_f("invalid mask %d bits", bits); + return 1; /*allowed?*/ } first_unused = max_children; + count = 0; /* Count matching entries and find first unused one. */ for (i = 0; i < max_children; i++) { if (child[i].id == -1) { - if (i < first_unused) + if (i < first_unused) { first_unused = i; - } else if (addr_cmp(&child[i].addr, &xb) == 0) { - count++; - } - } - if (addr_ntop(&xa, xas, sizeof(xas)) != 0) { - debug3("%s: addr ntop failed", __func__); - return 1; + break; + } + } else + if (addr_cmp(&child[i].addr, &xb) == 0) + count++; } - debug3("%s: new unauthenticated connection from %s/%d, at %d of %d", - __func__, xas, bits, count, max_persource); - if (first_unused == max_children) { /* no free slot found */ - debug3("%s: no free slot", __func__); + debug3_f("no free slot"); return 0; } - if (first_unused < 0 || first_unused >= max_children) - fatal("%s: internal error: first_unused out of range", - __func__); + +{ char xas[NI_MAXHOST]; + if (addr_ntop(&xa, xas, sizeof(xas)) != 0) + debug3_f("addr ntop failed"); + /* return 1; allowed!? */ + else + strlcpy(xas, "", sizeof(xas)); + debug3_f("new unauthenticated connection from %s/%d, at %d of %d", + xas, bits, count, max_persource); +} if (count >= max_persource) return 0; @@ -126,10 +131,9 @@ { int i; - if (max_persource == INT_MAX) /* no limit */ - return; + if (max_persource < 0) return; /* no limit */ - debug("%s: id %d", __func__, id); + debug_f("id %d", id); /* Clear corresponding state entry. */ for (i = 0; i < max_children; i++) { if (child[i].id == id) { diff -ruN openssh-9.4p1/srclimit.h openssh-9.4p1+x509-14.2.1/srclimit.h --- openssh-9.4p1/srclimit.h 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/srclimit.h 2023-08-20 10:07:00.000000000 +0300 @@ -1,3 +1,5 @@ +#ifndef SRCLIMIT_H +#define SRCLIMIT_H /* * Copyright (c) 2020 Darren Tucker * @@ -16,3 +18,4 @@ void srclimit_init(int, int, int, int); int srclimit_check_allow(int, int); void srclimit_done(int); +#endif /* SRCLIMIT_H */ diff -ruN openssh-9.4p1/ssh.0 openssh-9.4p1+x509-14.2.1/ssh.0 --- openssh-9.4p1/ssh.0 2023-08-10 04:11:18.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/ssh.0 2023-08-20 10:07:00.000000000 +0300 @@ -1,16 +1,16 @@ -SSH(1) General Commands Manual SSH(1) +SSH(1) BSD General Commands Manual SSH(1) NAME - ssh M-bM-^@M-^S OpenSSH remote login client + ssh -- Secure shell client (remote login program) SYNOPSIS - ssh [-46AaCfGgKkMNnqsTtVvXxYy] [-B bind_interface] [-b bind_address] + ssh [-46AaCdfgKkMNnqsTtVvXxYy] [-B bind_interface] [-b bind_address] [-c cipher_spec] [-D [bind_address:]port] [-E log_file] - [-e escape_char] [-F configfile] [-I pkcs11] [-i identity_file] - [-J destination] [-L address] [-l login_name] [-m mac_spec] - [-O ctl_cmd] [-o option] [-P tag] [-p port] [-Q query_option] - [-R address] [-S ctl_path] [-W host:port] [-w local_tun[:remote_tun]] - destination [command [argument ...]] + [-e escape_char] [-F configfile] [-G engine_configfile] [-I pkcs11] + [-i identity_file] [-J destination] [-L address] [-l login_name] + [-m mac_spec] [-O ctl_cmd] [-o option] [-P tag] [-p port] + [-Q query_option] [-R address] [-S ctl_path] [-W host:port] + [-w local_tun[:remote_tun]] destination [command [argument ...]] DESCRIPTION ssh (SSH client) is a program for logging into a remote machine and for @@ -19,8 +19,8 @@ network. X11 connections, arbitrary TCP ports and UNIX-domain sockets can also be forwarded over the secure channel. - ssh connects and logs into the specified destination, which may be - specified as either [user@]hostname or a URI of the form + ssh connects and logs into the specified destination, which may be speci- + fied as either [user@]hostname or a URI of the form ssh://[user@]hostname[:port]. The user must prove their identity to the remote machine using one of several methods (see below). @@ -46,28 +46,30 @@ the forwarded connection. An attacker cannot obtain key material from the agent, however they can perform operations on the keys that enable them to authenticate using the identities loaded into - the agent. A safer alternative may be to use a jump host (see - -J). + the agent. Using the -c flag of ssh-add(1) can reduce (but not + eliminate) the risk. A safer alternative may be to use a jump + host (see -J). -a Disables forwarding of the authentication agent connection. -B bind_interface - Bind to the address of bind_interface before attempting to - connect to the destination host. This is only useful on systems + Bind to the address of bind_interface before attempting to con- + nect to the destination host. This is only useful on systems with more than one address. -b bind_address Use bind_address on the local machine as the source address of - the connection. Only useful on systems with more than one - address. + the connection. Only useful on systems with more than one ad- + dress. -C Requests compression of all data (including stdin, stdout, - stderr, and data for forwarded X11, TCP and UNIX-domain - connections). The compression algorithm is the same used by - gzip(1). Compression is desirable on modem lines and other slow - connections, but will only slow down things on fast networks. - The default value can be set on a host-by-host basis in the - configuration files; see the Compression option in ssh_config(5). + stderr, and data for forwarded X11, TCP and UNIX-domain connec- + tions). The compression algorithm is the same used by gzip(1). + Compression is desirable on modem lines and other slow connec- + tions, but will only slow down things on fast networks. The de- + fault value can be set on a host-by-host basis in the configura- + tion files. See the Compression keyword in ssh_config(5) for more + information. -c cipher_spec Selects the cipher specification for encrypting the session. @@ -76,59 +78,64 @@ information. -D [bind_address:]port - Specifies a local M-bM-^@M-^\dynamicM-bM-^@M-^] application-level port forwarding. + Specifies a local "dynamic" application-level port forwarding. This works by allocating a socket to listen to port on the local side, optionally bound to the specified bind_address. Whenever a connection is made to this port, the connection is forwarded over the secure channel, and the application protocol is then used to determine where to connect to from the remote machine. Currently the SOCKS4 and SOCKS5 protocols are supported, and ssh will act - as a SOCKS server. Only root can forward privileged ports. - Dynamic port forwardings can also be specified in the - configuration file. + as a SOCKS server. Only root can forward privileged ports. Dy- + namic port forwardings can also be specified in the configuration + file. IPv6 addresses can be specified by enclosing the address in square brackets. Only the superuser can forward privileged ports. By default, the local port is bound in accordance with the GatewayPorts setting. However, an explicit bind_address may be used to bind the connection to a specific address. The - bind_address of M-bM-^@M-^\localhostM-bM-^@M-^] indicates that the listening port be - bound for local use only, while an empty address or M-bM-^@M-^X*M-bM-^@M-^Y indicates + bind_address of "localhost" indicates that the listening port be + bound for local use only, while an empty address or '*' indicates that the port should be available from all interfaces. + -d Causes ssh to print its configuration after evaluating Host and + Match blocks and exit. + -E log_file Append debug logs to log_file instead of standard error. -e escape_char - Sets the escape character for sessions with a pty (default: M-bM-^@M-^X~M-bM-^@M-^Y). + Sets the escape character for sessions with a pty (default: '~'). The escape character is only recognized at the beginning of a - line. The escape character followed by a dot (M-bM-^@M-^X.M-bM-^@M-^Y) closes the + line. The escape character followed by a dot ('.') closes the connection; followed by control-Z suspends the connection; and followed by itself sends the escape character once. Setting the - character to M-bM-^@M-^\noneM-bM-^@M-^] disables any escapes and makes the session + character to "none" disables any escapes and makes the session fully transparent. -F configfile - Specifies an alternative per-user configuration file. If a - configuration file is given on the command line, the system-wide + Specifies an alternative per-user configuration file. If a con- + figuration file is given on the command line, the system-wide configuration file (/etc/ssh/ssh_config) will be ignored. The default for the per-user configuration file is ~/.ssh/config. If - set to M-bM-^@M-^\noneM-bM-^@M-^], no configuration files will be read. + set to "none", no configuration files will be read. -f Requests ssh to go to background just before command execution. This is useful if ssh is going to ask for passwords or - passphrases, but the user wants it in the background. This - implies -n. The recommended way to start X11 programs at a - remote site is with something like ssh -f host xterm. - - If the ExitOnForwardFailure configuration option is set to M-bM-^@M-^\yesM-bM-^@M-^], - then a client started with -f will wait for all remote port - forwards to be successfully established before placing itself in - the background. Refer to the description of - ForkAfterAuthentication in ssh_config(5) for details. - - -G Causes ssh to print its configuration after evaluating Host and - Match blocks and exit. + passphrases, but the user wants it in the background. This im- + plies -n. The recommended way to start X11 programs at a remote + site is with something like ssh -f host xterm. + + If the ExitOnForwardFailure configuration option is set to "yes", + then a client started with -f will wait for all remote port for- + wards to be successfully established before placing itself in the + background. Refer to the description of ForkAfterAuthentication + in ssh_config(5) for details. + + -G engine_configfile + Specifies an alternative per-user file for post initialization of + openssl(1) engines. The default per-user configuration file is + ~/.ssh/engine. -g Allows remote hosts to connect to local forwarded ports. If used on a multiplexed connection, then this option must be specified @@ -136,25 +143,39 @@ -I pkcs11 Specify the PKCS#11 shared library ssh should use to communicate - with a PKCS#11 token providing keys for user authentication. + with a PKCS#11 token providing the user's private EC or RSA key + and X.509 certificate. -i identity_file Selects a file from which the identity (private key) for public key authentication is read. You can also specify a public key file to use the corresponding private key that is loaded in ssh-agent(1) when the private key file is not present locally. - The default is ~/.ssh/id_rsa, ~/.ssh/id_ecdsa, - ~/.ssh/id_ecdsa_sk, ~/.ssh/id_ed25519, ~/.ssh/id_ed25519_sk and - ~/.ssh/id_dsa. Identity files may also be specified on a per- - host basis in the configuration file. It is possible to have - multiple -i options (and multiple identities specified in - configuration files). If no certificates have been explicitly - specified by the CertificateFile directive, ssh will also try to - load certificate information from the filename obtained by - appending -cert.pub to identity filenames. + The default is ~/.ssh/id_rsa, ~/.ssh/id_ecdsa, ~/.ssh/id_ed25519 + and ~/.ssh/id_dsa. Identity files may also be specified on a + per-host basis in the configuration file. It is possible to have + multiple -i options (and multiple identities specified in config- + uration files). + + Option is equal to configuration option IdentityFile - see + ssh_config(5) for more details. This mean than could be used + prefixes "engine:" or "store:" to load identifies using engine or + store functionality provided by cryptographic library. + + For RSA, ECDSA, Ed25519 or DSA identity file may contain X.509 + certificate that match key. In addition file may contain extra + X.509 certificates. Extra certificates along with certificates + from X.509 store are used to build chain of certificates leading + to a trusted certificate authority if required by public key al- + gorithm format. + + If no OpenSSH custom certificates have been explicitly specified + by the CertificateFile directive, ssh will also try to load + OpenSSH custom certificate information from the filename obtained + by appending -cert.pub to identity filenames. -J destination - Connect to the target host by first making an ssh connection to + Connect to the target host by first making a ssh connection to the jump host described by destination and then establishing a TCP forwarding to the ultimate destination from there. Multiple jump hops may be specified separated by comma characters. This @@ -176,8 +197,8 @@ -L local_socket:remote_socket Specifies that connections to the given TCP port or Unix socket on the local (client) host are to be forwarded to the given host - and port, or Unix socket, on the remote side. This works by - allocating a socket to listen to either a TCP port on the local + and port, or Unix socket, on the remote side. This works by al- + locating a socket to listen to either a TCP port on the local side, optionally bound to the specified bind_address, or to a Unix socket. Whenever a connection is made to the local port or socket, the connection is forwarded over the secure channel, and @@ -191,170 +212,77 @@ By default, the local port is bound in accordance with the GatewayPorts setting. However, an explicit bind_address may be used to bind the connection to a specific address. The - bind_address of M-bM-^@M-^\localhostM-bM-^@M-^] indicates that the listening port be - bound for local use only, while an empty address or M-bM-^@M-^X*M-bM-^@M-^Y indicates + bind_address of "localhost" indicates that the listening port be + bound for local use only, while an empty address or '*' indicates that the port should be available from all interfaces. -l login_name Specifies the user to log in as on the remote machine. This also may be specified on a per-host basis in the configuration file. - -M Places the ssh client into M-bM-^@M-^\masterM-bM-^@M-^] mode for connection sharing. - Multiple -M options places ssh into M-bM-^@M-^\masterM-bM-^@M-^] mode but with - confirmation required using ssh-askpass(1) before each operation + -M Places the ssh client into "master" mode for connection sharing. + Multiple -M options places ssh into "master" mode but with con- + firmation required using ssh-askpass(1) before each operation that changes the multiplexing state (e.g. opening a new session). Refer to the description of ControlMaster in ssh_config(5) for details. -m mac_spec - A comma-separated list of MAC (message authentication code) - algorithms, specified in order of preference. See the MACs - keyword in ssh_config(5) for more information. + A comma-separated list of MAC (message authentication code) algo- + rithms, specified in order of preference. See the MACs keyword + in ssh_config(5) for more information. - -N Do not execute a remote command. This is useful for just - forwarding ports. Refer to the description of SessionType in + -N Do not execute a remote command. This is useful for just for- + warding ports. Refer to the description of SessionType in ssh_config(5) for details. -n Redirects stdin from /dev/null (actually, prevents reading from stdin). This must be used when ssh is run in the background. A - common trick is to use this to run X11 programs on a remote - machine. For example, ssh -n shadows.cs.hut.fi emacs & will - start an emacs on shadows.cs.hut.fi, and the X11 connection will - be automatically forwarded over an encrypted channel. The ssh - program will be put in the background. (This does not work if - ssh needs to ask for a password or passphrase; see also the -f - option.) Refer to the description of StdinNull in ssh_config(5) - for details. + common trick is to use this to run X11 programs on a remote ma- + chine. For example, ssh -n shadows.cs.hut.fi emacs & will start + an emacs on shadows.cs.hut.fi, and the X11 connection will be au- + tomatically forwarded over an encrypted channel. The ssh program + will be put in the background. (This does not work if ssh needs + to ask for a password or passphrase; see also the -f option.) + Refer to the description of StdinNull in ssh_config(5) for de- + tails. -O ctl_cmd Control an active connection multiplexing master process. When the -O option is specified, the ctl_cmd argument is interpreted - and passed to the master process. Valid commands are: M-bM-^@M-^\checkM-bM-^@M-^] - (check that the master process is running), M-bM-^@M-^\forwardM-bM-^@M-^] (request - forwardings without command execution), M-bM-^@M-^\cancelM-bM-^@M-^] (cancel - forwardings), M-bM-^@M-^\exitM-bM-^@M-^] (request the master to exit), and M-bM-^@M-^\stopM-bM-^@M-^] - (request the master to stop accepting further multiplexing - requests). + and passed to the master process. Valid commands are: "check" + (check that the master process is running), "forward" (request + forwardings without command execution), "cancel" (cancel forward- + ings), "exit" (request the master to exit), and "stop" (request + the master to stop accepting further multiplexing requests). -o option - Can be used to give options in the format used in the - configuration file. This is useful for specifying options for - which there is no separate command-line flag. For full details - of the options listed below, and their possible values, see - ssh_config(5). - - AddKeysToAgent - AddressFamily - BatchMode - BindAddress - CanonicalDomains - CanonicalizeFallbackLocal - CanonicalizeHostname - CanonicalizeMaxDots - CanonicalizePermittedCNAMEs - CASignatureAlgorithms - CertificateFile - CheckHostIP - Ciphers - ClearAllForwardings - Compression - ConnectionAttempts - ConnectTimeout - ControlMaster - ControlPath - ControlPersist - DynamicForward - EnableEscapeCommandline - EscapeChar - ExitOnForwardFailure - FingerprintHash - ForkAfterAuthentication - ForwardAgent - ForwardX11 - ForwardX11Timeout - ForwardX11Trusted - GatewayPorts - GlobalKnownHostsFile - GSSAPIAuthentication - GSSAPIDelegateCredentials - HashKnownHosts - Host - HostbasedAcceptedAlgorithms - HostbasedAuthentication - HostKeyAlgorithms - HostKeyAlias - Hostname - IdentitiesOnly - IdentityAgent - IdentityFile - IPQoS - KbdInteractiveAuthentication - KbdInteractiveDevices - KexAlgorithms - KnownHostsCommand - LocalCommand - LocalForward - LogLevel - MACs - Match - NoHostAuthenticationForLocalhost - NumberOfPasswordPrompts - PasswordAuthentication - PermitLocalCommand - PermitRemoteOpen - PKCS11Provider - Port - PreferredAuthentications - ProxyCommand - ProxyJump - ProxyUseFdpass - PubkeyAcceptedAlgorithms - PubkeyAuthentication - RekeyLimit - RemoteCommand - RemoteForward - RequestTTY - RequiredRSASize - SendEnv - ServerAliveInterval - ServerAliveCountMax - SessionType - SetEnv - StdinNull - StreamLocalBindMask - StreamLocalBindUnlink - StrictHostKeyChecking - TCPKeepAlive - Tunnel - TunnelDevice - UpdateHostKeys - User - UserKnownHostsFile - VerifyHostKeyDNS - VisualHostKey - XAuthLocation + Can be used to give options in the format used in the configura- + tion file. This is useful for specifying options for which there + is no separate command-line flag. For full details of the op- + tions and their possible values, see ssh_config(5). -P tag Specify a tag name that may be used to select configuration in ssh_config(5). Refer to the Tag and Match keywords in ssh_config(5) for more information. + -p port Port to connect to on the remote host. This can be specified on a per-host basis in the configuration file. -Q query_option - Queries for the algorithms supported by one of the following - features: cipher (supported symmetric ciphers), cipher-auth - (supported symmetric ciphers that support authenticated - encryption), help (supported query terms for use with the -Q - flag), mac (supported message integrity codes), kex (key exchange - algorithms), key (key types), key-ca-sign (valid CA signature - algorithms for certificates), key-cert (certificate key types), - key-plain (non-certificate key types), key-sig (all key types and - signature algorithms), protocol-version (supported SSH protocol - versions), and sig (supported signature algorithms). - Alternatively, any keyword from ssh_config(5) or sshd_config(5) - that takes an algorithm list may be used as an alias for the - corresponding query_option. + Queries for the algorithms supported by one of the following fea- + tures: cipher (supported symmetric ciphers), cipher-auth (sup- + ported symmetric ciphers that support authenticated encryption), + help (supported query terms for use with the -Q flag), mac (sup- + ported message integrity codes), compression (compression algo- + rithms), kex (key exchange algorithms), key (key types), key-alg + (public key algorithms), key-ca-sign (compatibility option), + key-cert (OpenSSH custom certificate key types), key-plain (non- + certificate key types), protocol-version (supported SSH protocol + versions), and sig (compatibility option). This option must be + specified last as other options may impact list of supported al- + gorithms. -q Quiet mode. Causes most warning and diagnostic messages to be suppressed. @@ -374,9 +302,8 @@ over the secure channel, and a connection is made from the local machine to either an explicit destination specified by host port hostport, or local_socket, or, if no explicit destination was - specified, ssh will act as a SOCKS 4/5 proxy and forward - connections to the destinations requested by the remote SOCKS - client. + specified, ssh will act as a SOCKS 4/5 proxy and forward connec- + tions to the destinations requested by the remote SOCKS client. Port forwardings can also be specified in the configuration file. Privileged ports can be forwarded only when logging in as root on @@ -384,28 +311,27 @@ the address in square brackets. By default, TCP listening sockets on the server will be bound to - the loopback interface only. This may be overridden by - specifying a bind_address. An empty bind_address, or the address - M-bM-^@M-^X*M-bM-^@M-^Y, indicates that the remote socket should listen on all - interfaces. Specifying a remote bind_address will only succeed - if the server's GatewayPorts option is enabled (see - sshd_config(5)). + the loopback interface only. This may be overridden by specify- + ing a bind_address. An empty bind_address, or the address '*', + indicates that the remote socket should listen on all interfaces. + Specifying a remote bind_address will only succeed if the + server's GatewayPorts option is enabled (see sshd_config(5)). - If the port argument is M-bM-^@M-^X0M-bM-^@M-^Y, the listen port will be dynamically + If the port argument is '0', the listen port will be dynamically allocated on the server and reported to the client at run time. When used together with -O forward, the allocated port will be printed to the standard output. -S ctl_path - Specifies the location of a control socket for connection - sharing, or the string M-bM-^@M-^\noneM-bM-^@M-^] to disable connection sharing. - Refer to the description of ControlPath and ControlMaster in + Specifies the location of a control socket for connection shar- + ing, or the string "none" to disable connection sharing. Refer + to the description of ControlPath and ControlMaster in ssh_config(5) for details. -s May be used to request invocation of a subsystem on the remote - system. Subsystems facilitate the use of SSH as a secure - transport for other applications (e.g. sftp(1)). The subsystem - is specified as the remote command. Refer to the description of + system. Subsystems facilitate the use of SSH as a secure trans- + port for other applications (e.g. sftp(1)). The subsystem is + specified as the remote command. Refer to the description of SessionType in ssh_config(5) for details. -T Disable pseudo-terminal allocation. @@ -418,29 +344,28 @@ -V Display the version number and exit. -v Verbose mode. Causes ssh to print debugging messages about its - progress. This is helpful in debugging connection, - authentication, and configuration problems. Multiple -v options - increase the verbosity. The maximum is 3. + progress. This is helpful in debugging connection, authentica- + tion, and configuration problems. Multiple -v options increase + the verbosity. The maximum is 4. -W host:port - Requests that standard input and output on the client be - forwarded to host on port over the secure channel. Implies -N, - -T, ExitOnForwardFailure and ClearAllForwardings, though these - can be overridden in the configuration file or using -o command - line options. + Requests that standard input and output on the client be for- + warded to host on port over the secure channel. Implies -N, -T, + ExitOnForwardFailure and ClearAllForwardings, though these can be + overridden in the configuration file or using -o command line op- + tions. -w local_tun[:remote_tun] - Requests tunnel device forwarding with the specified tun(4) - devices between the client (local_tun) and the server - (remote_tun). + Requests tunnel device forwarding with the specified tun(4) de- + vices between the client (local_tun) and the server (remote_tun). The devices may be specified by numerical ID or the keyword - M-bM-^@M-^\anyM-bM-^@M-^], which uses the next available tunnel device. If - remote_tun is not specified, it defaults to M-bM-^@M-^\anyM-bM-^@M-^]. See also the + "any", which uses the next available tunnel device. If + remote_tun is not specified, it defaults to "any". See also the Tunnel and TunnelDevice directives in ssh_config(5). If the Tunnel directive is unset, it will be set to the default - tunnel mode, which is M-bM-^@M-^\point-to-pointM-bM-^@M-^]. If a different Tunnel + tunnel mode, which is "point-to-point". If a different Tunnel forwarding mode it desired, then it should be specified before -w. @@ -453,30 +378,30 @@ through the forwarded connection. An attacker may then be able to perform activities such as keystroke monitoring. - For this reason, X11 forwarding is subjected to X11 SECURITY - extension restrictions by default. Refer to the ssh -Y option - and the ForwardX11Trusted directive in ssh_config(5) for more - information. + For this reason, X11 forwarding is subjected to X11 SECURITY ex- + tension restrictions by default. Refer to the ssh -Y option and + the ForwardX11Trusted directive in ssh_config(5) for more infor- + mation. -x Disables X11 forwarding. -Y Enables trusted X11 forwarding. Trusted X11 forwardings are not subjected to the X11 SECURITY extension controls. - -y Send log information using the syslog(3) system module. By - default this information is sent to stderr. + -y Send log information using the syslog(3) system module. By de- + fault this information is sent to stderr. - ssh may additionally obtain configuration data from a per-user - configuration file and a system-wide configuration file. The file format - and configuration options are described in ssh_config(5). + ssh may additionally obtain configuration data from a per-user configura- + tion file and a system-wide configuration file. The file format and con- + figuration options are described in ssh_config(5). AUTHENTICATION - The OpenSSH SSH client supports SSH protocol 2. + The SecSH client supports SSH protocol 2. - The methods available for authentication are: GSSAPI-based - authentication, host-based authentication, public key authentication, - keyboard-interactive authentication, and password authentication. - Authentication methods are tried in the order specified above, though + The methods available for authentication are: GSSAPI-based authentica- + tion, host-based authentication, public key authentication, keyboard-in- + teractive authentication, and password authentication. Authentication + methods are tried in the order specified above, though PreferredAuthentications can be used to change the default order. Host-based authentication works as follows: If the machine the user logs @@ -486,54 +411,59 @@ directory on the remote machine and contain a line containing the name of the client machine and the name of the user on that machine, the user is considered for login. Additionally, the server must be able to verify - the client's host key (see the description of /etc/ssh/ssh_known_hosts - and ~/.ssh/known_hosts, below) for login to be permitted. This - authentication method closes security holes due to IP spoofing, DNS - spoofing, and routing spoofing. [Note to the administrator: - /etc/hosts.equiv, ~/.rhosts, and the rlogin/rsh protocol in general, are - inherently insecure and should be disabled if security is desired.] - - Public key authentication works as follows: The scheme is based on - public-key cryptography, using cryptosystems where encryption and - decryption are done using separate keys, and it is unfeasible to derive - the decryption key from the encryption key. The idea is that each user - creates a public/private key pair for authentication purposes. The - server knows the public key, and only the user knows the private key. - ssh implements public key authentication protocol automatically, using - one of the DSA, ECDSA, Ed25519 or RSA algorithms. The HISTORY section of - ssl(8) contains a brief discussion of the DSA and RSA algorithms. - - The file ~/.ssh/authorized_keys lists the public keys that are permitted - for logging in. When the user logs in, the ssh program tells the server - which key pair it would like to use for authentication. The client - proves that it has access to the private key and the server checks that - the corresponding public key is authorized to accept the account. - - The server may inform the client of errors that prevented public key - authentication from succeeding after authentication completes using a - different method. These may be viewed by increasing the LogLevel to - DEBUG or higher (e.g. by using the -v flag). + the client's host key or X.509 certificate (see the description of + /etc/ssh/ssh_known_hosts and ~/.ssh/known_hosts, below) for login to be + permitted. This authentication method closes security holes due to IP + spoofing, DNS spoofing, and routing spoofing. [Note to the administra- + tor: /etc/hosts.equiv, ~/.rhosts, and the rlogin/rsh protocol in general, + are inherently insecure and should be disabled if security is desired.] + + Public key authentication works as follows: The scheme is based on pub- + lic-key cryptography or infrastructure (PKI), using cryptosystems where + encryption and decryption are done using separate keys, and it is unfea- + sible to derive the decryption key from the encryption key. The idea is + that each user creates a public/private key pair for authentication pur- + poses. The server knows the public key or X.509 certificate, and only + the user knows the private key. ssh implements public key authentication + protocol automatically, using one of the DSA, ECDSA, Ed25519 or RSA algo- + rithms or X.509 certificates. The HISTORY section of ssl(8) contains a + brief discussion of the DSA and RSA algorithms. + + The file ~/.ssh/authorized_keys lists the public keys or X.509 certifi- + cates that are permitted for logging in. When the user logs in, the ssh + program tells the server which key pair or X.509 certificate it would + like to use for authentication. The client proves that it has access to + the private key and the server checks that the corresponding public key + or X.509 certificate is authorized to accept the account. + + The server may inform the client of errors that prevented public key au- + thentication from succeeding after authentication completes using a dif- + ferent method. These may be viewed by increasing the LogLevel to DEBUG + or higher (e.g. by using the -v flag). The user creates their key pair by running ssh-keygen(1). This stores the private key in ~/.ssh/id_dsa (DSA), ~/.ssh/id_ecdsa (ECDSA), - ~/.ssh/id_ecdsa_sk (authenticator-hosted ECDSA), ~/.ssh/id_ed25519 - (Ed25519), ~/.ssh/id_ed25519_sk (authenticator-hosted Ed25519), or - ~/.ssh/id_rsa (RSA) and stores the public key in ~/.ssh/id_dsa.pub (DSA), - ~/.ssh/id_ecdsa.pub (ECDSA), ~/.ssh/id_ecdsa_sk.pub (authenticator-hosted - ECDSA), ~/.ssh/id_ed25519.pub (Ed25519), ~/.ssh/id_ed25519_sk.pub - (authenticator-hosted Ed25519), or ~/.ssh/id_rsa.pub (RSA) in the user's - home directory. The user should then copy the public key to - ~/.ssh/authorized_keys in their home directory on the remote machine. - The authorized_keys file corresponds to the conventional ~/.rhosts file, - and has one key per line, though the lines can be very long. After this, - the user can log in without giving the password. + ~/.ssh/id_ed25519 (Ed25519), or ~/.ssh/id_rsa (RSA) and stores the public + key in ~/.ssh/id_dsa.pub (DSA), ~/.ssh/id_ecdsa.pub (ECDSA), + ~/.ssh/id_ed25519.pub (Ed25519), or ~/.ssh/id_rsa.pub (RSA) in the user's + home directory. For RSA, ECDSA, Ed25519 or DSA identity files may con- + tain private key, X.509 certificate that match it and extra X.509 cer- + tificates. In this case *.pub file must contain certificate that match + key. The user should then copy the public key or X.509 certificate to + ~/.ssh/authorized_keys in their home directory on the remote machine. In + case with X.509 certificates user can use "new style" : instead to add + content of file to authorized_keys user can write certificate + "Distinguished Name" - see sshd(8) manual page. The authorized_keys file + corresponds to the conventional ~/.rhosts file, and has one key or X.509 + certificate per line, though the lines can be very long. After this, the + user can log in without giving the password. A variation on public key authentication is available in the form of - certificate authentication: instead of a set of public/private keys, - signed certificates are used. This has the advantage that a single - trusted certification authority can be used in place of many - public/private keys. See the CERTIFICATES section of ssh-keygen(1) for - more information. + OpenSSH custom certificate authentication: instead of a set of pub- + lic/private keys, signed certificates are used. This has the advantage + that a single trusted OpenSSH custom certification authority can be used + in place of many public/private keys. See the CERTIFICATES section of + ssh-keygen(1) for more information. The most convenient way to use public key or certificate authentication may be with an authentication agent. See ssh-agent(1) and (optionally) @@ -541,30 +471,32 @@ Keyboard-interactive authentication works as follows: The server sends an arbitrary "challenge" text and prompts for a response, possibly multiple - times. Examples of keyboard-interactive authentication include BSD - Authentication (see login.conf(5)) and PAM (some non-OpenBSD systems). + times. Examples of keyboard-interactive authentication include BSD Au- + thentication (see login.conf(5)) and PAM (some non-OpenBSD systems). Finally, if other authentication methods fail, ssh prompts the user for a password. The password is sent to the remote host for checking; however, since all communications are encrypted, the password cannot be seen by someone listening on the network. - ssh automatically maintains and checks a database containing - identification for all hosts it has ever been used with. Host keys are - stored in ~/.ssh/known_hosts in the user's home directory. Additionally, - the file /etc/ssh/ssh_known_hosts is automatically checked for known - hosts. Any new hosts are automatically added to the user's file. If a - host's identification ever changes, ssh warns about this and disables - password authentication to prevent server spoofing or man-in-the-middle - attacks, which could otherwise be used to circumvent the encryption. The + ssh automatically maintains and checks a database containing identifica- + tion for all hosts it has ever been used with. Host keys are stored in + ~/.ssh/known_hosts in the user's home directory. Additionally, the file + /etc/ssh/ssh_known_hosts is automatically checked for known hosts. If + host key is a X.509 certificate line may contain certificate + "Distinguished Name" instead base64 encoded representation. Any new + hosts are automatically added to the user's file. If a host's identifi- + cation ever changes, ssh warns about this and disables password authenti- + cation to prevent server spoofing or man-in-the-middle attacks, which + could otherwise be used to circumvent the encryption. The StrictHostKeyChecking option can be used to control logins to machines whose host key is not known or has changed. - When the user's identity has been accepted by the server, the server - either executes the given command in a non-interactive session or, if no + When the user's identity has been accepted by the server, the server ei- + ther executes the given command in a non-interactive session or, if no command has been specified, logs into the machine and gives the user a - normal shell as an interactive session. All communication with the - remote command or shell will be automatically encrypted. + normal shell as an interactive session. All communication with the re- + mote command or shell will be automatically encrypted. If an interactive session is requested, ssh by default will only request a pseudo-terminal (pty) for interactive sessions when the client has one. @@ -575,23 +507,23 @@ If no pseudo-terminal has been allocated, the session is transparent and can be used to reliably transfer binary data. On most systems, setting - the escape character to M-bM-^@M-^\noneM-bM-^@M-^] will also make the session transparent + the escape character to "none" will also make the session transparent even if a tty is used. The session terminates when the command or shell on the remote machine exits and all X11 and TCP connections have been closed. ESCAPE CHARACTERS - When a pseudo-terminal has been requested, ssh supports a number of - functions through the use of an escape character. + When a pseudo-terminal has been requested, ssh supports a number of func- + tions through the use of an escape character. A single tilde character can be sent as ~~ or by following the tilde by a character other than those described below. The escape character must - always follow a newline to be interpreted as special. The escape - character can be changed in configuration files using the EscapeChar - configuration directive or on the command line by the -e option. + always follow a newline to be interpreted as special. The escape charac- + ter can be changed in configuration files using the EscapeChar configura- + tion directive or on the command line by the -e option. - The supported escapes (assuming the default M-bM-^@M-^X~M-bM-^@M-^Y) are: + The supported escapes (assuming the default '~') are: ~. Disconnect. @@ -604,20 +536,20 @@ ~? Display a list of escape characters. - ~B Send a BREAK to the remote system (only useful if the peer - supports it). + ~B Send a BREAK to the remote system (only useful if the peer sup- + ports it). ~C Open command line. Currently this allows the addition of port forwardings using the -L, -R and -D options (see above). It also allows the cancellation of existing port-forwardings with - -KL[bind_address:]port for local, -KR[bind_address:]port for - remote and -KD[bind_address:]port for dynamic port-forwardings. + -KL[bind_address:]port for local, -KR[bind_address:]port for re- + mote and -KD[bind_address:]port for dynamic port-forwardings. !command allows the user to execute a local command if the PermitLocalCommand option is enabled in ssh_config(5). Basic help is available, using the -h option. - ~R Request rekeying of the connection (only useful if the peer - supports it). + ~R Request rekeying of the connection (only useful if the peer sup- + ports it). ~V Decrease the verbosity (LogLevel) when errors are being written to stderr. @@ -632,39 +564,38 @@ server; another is going through firewalls. In the example below, we look at encrypting communication for an IRC - client, even though the IRC server it connects to does not directly - support encrypted communication. This works as follows: the user - connects to the remote host using ssh, specifying the ports to be used to - forward the connection. After that it is possible to start the program - locally, and ssh will encrypt and forward the connection to the remote - server. + client, even though the IRC server it connects to does not directly sup- + port encrypted communication. This works as follows: the user connects + to the remote host using ssh, specifying the ports to be used to forward + the connection. After that it is possible to start the program locally, + and ssh will encrypt and forward the connection to the remote server. The following example tunnels an IRC session from the client to an IRC - server at M-bM-^@M-^\server.example.comM-bM-^@M-^], joining channel M-bM-^@M-^\#usersM-bM-^@M-^], nickname - M-bM-^@M-^\pinkyM-bM-^@M-^], using the standard IRC port, 6667: + server at "server.example.com", joining channel "#users", nickname + "pinky", using the standard IRC port, 6667: $ ssh -f -L 6667:localhost:6667 server.example.com sleep 10 $ irc -c '#users' pinky IRC/127.0.0.1 - The -f option backgrounds ssh and the remote command M-bM-^@M-^\sleep 10M-bM-^@M-^] is - specified to allow an amount of time (10 seconds, in the example) to - start the program which is going to use the tunnel. If no connections - are made within the time specified, ssh will exit. + The -f option backgrounds ssh and the remote command "sleep 10" is speci- + fied to allow an amount of time (10 seconds, in the example) to start the + program which is going to use the tunnel. If no connections are made + within the time specified, ssh will exit. X11 FORWARDING - If the ForwardX11 variable is set to M-bM-^@M-^\yesM-bM-^@M-^] (or see the description of the - -X, -x, and -Y options above) and the user is using X11 (the DISPLAY - environment variable is set), the connection to the X11 display is - automatically forwarded to the remote side in such a way that any X11 - programs started from the shell (or command) will go through the - encrypted channel, and the connection to the real X server will be made - from the local machine. The user should not manually set DISPLAY. - Forwarding of X11 connections can be configured on the command line or in - configuration files. + If the ForwardX11 variable is set to "yes" (or see the description of the + -X, -x, and -Y options above) and the user is using X11 (the DISPLAY en- + vironment variable is set), the connection to the X11 display is automat- + ically forwarded to the remote side in such a way that any X11 programs + started from the shell (or command) will go through the encrypted chan- + nel, and the connection to the real X server will be made from the local + machine. The user should not manually set DISPLAY. Forwarding of X11 + connections can be configured on the command line or in configuration + files. The DISPLAY value set by ssh will point to the server machine, but with a display number greater than zero. This is normal, and happens because - ssh creates a M-bM-^@M-^\proxyM-bM-^@M-^] X server on the server machine for forwarding the + ssh creates a "proxy" X server on the server machine for forwarding the connections over the encrypted channel. ssh will also automatically set up Xauthority data on the server machine. @@ -674,10 +605,10 @@ is opened. The real authentication cookie is never sent to the server machine (and no cookies are sent in the plain). - If the ForwardAgent variable is set to M-bM-^@M-^\yesM-bM-^@M-^] (or see the description of + If the ForwardAgent variable is set to "yes" (or see the description of the -A and -a options above) and the user is using an authentication - agent, the connection to the agent is automatically forwarded to the - remote side. + agent, the connection to the agent is automatically forwarded to the re- + mote side. VERIFYING HOST KEYS When connecting to a server for the first time, a fingerprint of the @@ -692,9 +623,9 @@ are available, the ssh-keygen(1) -E option may be used to downgrade the fingerprint algorithm to match. - Because of the difficulty of comparing host keys just by looking at - fingerprint strings, there is also support to compare host keys visually, - using random art. By setting the VisualHostKey option to M-bM-^@M-^\yesM-bM-^@M-^], a small + Because of the difficulty of comparing host keys just by looking at fin- + gerprint strings, there is also support to compare host keys visually, + using random art. By setting the VisualHostKey option to "yes", a small ASCII graphic gets displayed on every login to a server, no matter if the session itself is interactive or not. By learning the pattern a known server produces, a user can easily find out that the host key has changed @@ -709,13 +640,14 @@ $ ssh-keygen -lv -f ~/.ssh/known_hosts If the fingerprint is unknown, an alternative method of verification is - available: SSH fingerprints verified by DNS. An additional resource - record (RR), SSHFP, is added to a zonefile and the connecting client is - able to match the fingerprint with that of the key presented. + available: SSH fingerprints or X.509 certificates verified by DNS. An + additional resource record (RR), SSHFP or CERT, is added to a zonefile + and the connecting client is able to match the fingerprint or X.509 cer- + tificate with that of the key presented. In this example, we are connecting a client to a server, - M-bM-^@M-^\host.example.comM-bM-^@M-^]. The SSHFP resource records should first be added to - the zonefile for host.example.com: + "host.example.com". The SSHFP or CERT resource records should first be + added to the zonefile for host.example.com: $ ssh-keygen -r host.example.com. @@ -724,6 +656,10 @@ $ dig -t SSHFP host.example.com + To check that the zone is answering X.509 certificate queries: + + $ dig -t CERT host.example.com + Finally the client connects: $ ssh -o "VerifyHostKeyDNS ask" host.example.com @@ -731,19 +667,23 @@ Matching host key fingerprint found in DNS. Are you sure you want to continue connecting (yes/no)? + When host key is a X.509 certificate "Distinguished Name" is displayed + after fingerprint. Note that host X.509 certificate always is verifified + and validated. + See the VerifyHostKeyDNS option in ssh_config(5) for more information. SSH-BASED VIRTUAL PRIVATE NETWORKS ssh contains support for Virtual Private Network (VPN) tunnelling using - the tun(4) network pseudo-device, allowing two networks to be joined - securely. The sshd_config(5) configuration option PermitTunnel controls - whether the server supports this, and at what level (layer 2 or 3 - traffic). - - The following example would connect client network 10.0.50.0/24 with - remote network 10.0.99.0/24 using a point-to-point connection from - 10.1.1.1 to 10.1.1.2, provided that the SSH server running on the gateway - to the remote network, at 192.168.1.15, allows it. + the tun(4) network pseudo-device, allowing two networks to be joined se- + curely. The sshd_config(5) configuration option PermitTunnel controls + whether the server supports this, and at what level (layer 2 or 3 traf- + fic). + + The following example would connect client network 10.0.50.0/24 with re- + mote network 10.0.99.0/24 using a point-to-point connection from 10.1.1.1 + to 10.1.1.2, provided that the SSH server running on the gateway to the + remote network, at 192.168.1.15, allows it. On the client: @@ -758,101 +698,108 @@ Client access may be more finely tuned via the /root/.ssh/authorized_keys file (see below) and the PermitRootLogin server option. The following - entry would permit connections on tun(4) device 1 from user M-bM-^@M-^\janeM-bM-^@M-^] and on - tun device 2 from user M-bM-^@M-^\johnM-bM-^@M-^], if PermitRootLogin is set to - M-bM-^@M-^\forced-commands-onlyM-bM-^@M-^]: + entry would permit connections on tun(4) device 1 from user "jane" and on + tun device 2 from user "john", if PermitRootLogin is set to + "forced-commands-only": tunnel="1",command="sh /etc/netstart tun1" ssh-rsa ... jane tunnel="2",command="sh /etc/netstart tun2" ssh-rsa ... john Since an SSH-based setup entails a fair amount of overhead, it may be - more suited to temporary setups, such as for wireless VPNs. More - permanent VPNs are better provided by tools such as ipsecctl(8) and + more suited to temporary setups, such as for wireless VPNs. More perma- + nent VPNs are better provided by tools such as ipsecctl(8) and isakmpd(8). ENVIRONMENT - ssh will normally set the following environment variables: - - DISPLAY The DISPLAY variable indicates the location of the - X11 server. It is automatically set by ssh to - point to a value of the form M-bM-^@M-^\hostname:nM-bM-^@M-^], where - M-bM-^@M-^\hostnameM-bM-^@M-^] indicates the host where the shell runs, - and M-bM-^@M-^XnM-bM-^@M-^Y is an integer M-bM-^IM-% 1. ssh uses this special - value to forward X11 connections over the secure - channel. The user should normally not set DISPLAY - explicitly, as that will render the X11 connection - insecure (and will require the user to manually - copy any required authorization cookies). - - HOME Set to the path of the user's home directory. - - LOGNAME Synonym for USER; set for compatibility with - systems that use this variable. - - MAIL Set to the path of the user's mailbox. - - PATH Set to the default PATH, as specified when - compiling ssh. - - SSH_ASKPASS If ssh needs a passphrase, it will read the - passphrase from the current terminal if it was run - from a terminal. If ssh does not have a terminal - associated with it but DISPLAY and SSH_ASKPASS are - set, it will execute the program specified by - SSH_ASKPASS and open an X11 window to read the - passphrase. This is particularly useful when - calling ssh from a .xsession or related script. - (Note that on some machines it may be necessary to - redirect the input from /dev/null to make this - work.) - - SSH_ASKPASS_REQUIRE Allows further control over the use of an askpass - program. If this variable is set to M-bM-^@M-^\neverM-bM-^@M-^] then - ssh will never attempt to use one. If it is set to - M-bM-^@M-^\preferM-bM-^@M-^], then ssh will prefer to use the askpass - program instead of the TTY when requesting - passwords. Finally, if the variable is set to - M-bM-^@M-^\forceM-bM-^@M-^], then the askpass program will be used for - all passphrase input regardless of whether DISPLAY - is set. - - SSH_AUTH_SOCK Identifies the path of a UNIX-domain socket used to - communicate with the agent. - - SSH_CONNECTION Identifies the client and server ends of the - connection. The variable contains four space- - separated values: client IP address, client port - number, server IP address, and server port number. - - SSH_ORIGINAL_COMMAND This variable contains the original command line if - a forced command is executed. It can be used to - extract the original arguments. - - SSH_TTY This is set to the name of the tty (path to the - device) associated with the current shell or - command. If the current session has no tty, this - variable is not set. - - SSH_TUNNEL Optionally set by sshd(8) to contain the interface - names assigned if tunnel forwarding was requested - by the client. - - SSH_USER_AUTH Optionally set by sshd(8), this variable may - contain a pathname to a file that lists the - authentication methods successfully used when the - session was established, including any public keys - that were used. - - TZ This variable is set to indicate the present time - zone if it was set when the daemon was started - (i.e. the daemon passes the value on to new - connections). - - USER Set to the name of the user logging in. - - Additionally, ssh reads ~/.ssh/environment, and adds lines of the format - M-bM-^@M-^\VARNAME=valueM-bM-^@M-^] to the environment if the file exists and users are - allowed to change their environment. For more information, see the + SSH_ASKPASS + If ssh needs a passphrase, it will read the passphrase from the + current terminal if it was run from a terminal. If ssh does not + have a terminal associated with it but DISPLAY and SSH_ASKPASS + are set, it will execute the program specified by SSH_ASKPASS + that may open a X11 window to read the passphrase. For keys from + "engine" or "store" SSH_ASKPASS is preferred over associated ter- + minal. Note if SSH_ASKPASS is not set will be executed program + ssh-askpass located in "libexec" directory. This is particularly + useful when calling ssh from a .xsession or related script. + + Remark: On Android DISPLAY is ignored. + + SSH_ASKPASS_REQUIRE + Allows further control over the use of an askpass program. If + this variable is set to "never" then ssh will never attempt to + use one. If it is set to "prefer", then ssh will prefer to use + the askpass program instead of the TTY when requesting passwords. + Finally, if the variable is set to "force", then the askpass pro- + gram will be used for all passphrase input regardless of whether + DISPLAY is set. + + SSH_AUTH_SOCK + Identifies the path of a UNIX-domain socket used to communicate + with the agent. + + SSH_ENGINE_CONF + Overrides default location of engine configuration file. + + sshd(8) will normally set the following environment variables: + + DISPLAY + The DISPLAY variable indicates the location of the X11 server. + It is automatically set by ssh to point to a value of the form + "hostname:n", where "hostname" indicates the host where the shell + runs, and 'n' is an integer >= 1. ssh uses this special value to + forward X11 connections over the secure channel. The user should + normally not set DISPLAY explicitly, as that will render the X11 + connection insecure (and will require the user to manually copy + any required authorization cookies). + + HOME Set to the path of the user's home directory. + + LOGNAME + Synonym for USER; set for compatibility with systems that use + this variable. + + MAIL Set to the path of the user's mailbox. + + PATH Set to the default PATH, as specified when compiling ssh. + + SSH_AUTH_SOCK + Identifies the path of a UNIX-domain socket used to communicate + with the forwarded agent. + + SSH_CONNECTION + Identifies the client and server ends of the connection. The + variable contains four space-separated values: client IP address, + client port number, server IP address, and server port number. + + SSH_ORIGINAL_COMMAND + This variable contains the original command line if a forced com- + mand is executed. It can be used to extract the original argu- + ments. + + SSH_TTY + This is set to the name of the tty (path to the device) associ- + ated with the current shell or command. If the current session + has no tty, this variable is not set. + + SSH_TUNNEL + Optionally set by sshd(8) to contain the interface names assigned + if tunnel forwarding was requested by the client. + + SSH_USER_AUTH + Optionally set by sshd(8), this variable may contain a pathname + to a file that lists the authentication methods successfully used + when the session was established, including any public keys that + were used. + + TZ This variable is set to indicate the present time zone if it was + set when the daemon was started (i.e. the daemon passes the value + on to new connections). + + USER Set to the name of the user logging in. + + Additionally, sshd(8) reads ~/.ssh/environment, and adds lines of the + format "VARNAME=value" to the environment if the file exists and users + are allowed to change their environment. For more information, see the PermitUserEnvironment option in sshd_config(5). FILES @@ -871,18 +818,27 @@ rlogin/rsh. ~/.ssh/ - This directory is the default location for all user-specific - configuration and authentication information. There is no - general requirement to keep the entire contents of this directory - secret, but the recommended permissions are read/write/execute - for the user, and not accessible by others. + This directory is the default location for all user-specific con- + figuration and authentication information. There is no general + requirement to keep the entire contents of this directory secret, + but the recommended permissions are read/write/execute for the + user, and not accessible by others. ~/.ssh/authorized_keys - Lists the public keys (DSA, ECDSA, Ed25519, RSA) that can be used - for logging in as this user. The format of this file is - described in the sshd(8) manual page. This file is not highly - sensitive, but the recommended permissions are read/write for the - user, and not accessible by others. + Lists the public keys (DSA, ECDSA, Ed25519, RSA) or X.509 cer- + tificates that can be used for logging in as this user. The for- + mat of this file is described in the sshd(8) manual page. This + file is not highly sensitive, but the recommended permissions are + read/write for the user, and not accessible by others. + + ~/.ssh/ca/ca-bundle.crt + ~/.ssh/ca/ca-bundle.crl + Part of user "X.509 store". Same as systemwide files below. + + ~/.ssh/ca/crt + ~/.ssh/ca/crl + Part of user "X.509 store". Same as systemwide directories be- + low. ~/.ssh/config This is the per-user configuration file. The file format and @@ -896,32 +852,37 @@ ~/.ssh/id_dsa ~/.ssh/id_ecdsa - ~/.ssh/id_ecdsa_sk ~/.ssh/id_ed25519 - ~/.ssh/id_ed25519_sk ~/.ssh/id_rsa Contains the private key for authentication. These files contain - sensitive data and should be readable by the user but not - accessible by others (read/write/execute). ssh will simply - ignore a private key file if it is accessible by others. It is - possible to specify a passphrase when generating the key which - will be used to encrypt the sensitive part of this file using - AES-128. + sensitive data and should be readable by the user but not acces- + sible by others (read/write/execute). ssh will simply ignore a + private key file if it is accessible by others. It is possible + to specify a passphrase when generating the key which will be + used to encrypt the sensitive part of this file using 256-bit + AES. + + For RSA, ECDSA, Ed25519 or DSA identity file (private key) may + contain X.509 certificate that match key. In addition file may + contain extra X.509 certificates. Extra certificates along with + certificates from X.509 store are used to build chain of certifi- + cates leading to a trusted certificate authority if required by + public key algorithm format. ~/.ssh/id_dsa.pub ~/.ssh/id_ecdsa.pub - ~/.ssh/id_ecdsa_sk.pub ~/.ssh/id_ed25519.pub - ~/.ssh/id_ed25519_sk.pub ~/.ssh/id_rsa.pub - Contains the public key for authentication. These files are not - sensitive and can (but need not) be readable by anyone. + Contains the public key for authentication. Note if an identity + contain private key and X.509 certificate, file must contain that + certificate. These files are not sensitive and can (but need + not) be readable by anyone. ~/.ssh/known_hosts - Contains a list of host keys for all hosts the user has logged - into that are not already in the systemwide list of known host - keys. See sshd(8) for further details of the format of this - file. + Contains a list of host keys or X.509 certificates for all hosts + the user has logged into that are not already in the systemwide + list of known host keys. See sshd(8) for further details of the + format of this file. ~/.ssh/rc Commands in this file are executed by ssh when the user logs in, @@ -933,10 +894,28 @@ should only be writable by root. /etc/shosts.equiv - This file is used in exactly the same way as hosts.equiv, but - allows host-based authentication without permitting login with + This file is used in exactly the same way as hosts.equiv, but al- + lows host-based authentication without permitting login with rlogin/rsh. + /etc/ssh/ca/ca-bundle.crt + /etc/ssh/ca/ca-bundle.crl + Part of systemwide "X.509 store". The first file contain multi- + ple certificates and the second "Certificate Revocation List" + (CRLs) of X.509 certificate signers in PEM format concatenated + together. Used in verification and validation of server host + certificate. + + /etc/ssh/ca/crt + /etc/ssh/ca/crl + Part of systemwide "X.509 store". "Hash dirs" with certificates, + the first directory or CLRs, the second of certificate signers. + Each certificate should be stored in separate file with name + [HASH].[NUMBER] or [HASH].r[NUMBER] for the CRL, where [HASH] is + certificate or CRL hash value and [NUMBER] is an integer starting + from zero. Used in verification and validation of server host + certificate. + /etc/ssh/ssh_config Systemwide configuration file. The file format and configuration options are described in ssh_config(5). @@ -947,13 +926,23 @@ /etc/ssh/ssh_host_ed25519_key /etc/ssh/ssh_host_rsa_key These files contain the private parts of the host keys and are - used for host-based authentication. + used for host-based authentication. For RSA, ECDSA, Ed25519 or + DSA keys files may contain X.509 certificate that match it. In + addition file may contain extra X.509 certificates. Extra cer- + tificates along with certificates from X.509 store are used to + build chain of certificates leading to a trusted certificate au- + thority if required by host-based key algorithm format. If a + X.509 certificate is used as host key for hostbased authentica- + tion that certificate must have client purpose too or server con- + figuration must permit connection without client purpose. For al- + lowed client certificate purposes see ssh_config(5). /etc/ssh/ssh_known_hosts - Systemwide list of known host keys. This file should be prepared - by the system administrator to contain the public host keys of - all machines in the organization. It should be world-readable. - See sshd(8) for further details of the format of this file. + Systemwide list of known host keys or X.509 certificates. This + file should be prepared by the system administrator to contain + the public host keys or X.509 certificates of all machines in the + organization. It should be world-readable. See sshd(8) for fur- + ther details of the format of this file. /etc/ssh/sshrc Commands in this file are executed by ssh when the user logs in, @@ -965,58 +954,83 @@ error occurred. SEE ALSO - scp(1), sftp(1), ssh-add(1), ssh-agent(1), ssh-keygen(1), ssh-keyscan(1), - tun(4), ssh_config(5), ssh-keysign(8), sshd(8) + scp(1), sftp(1), ssh-add(1), ssh-agent(1), ssh-askpass(1), ssh-keygen(1), + ssh-keyscan(1), tun(4), ssh_config(5), ssh-keysign(8), sshd(8) + +CONFORMING TO + 1. T. Ylonen, T. Kivinen, M. Saarinen, T. Rinne, and S. Lehtinen, SSH + Transport Layer Protocol, 31 January 2002, draft-ietf-secsh- + transport-12.txt. + + 2. S. Lehtinen and C. Lonvick, The Secure Shell (SSH) Protocol Assigned + Numbers, RFC 4250, January 2006. + + 3. T. Ylonen and C. Lonvick, The Secure Shell (SSH) Protocol + Architecture, RFC 4251, January 2006. + + 4. T. Ylonen and C. Lonvick, The Secure Shell (SSH) Authentication + Protocol, RFC 4252, January 2006. + + 5. T. Ylonen and C. Lonvick, The Secure Shell (SSH) Transport Layer + Protocol, RFC 4253, January 2006. + + 6. T. Ylonen and C. Lonvick, The Secure Shell (SSH) Connection + Protocol, RFC 4254, January 2006. + + 7. J. Schlyter and W. Griffin, Using DNS to Securely Publish Secure + Shell (SSH) Key Fingerprints, RFC 4255, January 2006. -STANDARDS - S. Lehtinen and C. Lonvick, The Secure Shell (SSH) Protocol Assigned - Numbers, RFC 4250, January 2006. + 8. F. Cusack and M. Forssen, Generic Message Exchange Authentication + for the Secure Shell Protocol (SSH), RFC 4256, January 2006. - T. Ylonen and C. Lonvick, The Secure Shell (SSH) Protocol Architecture, - RFC 4251, January 2006. + 9. J. Galbraith and P. Remaker, The Secure Shell (SSH) Session Channel + Break Extension, RFC 4335, January 2006. - T. Ylonen and C. Lonvick, The Secure Shell (SSH) Authentication Protocol, - RFC 4252, January 2006. + 10. M. Bellare, T. Kohno, and C. Namprempre, The Secure Shell (SSH) + Transport Layer Encryption Modes, RFC 4344, January 2006. - T. Ylonen and C. Lonvick, The Secure Shell (SSH) Transport Layer - Protocol, RFC 4253, January 2006. + 11. B. Harris, Improved Arcfour Modes for the Secure Shell (SSH) + Transport Layer Protocol, RFC 4345, January 2006. - T. Ylonen and C. Lonvick, The Secure Shell (SSH) Connection Protocol, RFC - 4254, January 2006. + 12. M. Friedl, N. Provos, and W. Simpson, Diffie-Hellman Group Exchange + for the Secure Shell (SSH) Transport Layer Protocol, RFC 4419, March + 2006. - J. Schlyter and W. Griffin, Using DNS to Securely Publish Secure Shell - (SSH) Key Fingerprints, RFC 4255, January 2006. + 13. J. Galbraith and R. Thayer, The Secure Shell (SSH) Public Key File + Format, RFC 4716, November 2006. - F. Cusack and M. Forssen, Generic Message Exchange Authentication for the - Secure Shell Protocol (SSH), RFC 4256, January 2006. + 14. D. Stebila and J. Green, Elliptic Curve Algorithm Integration in the + Secure Shell Transport Layer, RFC 5656, December 2009. - J. Galbraith and P. Remaker, The Secure Shell (SSH) Session Channel Break - Extension, RFC 4335, January 2006. + 15. A. Perrig and D. Song, Hash Visualization: a New Technique to + improve Real-World Security, 1999, International Workshop on + Cryptographic Techniques and E-Commerce (CrypTEC '99). - M. Bellare, T. Kohno, and C. Namprempre, The Secure Shell (SSH) Transport - Layer Encryption Modes, RFC 4344, January 2006. + 16. K. Igoe and D. Stebila, X.509v3 Certificates for Secure Shell + Authentication, RFC 6187, March 2011. - B. Harris, Improved Arcfour Modes for the Secure Shell (SSH) Transport - Layer Protocol, RFC 4345, January 2006. + 17. S. Josefsson and I. Liusvaara, Edwards-Curve Digital Signature + Algorithm (EdDSA), RFC 8032, January 2017. - M. Friedl, N. Provos, and W. Simpson, Diffie-Hellman Group Exchange for - the Secure Shell (SSH) Transport Layer Protocol, RFC 4419, March 2006. + 18. D. Bider, Extension Negotiation in the Secure Shell (SSH) Protocol, + RFC 8308, March 2018. - J. Galbraith and R. Thayer, The Secure Shell (SSH) Public Key File - Format, RFC 4716, November 2006. + 19. D. Bider, Use of RSA Keys with SHA-256 and SHA-512 in the Secure + Shell (SSH) Protocol, RFC 8332, March 2018. - D. Stebila and J. Green, Elliptic Curve Algorithm Integration in the - Secure Shell Transport Layer, RFC 5656, December 2009. + 20. A. Adamantiadis, S. Josefsson, and M. Baushke, Secure Shell (SSH) + Key Exchange Method Using Curve25519 and Curve448, RFC 8731, + February 2020. - A. Perrig and D. Song, Hash Visualization: a New Technique to improve - Real-World Security, 1999, International Workshop on Cryptographic - Techniques and E-Commerce (CrypTEC '99). + 21. B. Harris and L. Velvindron, Ed25519 and Ed448 Public Key Algorithms + for the Secure Shell (SSH) Protocol, RFC 8709, February 2020. AUTHORS - OpenSSH is a derivative of the original and free ssh 1.2.12 release by + PKIX-SSH is a derivative of the original and free ssh 1.2.12 release by Tatu Ylonen. Aaron Campbell, Bob Beck, Markus Friedl, Niels Provos, Theo - de Raadt and Dug Song removed many bugs, re-added newer features and - created OpenSSH. Markus Friedl contributed the support for SSH protocol - versions 1.5 and 2.0. + de Raadt and Dug Song removed many bugs, re-added newer features and cre- + ated OpenSSH. Markus Friedl contributed the support for SSH protocol + versions 1.5 and 2.0. Roumen Petrov contributed support for X.509 cer- + tificates. -OpenBSD 7.3 July 23, 2023 OpenBSD 7.3 +BSD 23 July 2023 BSD diff -ruN openssh-9.4p1/ssh.1 openssh-9.4p1+x509-14.2.1/ssh.1 --- openssh-9.4p1/ssh.1 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/ssh.1 2023-08-20 10:07:00.000000000 +0300 @@ -1,3 +1,11 @@ +.\" Implement .Dd with the Mdocdate RCS keyword +.rn Dd xD +.de Dd +.ie \\$1$Mdocdate: \{\ +. xD \\$3 \\$2 \\$4 +.\} +.el .xD \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 +.. .\" .\" Author: Tatu Ylonen .\" Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -12,6 +20,7 @@ .\" Copyright (c) 1999,2000 Markus Friedl. All rights reserved. .\" Copyright (c) 1999 Aaron Campbell. All rights reserved. .\" Copyright (c) 1999 Theo de Raadt. All rights reserved. +.\" Copyright (c) 2002-2022 Roumen Petrov. All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions @@ -39,10 +48,10 @@ .Os .Sh NAME .Nm ssh -.Nd OpenSSH remote login client +.Nd Secure shell client (remote login program) .Sh SYNOPSIS .Nm ssh -.Op Fl 46AaCfGgKkMNnqsTtVvXxYy +.Op Fl 46AaCdfgKkMNnqsTtVvXxYy .Op Fl B Ar bind_interface .Op Fl b Ar bind_address .Op Fl c Ar cipher_spec @@ -50,6 +59,7 @@ .Op Fl E Ar log_file .Op Fl e Ar escape_char .Op Fl F Ar configfile +.Op Fl G Ar engine_configfile .Op Fl I Ar pkcs11 .Op Fl i Ar identity_file .Op Fl J Ar destination @@ -128,6 +138,11 @@ An attacker cannot obtain key material from the agent, however they can perform operations on the keys that enable them to authenticate using the identities loaded into the agent. +Using the +.Fl c +flag of +.Xr ssh-add 1 +can reduce (but not eliminate) the risk. A safer alternative may be to use a jump host (see .Fl J ) . @@ -158,10 +173,11 @@ Compression is desirable on modem lines and other slow connections, but will only slow down things on fast networks. The default value can be set on a host-by-host basis in the -configuration files; see the +configuration files. See the .Cm Compression -option in -.Xr ssh_config 5 . +keyword in +.Xr ssh_config 5 +for more information. .Pp .It Fl c Ar cipher_spec Selects the cipher specification for encrypting the session. @@ -214,6 +230,15 @@ .Sq * indicates that the port should be available from all interfaces. .Pp +.It Fl d +Causes +.Nm +to print its configuration after evaluating +.Cm Host +and +.Cm Match +blocks and exit. +.Pp .It Fl E Ar log_file Append debug logs to .Ar log_file @@ -272,14 +297,12 @@ .Xr ssh_config 5 for details. .Pp -.It Fl G -Causes -.Nm -to print its configuration after evaluating -.Cm Host -and -.Cm Match -blocks and exit. +.It Fl G Ar engine_configfile +Specifies an alternative per-user file for post initialization of +.Xr openssl 1 +engines. +The default per-user configuration file is +.Pa ~/.ssh/engine . .Pp .It Fl g Allows remote hosts to connect to local forwarded ports. @@ -289,8 +312,8 @@ .It Fl I Ar pkcs11 Specify the PKCS#11 shared library .Nm -should use to communicate with a PKCS#11 token providing keys for user -authentication. +should use to communicate with a PKCS#11 token providing the user's +private EC or RSA key and X.509 certificate. .Pp .It Fl i Ar identity_file Selects a file from which the identity (private key) for @@ -302,9 +325,7 @@ The default is .Pa ~/.ssh/id_rsa , .Pa ~/.ssh/id_ecdsa , -.Pa ~/.ssh/id_ecdsa_sk , -.Pa ~/.ssh/id_ed25519 , -.Pa ~/.ssh/id_ed25519_sk +.Pa ~/.ssh/id_ed25519 and .Pa ~/.ssh/id_dsa . Identity files may also be specified on @@ -313,17 +334,36 @@ .Fl i options (and multiple identities specified in configuration files). -If no certificates have been explicitly specified by the +.Pp +Option is equal to configuration option +.Cm IdentityFile +- see +.Xr ssh_config 5 +for more details. +This mean than could be used prefixes +.Dq engine: +or +.Dq store: +to load identifies using engine or store functionality +provided by cryptographic library. +.Pp +For RSA, ECDSA, Ed25519 or DSA identity file may contain X.509 certificate that +match key. In addition file may contain extra X.509 certificates. +Extra certificates along with certificates from X.509 store are used +to build chain of certificates leading to a trusted certificate +authority if required by public key algorithm format. +.Pp +If no OpenSSH custom certificates have been explicitly specified by the .Cm CertificateFile directive, .Nm -will also try to load certificate information from the filename obtained +will also try to load OpenSSH custom certificate information from the filename obtained by appending .Pa -cert.pub to identity filenames. .Pp .It Fl J Ar destination -Connect to the target host by first making an +Connect to the target host by first making a .Nm connection to the jump host described by .Ar destination @@ -498,102 +538,9 @@ Can be used to give options in the format used in the configuration file. This is useful for specifying options for which there is no separate command-line flag. -For full details of the options listed below, and their possible values, see +For full details of the options and their possible values, see .Xr ssh_config 5 . .Pp -.Bl -tag -width Ds -offset indent -compact -.It AddKeysToAgent -.It AddressFamily -.It BatchMode -.It BindAddress -.It CanonicalDomains -.It CanonicalizeFallbackLocal -.It CanonicalizeHostname -.It CanonicalizeMaxDots -.It CanonicalizePermittedCNAMEs -.It CASignatureAlgorithms -.It CertificateFile -.It CheckHostIP -.It Ciphers -.It ClearAllForwardings -.It Compression -.It ConnectionAttempts -.It ConnectTimeout -.It ControlMaster -.It ControlPath -.It ControlPersist -.It DynamicForward -.It EnableEscapeCommandline -.It EscapeChar -.It ExitOnForwardFailure -.It FingerprintHash -.It ForkAfterAuthentication -.It ForwardAgent -.It ForwardX11 -.It ForwardX11Timeout -.It ForwardX11Trusted -.It GatewayPorts -.It GlobalKnownHostsFile -.It GSSAPIAuthentication -.It GSSAPIDelegateCredentials -.It HashKnownHosts -.It Host -.It HostbasedAcceptedAlgorithms -.It HostbasedAuthentication -.It HostKeyAlgorithms -.It HostKeyAlias -.It Hostname -.It IdentitiesOnly -.It IdentityAgent -.It IdentityFile -.It IPQoS -.It KbdInteractiveAuthentication -.It KbdInteractiveDevices -.It KexAlgorithms -.It KnownHostsCommand -.It LocalCommand -.It LocalForward -.It LogLevel -.It MACs -.It Match -.It NoHostAuthenticationForLocalhost -.It NumberOfPasswordPrompts -.It PasswordAuthentication -.It PermitLocalCommand -.It PermitRemoteOpen -.It PKCS11Provider -.It Port -.It PreferredAuthentications -.It ProxyCommand -.It ProxyJump -.It ProxyUseFdpass -.It PubkeyAcceptedAlgorithms -.It PubkeyAuthentication -.It RekeyLimit -.It RemoteCommand -.It RemoteForward -.It RequestTTY -.It RequiredRSASize -.It SendEnv -.It ServerAliveInterval -.It ServerAliveCountMax -.It SessionType -.It SetEnv -.It StdinNull -.It StreamLocalBindMask -.It StreamLocalBindUnlink -.It StrictHostKeyChecking -.It TCPKeepAlive -.It Tunnel -.It TunnelDevice -.It UpdateHostKeys -.It User -.It UserKnownHostsFile -.It VerifyHostKeyDNS -.It VisualHostKey -.It XAuthLocation -.El -.Pp .It Fl P Ar tag Specify a tag name that may be used to select configuration in .Xr ssh_config 5 . @@ -604,6 +551,7 @@ keywords in .Xr ssh_config 5 for more information. +.Pp .It Fl p Ar port Port to connect to on the remote host. This can be specified on a @@ -621,28 +569,26 @@ flag), .Ar mac (supported message integrity codes), +.Ar compression +(compression algorithms), .Ar kex (key exchange algorithms), .Ar key (key types), +.Ar key-alg +(public key algorithms), .Ar key-ca-sign -(valid CA signature algorithms for certificates), +(compatibility option), .Ar key-cert -(certificate key types), +(OpenSSH custom certificate key types), .Ar key-plain (non-certificate key types), -.Ar key-sig -(all key types and signature algorithms), .Ar protocol-version (supported SSH protocol versions), and .Ar sig -(supported signature algorithms). -Alternatively, any keyword from -.Xr ssh_config 5 -or -.Xr sshd_config 5 -that takes an algorithm list may be used as an alias for the corresponding -query_option. +(compatibility option). +This option must be specified last as other options may impact list +of supported algorithms. .Pp .It Fl q Quiet mode. @@ -778,7 +724,7 @@ Multiple .Fl v options increase the verbosity. -The maximum is 3. +The maximum is 4. .Pp .It Fl W Ar host : Ns Ar port Requests that standard input and output on the client be forwarded to @@ -873,7 +819,7 @@ The file format and configuration options are described in .Xr ssh_config 5 . .Sh AUTHENTICATION -The OpenSSH SSH client supports SSH protocol 2. +The SecSH client supports SSH protocol 2. .Pp The methods available for authentication are: GSSAPI-based authentication, @@ -903,7 +849,7 @@ Additionally, the server .Em must be able to verify the client's -host key (see the description of +host key or X.509 certificate (see the description of .Pa /etc/ssh/ssh_known_hosts and .Pa ~/.ssh/known_hosts , @@ -918,29 +864,29 @@ disabled if security is desired.] .Pp Public key authentication works as follows: -The scheme is based on public-key cryptography, +The scheme is based on public-key cryptography or infrastructure (PKI), using cryptosystems where encryption and decryption are done using separate keys, and it is unfeasible to derive the decryption key from the encryption key. The idea is that each user creates a public/private key pair for authentication purposes. -The server knows the public key, and only the user knows the private key. +The server knows the public key or X.509 certificate, and only the user knows the private key. .Nm implements public key authentication protocol automatically, -using one of the DSA, ECDSA, Ed25519 or RSA algorithms. +using one of the DSA, ECDSA, Ed25519 or RSA algorithms or X.509 certificates. The HISTORY section of .Xr ssl 8 contains a brief discussion of the DSA and RSA algorithms. .Pp The file .Pa ~/.ssh/authorized_keys -lists the public keys that are permitted for logging in. +lists the public keys or X.509 certificates that are permitted for logging in. When the user logs in, the .Nm -program tells the server which key pair it would like to use for +program tells the server which key pair or X.509 certificate it would like to use for authentication. The client proves that it has access to the private key -and the server checks that the corresponding public key +and the server checks that the corresponding public key or X.509 certificate is authorized to accept the account. .Pp The server may inform the client of errors that prevented public key @@ -961,12 +907,8 @@ (DSA), .Pa ~/.ssh/id_ecdsa (ECDSA), -.Pa ~/.ssh/id_ecdsa_sk -(authenticator-hosted ECDSA), .Pa ~/.ssh/id_ed25519 (Ed25519), -.Pa ~/.ssh/id_ed25519_sk -(authenticator-hosted Ed25519), or .Pa ~/.ssh/id_rsa (RSA) @@ -975,33 +917,40 @@ (DSA), .Pa ~/.ssh/id_ecdsa.pub (ECDSA), -.Pa ~/.ssh/id_ecdsa_sk.pub -(authenticator-hosted ECDSA), .Pa ~/.ssh/id_ed25519.pub (Ed25519), -.Pa ~/.ssh/id_ed25519_sk.pub -(authenticator-hosted Ed25519), or .Pa ~/.ssh/id_rsa.pub (RSA) in the user's home directory. -The user should then copy the public key +For RSA, ECDSA, Ed25519 or DSA identity files may contain private key, +X.509 certificate that match it and extra X.509 certificates. +In this case *.pub file must contain certificate that match key. +The user should then copy the public key or X.509 certificate to .Pa ~/.ssh/authorized_keys in their home directory on the remote machine. +In case with X.509 certificates user can use +.Dq new style +: instead to add content of file to authorized_keys user +can write certificate +.Dq Distinguished Name +- see +.Xr sshd 8 +manual page. The .Pa authorized_keys file corresponds to the conventional .Pa ~/.rhosts -file, and has one key +file, and has one key or X.509 certificate per line, though the lines can be very long. After this, the user can log in without giving the password. .Pp A variation on public key authentication -is available in the form of certificate authentication: +is available in the form of OpenSSH custom certificate authentication: instead of a set of public/private keys, signed certificates are used. -This has the advantage that a single trusted certification authority +This has the advantage that a single trusted OpenSSH custom certification authority can be used in place of many public/private keys. See the CERTIFICATES section of .Xr ssh-keygen 1 @@ -1045,6 +994,9 @@ Additionally, the file .Pa /etc/ssh/ssh_known_hosts is automatically checked for known hosts. +If host key is a X.509 certificate line may contain certificate +.Dq Distinguished Name +instead base64 encoded representation. Any new hosts are automatically added to the user's file. If a host's identification ever changes, .Nm @@ -1303,16 +1255,17 @@ .Pp If the fingerprint is unknown, an alternative method of verification is available: -SSH fingerprints verified by DNS. +SSH fingerprints or X.509 certificates verified by DNS. An additional resource record (RR), -SSHFP, +SSHFP or CERT, is added to a zonefile and the connecting client is able to match the fingerprint +or X.509 certificate with that of the key presented. .Pp In this example, we are connecting a client to a server, .Dq host.example.com . -The SSHFP resource records should first be added to the zonefile for +The SSHFP or CERT resource records should first be added to the zonefile for host.example.com: .Bd -literal -offset indent $ ssh-keygen -r host.example.com. @@ -1323,6 +1276,10 @@ .Pp .Dl $ dig -t SSHFP host.example.com .Pp +To check that the zone is answering X.509 certificate queries: +.Pp +.Dl $ dig -t CERT host.example.com +.Pp Finally the client connects: .Bd -literal -offset indent $ ssh -o "VerifyHostKeyDNS ask" host.example.com @@ -1331,6 +1288,11 @@ Are you sure you want to continue connecting (yes/no)? .Ed .Pp +When host key is a X.509 certificate +.Dq Distinguished Name +is displayed after fingerprint. +Note that host X.509 certificate always is verifified and validated. +.Pp See the .Cm VerifyHostKeyDNS option in @@ -1397,9 +1359,71 @@ and .Xr isakmpd 8 . .Sh ENVIRONMENT +.Bl -tag -width Ds +.It Ev SSH_ASKPASS +If .Nm +needs a passphrase, it will read the passphrase from the current +terminal if it was run from a terminal. +If +.Nm +does not have a terminal associated with it but +.Ev "DISPLAY" and "SSH_ASKPASS" +are set, it will execute the program specified by +.Ev SSH_ASKPASS +that may open a X11 window to read the passphrase. +For keys from +.Dq engine +or +.Dq store +.Ev SSH_ASKPASS +is preferred over associated terminal. +Note if +.Ev SSH_ASKPASS +is not set will be executed program +.Nm ssh-askpass +located in +.Dq libexec +directory. +This is particularly useful when calling +.Nm +from a +.Pa .xsession +or related script. +.Pp +Remark: On Android +.Ev DISPLAY +is ignored. +.It Ev SSH_ASKPASS_REQUIRE +Allows further control over the use of an askpass program. +If this variable is set to +.Dq never +then +.Nm +will never attempt to use one. +If it is set to +.Dq prefer , +then +.Nm +will prefer to use the askpass program instead of the TTY when requesting +passwords. +Finally, if the variable is set to +.Dq force , +then the askpass program will be used for all passphrase input regardless +of whether +.Ev DISPLAY +is set. +.It Ev SSH_AUTH_SOCK +Identifies the path of a +.Ux Ns -domain +socket used to communicate with the agent. +.It Ev SSH_ENGINE_CONF +Overrides default location of engine configuration file. +.El +.Pp +.Xr sshd 8 will normally set the following environment variables: -.Bl -tag -width "SSH_ORIGINAL_COMMAND" +.Bl -tag -width Ds .It Ev DISPLAY The .Ev DISPLAY @@ -1434,52 +1458,10 @@ .Ev PATH , as specified when compiling .Nm . -.It Ev SSH_ASKPASS -If -.Nm -needs a passphrase, it will read the passphrase from the current -terminal if it was run from a terminal. -If -.Nm -does not have a terminal associated with it but -.Ev DISPLAY -and -.Ev SSH_ASKPASS -are set, it will execute the program specified by -.Ev SSH_ASKPASS -and open an X11 window to read the passphrase. -This is particularly useful when calling -.Nm -from a -.Pa .xsession -or related script. -(Note that on some machines it -may be necessary to redirect the input from -.Pa /dev/null -to make this work.) -.It Ev SSH_ASKPASS_REQUIRE -Allows further control over the use of an askpass program. -If this variable is set to -.Dq never -then -.Nm -will never attempt to use one. -If it is set to -.Dq prefer , -then -.Nm -will prefer to use the askpass program instead of the TTY when requesting -passwords. -Finally, if the variable is set to -.Dq force , -then the askpass program will be used for all passphrase input regardless -of whether -.Ev DISPLAY -is set. .It Ev SSH_AUTH_SOCK Identifies the path of a .Ux Ns -domain -socket used to communicate with the agent. +socket used to communicate with the forwarded agent. .It Ev SSH_CONNECTION Identifies the client and server ends of the connection. The variable contains @@ -1514,7 +1496,7 @@ .El .Pp Additionally, -.Nm +.Xr sshd 8 reads .Pa ~/.ssh/environment , and adds lines of the format @@ -1555,6 +1537,7 @@ .Pp .It Pa ~/.ssh/authorized_keys Lists the public keys (DSA, ECDSA, Ed25519, RSA) +or X.509 certificates that can be used for logging in as this user. The format of this file is described in the .Xr sshd 8 @@ -1562,6 +1545,18 @@ This file is not highly sensitive, but the recommended permissions are read/write for the user, and not accessible by others. .Pp +.It Pa ~/.ssh/ca/ca-bundle.crt +.It Pa ~/.ssh/ca/ca-bundle.crl +Part of user +.Dq "X.509 store" . +Same as systemwide files below. +.Pp +.It Pa ~/.ssh/ca/crt +.It Pa ~/.ssh/ca/crl +Part of user +.Dq "X.509 store" . +Same as systemwide directories below. +.Pp .It Pa ~/.ssh/config This is the per-user configuration file. The file format and configuration options are described in @@ -1576,9 +1571,7 @@ .Pp .It Pa ~/.ssh/id_dsa .It Pa ~/.ssh/id_ecdsa -.It Pa ~/.ssh/id_ecdsa_sk .It Pa ~/.ssh/id_ed25519 -.It Pa ~/.ssh/id_ed25519_sk .It Pa ~/.ssh/id_rsa Contains the private key for authentication. These files @@ -1588,20 +1581,27 @@ will simply ignore a private key file if it is accessible by others. It is possible to specify a passphrase when generating the key which will be used to encrypt the -sensitive part of this file using AES-128. +sensitive part of this file using 256-bit AES. +.Pp +For RSA, ECDSA, Ed25519 or DSA identity file (private key) +may contain X.509 certificate that match key. +In addition file may contain extra X.509 certificates. +Extra certificates along with certificates from X.509 store are used +to build chain of certificates leading to a trusted certificate +authority if required by public key algorithm format. .Pp .It Pa ~/.ssh/id_dsa.pub .It Pa ~/.ssh/id_ecdsa.pub -.It Pa ~/.ssh/id_ecdsa_sk.pub .It Pa ~/.ssh/id_ed25519.pub -.It Pa ~/.ssh/id_ed25519_sk.pub .It Pa ~/.ssh/id_rsa.pub Contains the public key for authentication. +Note if an identity contain private key and X.509 certificate, +file must contain that certificate. These files are not sensitive and can (but need not) be readable by anyone. .Pp .It Pa ~/.ssh/known_hosts -Contains a list of host keys for all hosts the user has logged into +Contains a list of host keys or X.509 certificates for all hosts the user has logged into that are not already in the systemwide list of known host keys. See .Xr sshd 8 @@ -1626,6 +1626,28 @@ but allows host-based authentication without permitting login with rlogin/rsh. .Pp +.It /etc/ssh/ca/ca-bundle.crt +.It /etc/ssh/ca/ca-bundle.crl +Part of systemwide +.Dq "X.509 store" . +The first file contain multiple certificates and the second +.Dq "Certificate Revocation List" +(CRLs) of X.509 certificate signers in PEM format concatenated together. +Used in verification and validation of server host certificate. +.Pp +.It /etc/ssh/ca/crt +.It /etc/ssh/ca/crl +Part of systemwide +.Dq "X.509 store" . +.Dq "Hash dirs" +with certificates, the first directory or CLRs, the second of +certificate signers. +Each certificate should be stored in separate file with name +[HASH].[NUMBER] or [HASH].r[NUMBER] for the CRL, where [HASH] is +certificate or CRL hash value and [NUMBER] is an integer starting +from zero. +Used in verification and validation of server host certificate. +.Pp .It Pa /etc/ssh/ssh_config Systemwide configuration file. The file format and configuration options are described in @@ -1638,12 +1660,23 @@ .It Pa /etc/ssh/ssh_host_rsa_key These files contain the private parts of the host keys and are used for host-based authentication. +For RSA, ECDSA, Ed25519 or DSA keys files may contain X.509 certificate that +match it. +In addition file may contain extra X.509 certificates. +Extra certificates along with certificates from X.509 store are used +to build chain of certificates leading to a trusted certificate +authority if required by host-based key algorithm format. +If a X.509 certificate is used as host key for hostbased authentication +that certificate must have client purpose too or server configuration +must permit connection without client purpose. For allowed client +certificate purposes see +.Xr ssh_config 5 . .Pp .It Pa /etc/ssh/ssh_known_hosts -Systemwide list of known host keys. +Systemwide list of known host keys or X.509 certificates. This file should be prepared by the -system administrator to contain the public host keys of all machines in the -organization. +system administrator to contain the public host keys or X.509 certificates +of all machines in the organization. It should be world-readable. See .Xr sshd 8 @@ -1666,13 +1699,27 @@ .Xr sftp 1 , .Xr ssh-add 1 , .Xr ssh-agent 1 , +.Xr ssh-askpass 1 , .Xr ssh-keygen 1 , .Xr ssh-keyscan 1 , .Xr tun 4 , .Xr ssh_config 5 , .Xr ssh-keysign 8 , .Xr sshd 8 -.Sh STANDARDS +.Sh CONFORMING TO +.Bl -enum +.It +.Rs +.%A T. Ylonen +.%A T. Kivinen +.%A M. Saarinen +.%A T. Rinne +.%A S. Lehtinen +.%D 31 January 2002 +.%O draft-ietf-secsh-transport-12.txt +.%T SSH Transport Layer Protocol +.Re +.It .Rs .%A S. Lehtinen .%A C. Lonvick @@ -1680,7 +1727,7 @@ .%R RFC 4250 .%T The Secure Shell (SSH) Protocol Assigned Numbers .Re -.Pp +.It .Rs .%A T. Ylonen .%A C. Lonvick @@ -1688,7 +1735,7 @@ .%R RFC 4251 .%T The Secure Shell (SSH) Protocol Architecture .Re -.Pp +.It .Rs .%A T. Ylonen .%A C. Lonvick @@ -1696,7 +1743,7 @@ .%R RFC 4252 .%T The Secure Shell (SSH) Authentication Protocol .Re -.Pp +.It .Rs .%A T. Ylonen .%A C. Lonvick @@ -1704,7 +1751,7 @@ .%R RFC 4253 .%T The Secure Shell (SSH) Transport Layer Protocol .Re -.Pp +.It .Rs .%A T. Ylonen .%A C. Lonvick @@ -1712,7 +1759,7 @@ .%R RFC 4254 .%T The Secure Shell (SSH) Connection Protocol .Re -.Pp +.It .Rs .%A J. Schlyter .%A W. Griffin @@ -1720,7 +1767,7 @@ .%R RFC 4255 .%T Using DNS to Securely Publish Secure Shell (SSH) Key Fingerprints .Re -.Pp +.It .Rs .%A F. Cusack .%A M. Forssen @@ -1728,7 +1775,7 @@ .%R RFC 4256 .%T Generic Message Exchange Authentication for the Secure Shell Protocol (SSH) .Re -.Pp +.It .Rs .%A J. Galbraith .%A P. Remaker @@ -1736,7 +1783,7 @@ .%R RFC 4335 .%T The Secure Shell (SSH) Session Channel Break Extension .Re -.Pp +.It .Rs .%A M. Bellare .%A T. Kohno @@ -1745,14 +1792,14 @@ .%R RFC 4344 .%T The Secure Shell (SSH) Transport Layer Encryption Modes .Re -.Pp +.It .Rs .%A B. Harris .%D January 2006 .%R RFC 4345 .%T Improved Arcfour Modes for the Secure Shell (SSH) Transport Layer Protocol .Re -.Pp +.It .Rs .%A M. Friedl .%A N. Provos @@ -1761,7 +1808,7 @@ .%R RFC 4419 .%T Diffie-Hellman Group Exchange for the Secure Shell (SSH) Transport Layer Protocol .Re -.Pp +.It .Rs .%A J. Galbraith .%A R. Thayer @@ -1769,7 +1816,7 @@ .%R RFC 4716 .%T The Secure Shell (SSH) Public Key File Format .Re -.Pp +.It .Rs .%A D. Stebila .%A J. Green @@ -1777,7 +1824,7 @@ .%R RFC 5656 .%T Elliptic Curve Algorithm Integration in the Secure Shell Transport Layer .Re -.Pp +.It .Rs .%A A. Perrig .%A D. Song @@ -1785,8 +1832,56 @@ .%O International Workshop on Cryptographic Techniques and E-Commerce (CrypTEC '99) .%T Hash Visualization: a New Technique to improve Real-World Security .Re +.It +.Rs +.%A K. Igoe +.%A D. Stebila +.%D March 2011 +.%R RFC 6187 +.%T X.509v3 Certificates for Secure Shell Authentication +.Re +.It +.Rs +.%A S. Josefsson +.%A I. Liusvaara +.%D January 2017 +.%R RFC 8032 +.%T Edwards-Curve Digital Signature Algorithm (EdDSA) +.Re +.It +.Rs +.%A D. Bider +.%D March 2018 +.%R RFC 8308 +.%T Extension Negotiation in the Secure Shell (SSH) Protocol +.Re +.It +.Rs +.%A D. Bider +.%D March 2018 +.%R RFC 8332 +.%T Use of RSA Keys with SHA-256 and SHA-512 in the Secure Shell (SSH) Protocol +.Re +.It +.Rs +.%A A. Adamantiadis +.%A S. Josefsson +.%A M. Baushke +.%D February 2020 +.%R RFC 8731 +.%T Secure Shell (SSH) Key Exchange Method Using Curve25519 and Curve448 +.Re +.It +.Rs +.%A B. Harris +.%A L. Velvindron +.%D February 2020 +.%R RFC 8709 +.%T Ed25519 and Ed448 Public Key Algorithms for the Secure Shell (SSH) Protocol +.Re +.El .Sh AUTHORS -OpenSSH is a derivative of the original and free +PKIX-SSH is a derivative of the original and free ssh 1.2.12 release by Tatu Ylonen. Aaron Campbell, Bob Beck, Markus Friedl, Niels Provos, Theo de Raadt and Dug Song @@ -1794,3 +1889,4 @@ created OpenSSH. Markus Friedl contributed the support for SSH protocol versions 1.5 and 2.0. +Roumen Petrov contributed support for X.509 certificates. diff -ruN openssh-9.4p1/ssh-add.0 openssh-9.4p1+x509-14.2.1/ssh-add.0 --- openssh-9.4p1/ssh-add.0 2023-08-10 04:11:18.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/ssh-add.0 2023-08-20 10:07:00.000000000 +0300 @@ -1,31 +1,38 @@ -SSH-ADD(1) General Commands Manual SSH-ADD(1) +SSH-ADD(1) BSD General Commands Manual SSH-ADD(1) NAME - ssh-add M-bM-^@M-^S adds private key identities to the OpenSSH authentication agent + ssh-add -- Adds private key identities to the authentication agent SYNOPSIS - ssh-add [-cDdKkLlqvXx] [-E fingerprint_hash] [-H hostkey_file] - [-h destination_constraint] [-S provider] [-t life] [file ...] + ssh-add [-cDdkLlqvXx] [-E fingerprint_hash] [-t life] [file ...] ssh-add -s pkcs11 ssh-add -e pkcs11 ssh-add -T pubkey ... DESCRIPTION ssh-add adds private key identities to the authentication agent, - ssh-agent(1). When run without arguments, it adds the files - ~/.ssh/id_rsa, ~/.ssh/id_ecdsa, ~/.ssh/id_ecdsa_sk, ~/.ssh/id_ed25519, - ~/.ssh/id_ed25519_sk, and ~/.ssh/id_dsa. After loading a private key, - ssh-add will try to load corresponding certificate information from the - filename obtained by appending -cert.pub to the name of the private key - file. Alternative file names can be given on the command line. + ssh-agent(1). + + For RSA, ECDSA, Ed25519 or DSA identity may contain X.509 certificate + that match private key. This certificate will be loaded as well. Also + identity may contain extra X.509 certificates. Agent client uses those + extra certificates along with certificates from system default X.509 + store to build chain of certificates leading to a trusted certificate au- + thority. + + When run without arguments, it adds the files ~/.ssh/id_rsa, + ~/.ssh/id_ecdsa, ~/.ssh/id_ed25519 and ~/.ssh/id_dsa. After loading a + private key, ssh-add will try to load corresponding custom certificate + information from the filename obtained by appending -cert.pub to the name + of the private key file. Alternative file names can be given on the com- + mand line. If any file requires a passphrase, ssh-add asks for the passphrase from the user. The passphrase is read from the user's tty. ssh-add retries the last passphrase if multiple identity files are given. - The authentication agent must be running and the SSH_AUTH_SOCK - environment variable must contain the name of its socket for ssh-add to - work. + The authentication agent must be running and the SSH_AUTH_SOCK environ- + ment variable must contain the name of its socket for ssh-add to work. The options are as follows: @@ -38,92 +45,39 @@ -D Deletes all identities from the agent. -d Instead of adding identities, removes identities from the agent. - If ssh-add has been run without arguments, the keys for the - default identities and their corresponding certificates will be - removed. Otherwise, the argument list will be interpreted as a - list of paths to public key files to specify keys and - certificates to be removed from the agent. If no public key is - found at a given path, ssh-add will append .pub and retry. If - the argument list consists of M-bM-^@M-^\-M-bM-^@M-^] then ssh-add will read public - keys to be removed from standard input. + If ssh-add has been run without arguments, the keys for the de- + fault identities and their corresponding certificates (X.509 or + custom) will be removed. Otherwise, the argument list will be + interpreted as a list of paths to public key files to specify + keys and certificates to be removed from the agent. If no public + key is found at a given path, ssh-add will append .pub and retry. + If the argument list consists of "-" then ssh-add will read pub- + lic keys to be removed from standard input. -E fingerprint_hash - Specifies the hash algorithm used when displaying key - fingerprints. Valid options are: M-bM-^@M-^\md5M-bM-^@M-^] and M-bM-^@M-^\sha256M-bM-^@M-^]. The - default is M-bM-^@M-^\sha256M-bM-^@M-^]. + Specifies the hash algorithm used when displaying key finger- + prints. Valid options are: "md5" and "sha256". The default is + "sha256". -e pkcs11 Remove keys provided by the PKCS#11 shared library pkcs11. - -H hostkey_file - Specifies a known hosts file to look up hostkeys when using - destination-constrained keys via the -h flag. This option may be - specified multiple times to allow multiple files to be searched. - If no files are specified, ssh-add will use the default - ssh_config(5) known hosts files: ~/.ssh/known_hosts, - ~/.ssh/known_hosts2, /etc/ssh/ssh_known_hosts, and - /etc/ssh/ssh_known_hosts2. - - -h destination_constraint - When adding keys, constrain them to be usable only through - specific hosts or to specific destinations. - - Destination constraints of the form M-bM-^@M-^X[user@]dest-hostnameM-bM-^@M-^Y permit - use of the key only from the origin host (the one running - ssh-agent(1)) to the listed destination host, with optional user - name. - - Constraints of the form M-bM-^@M-^Xsrc-hostname>[user@]dst-hostnameM-bM-^@M-^Y allow - a key available on a forwarded ssh-agent(1) to be used through a - particular host (as specified by M-bM-^@M-^Xsrc-hostnameM-bM-^@M-^Y) to authenticate - to a further host, specified by M-bM-^@M-^Xdst-hostnameM-bM-^@M-^Y. - - Multiple destination constraints may be added when loading keys. - When attempting authentication with a key that has destination - constraints, the whole connection path, including ssh-agent(1) - forwarding, is tested against those constraints and each hop must - be permitted for the attempt to succeed. For example, if key is - forwarded to a remote host, M-bM-^@M-^Xhost-bM-bM-^@M-^Y, and is attempting - authentication to another host, M-bM-^@M-^Xhost-cM-bM-^@M-^Y, then the operation will - be successful only if M-bM-^@M-^Xhost-bM-bM-^@M-^Y was permitted from the origin host - and the subsequent M-bM-^@M-^Xhost-b>host-cM-bM-^@M-^Y hop is also permitted by - destination constraints. - - Hosts are identified by their host keys, and are looked up from - known hosts files by ssh-add. Wildcards patterns may be used for - hostnames and certificate host keys are supported. By default, - keys added by ssh-add are not destination constrained. - - Destination constraints were added in OpenSSH release 8.9. - Support in both the remote SSH client and server is required when - using destination-constrained keys over a forwarded ssh-agent(1) - channel. - - It is also important to note that destination constraints can - only be enforced by ssh-agent(1) when a key is used, or when it - is forwarded by a cooperating ssh(1). Specifically, it does not - prevent an attacker with access to a remote SSH_AUTH_SOCK from - forwarding it again and using it on a different host (but only to - a permitted destination). - - -K Load resident keys from a FIDO authenticator. - - -k When loading keys into or deleting keys from the agent, process - plain private keys only and skip certificates. + -k When listing X.509 certificate based identities prints public key + instead certificate distinguished name. - -L Lists public key parameters of all identities currently - represented by the agent. + When loading keys into or deleting keys from the agent, process + plain private keys only and skip custom certificates. In this + case it is ignored for X.509 certificate based identities. + + -L Lists public key parameters of all identities currently repre- + sented by the agent. X.509 certificates are displayed with their + "Distinguished Name". -l Lists fingerprints of all identities currently represented by the agent. -q Be quiet after a successful operation. - -S provider - Specifies a path to a library that will be used when adding FIDO - authenticator-hosted keys, overriding the default of using the - internal USB HID support. - -s pkcs11 Add keys provided by the PKCS#11 shared library pkcs11. @@ -134,8 +88,8 @@ -t life Set a maximum lifetime when adding identities to an agent. The - lifetime may be specified in seconds or in a time format - specified in sshd_config(5). + lifetime may be specified in seconds or in a time format speci- + fied in sshd_config(5). -v Verbose mode. Causes ssh-add to print debugging messages about its progress. This is helpful in debugging problems. Multiple @@ -146,42 +100,43 @@ -x Lock the agent with a password. ENVIRONMENT - DISPLAY, SSH_ASKPASS and SSH_ASKPASS_REQUIRE + SSH_ASKPASS If ssh-add needs a passphrase, it will read the passphrase from the current terminal if it was run from a terminal. If ssh-add - does not have a terminal associated with it but DISPLAY and - SSH_ASKPASS are set, it will execute the program specified by - SSH_ASKPASS (by default M-bM-^@M-^\ssh-askpassM-bM-^@M-^]) and open an X11 window to - read the passphrase. This is particularly useful when calling - ssh-add from a .xsession or related script. - - SSH_ASKPASS_REQUIRE allows further control over the use of an - askpass program. If this variable is set to M-bM-^@M-^\neverM-bM-^@M-^] then ssh-add - will never attempt to use one. If it is set to M-bM-^@M-^\preferM-bM-^@M-^], then - ssh-add will prefer to use the askpass program instead of the TTY - when requesting passwords. Finally, if the variable is set to - M-bM-^@M-^\forceM-bM-^@M-^], then the askpass program will be used for all passphrase - input regardless of whether DISPLAY is set. + does not have a terminal associated with it but DISPLAY is set, + it will execute the program specified by SSH_ASKPASS that may + open a X11 window to read the passphrase. Note if SSH_ASKPASS is + not set will be executed program ssh-askpass located in "libexec" + directory. This is particularly useful when calling ssh-add from + a .xsession or related script. (Note that on some machines it + may be necessary to redirect the input from /dev/null to make + this work.) + + Remark: On Android DISPLAY is ignored. + + SSH_ASKPASS_REQUIRE + Allows further control over the use of an askpass program. If + this variable is set to "never" then ssh-add will never attempt + to use one. If it is set to "prefer", then ssh-add will prefer + to use the askpass program instead of the TTY when requesting + passwords. Finally, if the variable is set to "force", then the + askpass program will be used for all passphrase input regardless + of whether DISPLAY is set. SSH_AUTH_SOCK Identifies the path of a UNIX-domain socket used to communicate with the agent. - SSH_SK_PROVIDER - Specifies a path to a library that will be used when loading any - FIDO authenticator-hosted keys, overriding the default of using - the built-in USB HID support. - FILES ~/.ssh/id_dsa ~/.ssh/id_ecdsa - ~/.ssh/id_ecdsa_sk ~/.ssh/id_ed25519 - ~/.ssh/id_ed25519_sk ~/.ssh/id_rsa - Contains the DSA, ECDSA, authenticator-hosted ECDSA, Ed25519, - authenticator-hosted Ed25519 or RSA authentication identity of - the user. + Contains the DSA, ECDSA, Ed25519 or RSA authentication identity + of the user. + + For RSA, ECDSA, Ed25519 or DSA identity file may contain X.509 certifi- + cate that match private key and extra X.509 certificates. Identity files should not be readable by anyone but the user. Note that ssh-add ignores identity files if they are accessible by others. @@ -194,10 +149,11 @@ ssh(1), ssh-agent(1), ssh-askpass(1), ssh-keygen(1), sshd(8) AUTHORS - OpenSSH is a derivative of the original and free ssh 1.2.12 release by + PKIX-SSH is a derivative of the original and free ssh 1.2.12 release by Tatu Ylonen. Aaron Campbell, Bob Beck, Markus Friedl, Niels Provos, Theo - de Raadt and Dug Song removed many bugs, re-added newer features and - created OpenSSH. Markus Friedl contributed the support for SSH protocol - versions 1.5 and 2.0. + de Raadt and Dug Song removed many bugs, re-added newer features and cre- + ated OpenSSH. Markus Friedl contributed the support for SSH protocol + versions 1.5 and 2.0. Roumen Petrov contributed support for X.509 cer- + tificates. -OpenBSD 7.3 February 4, 2022 OpenBSD 7.3 +BSD 17 December 2022 BSD diff -ruN openssh-9.4p1/ssh-add.1 openssh-9.4p1+x509-14.2.1/ssh-add.1 --- openssh-9.4p1/ssh-add.1 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/ssh-add.1 2023-08-20 10:07:00.000000000 +0300 @@ -14,6 +14,7 @@ .\" Copyright (c) 1999,2000 Markus Friedl. All rights reserved. .\" Copyright (c) 1999 Aaron Campbell. All rights reserved. .\" Copyright (c) 1999 Theo de Raadt. All rights reserved. +.\" Copyright (c) 2002-2022 Roumen Petrov. All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions @@ -35,19 +36,24 @@ .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.Dd $Mdocdate: February 4 2022 $ +.\" Implement .Dd with the Mdocdate RCS keyword +.rn Dd xD +.de Dd +.ie \\$1$Mdocdate: \{\ +. xD \\$3 \\$2 \\$4 +.\} +.el .xD \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 +.. +.Dd $Mdocdate: December 17 2022 $ .Dt SSH-ADD 1 .Os .Sh NAME .Nm ssh-add -.Nd adds private key identities to the OpenSSH authentication agent +.Nd Adds private key identities to the authentication agent .Sh SYNOPSIS .Nm ssh-add -.Op Fl cDdKkLlqvXx +.Op Fl cDdkLlqvXx .Op Fl E Ar fingerprint_hash -.Op Fl H Ar hostkey_file -.Op Fl h Ar destination_constraint -.Op Fl S Ar provider .Op Fl t Ar life .Op Ar .Nm ssh-add @@ -61,17 +67,23 @@ .Nm adds private key identities to the authentication agent, .Xr ssh-agent 1 . +.Pp +For RSA, ECDSA, Ed25519 or DSA identity may contain X.509 certificate that +match private key. This certificate will be loaded as well. +Also identity may contain extra X.509 certificates. +Agent client uses those extra certificates along with certificates +from system default X.509 store to build chain of certificates +leading to a trusted certificate authority. +.Pp When run without arguments, it adds the files .Pa ~/.ssh/id_rsa , .Pa ~/.ssh/id_ecdsa , -.Pa ~/.ssh/id_ecdsa_sk , -.Pa ~/.ssh/id_ed25519 , -.Pa ~/.ssh/id_ed25519_sk , +.Pa ~/.ssh/id_ed25519 and .Pa ~/.ssh/id_dsa . After loading a private key, .Nm -will try to load corresponding certificate information from the +will try to load corresponding custom certificate information from the filename obtained by appending .Pa -cert.pub to the name of the private key file. @@ -107,7 +119,7 @@ If .Nm has been run without arguments, the keys for the default identities and -their corresponding certificates will be removed. +their corresponding certificates (X.509 or custom) will be removed. Otherwise, the argument list will be interpreted as a list of paths to public key files to specify keys and certificates to be removed from the agent. If no public key is found at a given path, @@ -131,100 +143,22 @@ .It Fl e Ar pkcs11 Remove keys provided by the PKCS#11 shared library .Ar pkcs11 . -.It Fl H Ar hostkey_file -Specifies a known hosts file to look up hostkeys when using -destination-constrained keys via the -.Fl h -flag. -This option may be specified multiple times to allow multiple files to be -searched. -If no files are specified, -.Nm -will use the default -.Xr ssh_config 5 -known hosts files: -.Pa ~/.ssh/known_hosts , -.Pa ~/.ssh/known_hosts2 , -.Pa /etc/ssh/ssh_known_hosts , -and -.Pa /etc/ssh/ssh_known_hosts2 . -.It Fl h Ar destination_constraint -When adding keys, constrain them to be usable only through specific hosts or to -specific destinations. -.Pp -Destination constraints of the form -.Sq [user@]dest-hostname -permit use of the key only from the origin host (the one running -.Xr ssh-agent 1 ) -to the listed destination host, with optional user name. -.Pp -Constraints of the form -.Sq src-hostname>[user@]dst-hostname -allow a key available on a forwarded -.Xr ssh-agent 1 -to be used through a particular host (as specified by -.Sq src-hostname ) -to authenticate to a further host, -specified by -.Sq dst-hostname . -.Pp -Multiple destination constraints may be added when loading keys. -When attempting authentication with a key that has destination constraints, -the whole connection path, including -.Xr ssh-agent 1 -forwarding, is tested against those constraints and each -hop must be permitted for the attempt to succeed. -For example, if key is forwarded to a remote host, -.Sq host-b , -and is attempting authentication to another host, -.Sq host-c , -then the operation will be successful only if -.Sq host-b -was permitted from the origin host and the subsequent -.Sq host-b>host-c -hop is also permitted by destination constraints. -.Pp -Hosts are identified by their host keys, and are looked up from known hosts -files by -.Nm . -Wildcards patterns may be used for hostnames and certificate host -keys are supported. -By default, keys added by -.Nm -are not destination constrained. -.Pp -Destination constraints were added in OpenSSH release 8.9. -Support in both the remote SSH client and server is required when using -destination-constrained keys over a forwarded -.Xr ssh-agent 1 -channel. -.Pp -It is also important to note that destination constraints can only be -enforced by -.Xr ssh-agent 1 -when a key is used, or when it is forwarded by a -.Sy cooperating -.Xr ssh 1 . -Specifically, it does not prevent an attacker with access to a remote -.Ev SSH_AUTH_SOCK -from forwarding it again and using it on a different host (but only to -a permitted destination). -.It Fl K -Load resident keys from a FIDO authenticator. .It Fl k +When listing X.509 certificate based identities prints public key +instead certificate distinguished name. +.Pp When loading keys into or deleting keys from the agent, process plain private -keys only and skip certificates. +keys only and skip custom certificates. +In this case it is ignored for X.509 certificate based identities. .It Fl L Lists public key parameters of all identities currently represented by the agent. +X.509 certificates are displayed with their +.Dq "Distinguished Name" . .It Fl l Lists fingerprints of all identities currently represented by the agent. .It Fl q Be quiet after a successful operation. -.It Fl S Ar provider -Specifies a path to a library that will be used when adding -FIDO authenticator-hosted keys, overriding the default of using the -internal USB HID support. .It Fl s Ar pkcs11 Add keys provided by the PKCS#11 shared library .Ar pkcs11 . @@ -254,7 +188,7 @@ .El .Sh ENVIRONMENT .Bl -tag -width Ds -.It Ev "DISPLAY", "SSH_ASKPASS" and "SSH_ASKPASS_REQUIRE" +.It Ev SSH_ASKPASS If .Nm needs a passphrase, it will read the passphrase from the current @@ -263,21 +197,31 @@ .Nm does not have a terminal associated with it but .Ev DISPLAY -and +is set, it will execute the program specified by .Ev SSH_ASKPASS -are set, it will execute the program specified by +that may open a X11 window to read the passphrase. +Note if .Ev SSH_ASKPASS -(by default -.Dq ssh-askpass ) -and open an X11 window to read the passphrase. +is not set will be executed program +.Nm ssh-askpass +located in +.Dq libexec +directory. This is particularly useful when calling .Nm from a .Pa .xsession or related script. +(Note that on some machines it +may be necessary to redirect the input from +.Pa /dev/null +to make this work.) .Pp -.Ev SSH_ASKPASS_REQUIRE -allows further control over the use of an askpass program. +Remark: On Android +.Ev DISPLAY +is ignored. +.It SSH_ASKPASS_REQUIRE +Allows further control over the use of an askpass program. If this variable is set to .Dq never then @@ -299,23 +243,19 @@ Identifies the path of a .Ux Ns -domain socket used to communicate with the agent. -.It Ev SSH_SK_PROVIDER -Specifies a path to a library that will be used when loading any -FIDO authenticator-hosted keys, overriding the default of using -the built-in USB HID support. .El .Sh FILES .Bl -tag -width Ds -compact .It Pa ~/.ssh/id_dsa .It Pa ~/.ssh/id_ecdsa -.It Pa ~/.ssh/id_ecdsa_sk .It Pa ~/.ssh/id_ed25519 -.It Pa ~/.ssh/id_ed25519_sk .It Pa ~/.ssh/id_rsa -Contains the DSA, ECDSA, authenticator-hosted ECDSA, Ed25519, -authenticator-hosted Ed25519 or RSA authentication identity of the user. +Contains the DSA, ECDSA, Ed25519 or RSA authentication identity of the user. .El .Pp +For RSA, ECDSA, Ed25519 or DSA identity file may contain X.509 certificate that +match private key and extra X.509 certificates. +.Pp Identity files should not be readable by anyone but the user. Note that .Nm @@ -332,7 +272,7 @@ .Xr ssh-keygen 1 , .Xr sshd 8 .Sh AUTHORS -OpenSSH is a derivative of the original and free +PKIX-SSH is a derivative of the original and free ssh 1.2.12 release by Tatu Ylonen. Aaron Campbell, Bob Beck, Markus Friedl, Niels Provos, Theo de Raadt and Dug Song @@ -340,3 +280,4 @@ created OpenSSH. Markus Friedl contributed the support for SSH protocol versions 1.5 and 2.0. +Roumen Petrov contributed support for X.509 certificates. diff -ruN openssh-9.4p1/ssh-add.c openssh-9.4p1+x509-14.2.1/ssh-add.c --- openssh-9.4p1/ssh-add.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/ssh-add.c 2023-08-20 10:07:01.000000000 +0300 @@ -13,6 +13,7 @@ * * SSH2 implementation, * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. + * Copyright (c) 2002-2023 Roumen Petrov. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -40,11 +41,6 @@ #include #include -#ifdef WITH_OPENSSL -# include -# include "openbsd-compat/openssl-compat.h" -#endif - #include #include #include @@ -58,7 +54,9 @@ #include "xmalloc.h" #include "ssh.h" #include "log.h" -#include "sshkey.h" +#include "ssh-x509.h" +#include "ssh-xkalg.h" +#include "compat.h" #include "sshbuf.h" #include "authfd.h" #include "authfile.h" @@ -66,9 +64,6 @@ #include "misc.h" #include "ssherr.h" #include "digest.h" -#include "ssh-sk.h" -#include "sk-api.h" -#include "hostfile.h" /* argv0 */ extern char *__progname; @@ -79,27 +74,51 @@ _PATH_SSH_CLIENT_ID_RSA, #ifdef OPENSSL_HAS_ECC _PATH_SSH_CLIENT_ID_ECDSA, - _PATH_SSH_CLIENT_ID_ECDSA_SK, #endif #endif /* WITH_OPENSSL */ _PATH_SSH_CLIENT_ID_ED25519, - _PATH_SSH_CLIENT_ID_ED25519_SK, - _PATH_SSH_CLIENT_ID_XMSS, +#ifdef WITH_OPENSSL _PATH_SSH_CLIENT_ID_DSA, +#endif /* WITH_OPENSSL */ +#ifdef WITH_XMSS + _PATH_SSH_CLIENT_ID_XMSS, +#endif NULL }; static int fingerprint_hash = SSH_FP_HASH_DEFAULT; /* Default lifetime (0 == forever) */ -static int lifetime = 0; +static u_int lifetime = 0; +static int/*bool*/ +set_lifetime(const char *val) +{ long t = convtime(val); + if (t == -1) { + fprintf(stderr, "Invalid lifetime\n"); + return 0; + } +/* Note u_int32_t is size used in communication to agent + * (see SSH_AGENT_CONSTRAIN_LIFETIME). */ +#if SIZEOF_LONG_INT > SIZEOF_INT + if (t > UINT32_MAX) { + fprintf(stderr, "Lifetime too high\n"); + return 0; + } +#endif + lifetime = (u_int)t; /*safe cast*/ + return 1; +} /* User has to confirm key use */ static int confirm = 0; +#ifdef WITH_XMSS /* Maximum number of signatures (XMSS) */ static u_int maxsign = 0; static u_int minleft = 0; +#else +# define maxsign 0 +#endif /* we keep a cache of one passphrase */ static char *pass = NULL; @@ -140,12 +159,11 @@ while (getline(&line, &linesize, stdin) != -1) { lnum++; - sshkey_free(key); - key = NULL; line[strcspn(line, "\n")] = '\0'; cp = line + strspn(line, " \t"); if (*cp == '#' || *cp == '\0') continue; + sshkey_free(key); if ((key = sshkey_new(KEY_UNSPEC)) == NULL) fatal_f("sshkey_new"); if ((r = sshkey_read(key, &cp)) != 0) { @@ -232,17 +250,13 @@ static int add_file(int agent_fd, const char *filename, int key_only, int qflag, - const char *skprovider, struct dest_constraint **dest_constraints, - size_t ndest_constraints) + const char *skprovider) { struct sshkey *private, *cert; char *comment = NULL; char msg[1024], *certpath = NULL; int r, fd, ret = -1; - size_t i; - u_int32_t left; struct sshbuf *keyblob; - struct ssh_identitylist *idlist; if (strcmp(filename, "-") == 0) { fd = STDIN_FILENO; @@ -324,53 +338,49 @@ filename, comment); goto out; } +#ifdef WITH_XMSS +{ + struct ssh_identitylist *idlist; + if (maxsign && minleft && (r = ssh_fetch_identitylist(agent_fd, &idlist)) == 0) { + size_t i; for (i = 0; i < idlist->nkeys; i++) { + u_int left; if (!sshkey_equal_public(idlist->keys[i], private)) continue; left = sshkey_signatures_left(idlist->keys[i]); if (left < minleft) { fprintf(stderr, - "Only %d signatures left.\n", left); + "Only %u signatures left.\n", left); break; } fprintf(stderr, "Skipping update: "); if (left == minleft) { fprintf(stderr, - "required signatures left (%d).\n", left); + "required signatures left (%u).\n", left); } else { fprintf(stderr, - "more signatures left (%d) than" - " required (%d).\n", left, minleft); + "more signatures left (%u) than" + " required (%u).\n", left, minleft); } ssh_free_identitylist(idlist); goto out; } ssh_free_identitylist(idlist); } - - if (sshkey_is_sk(private)) { - if (skprovider == NULL) { - fprintf(stderr, "Cannot load FIDO key %s " - "without provider\n", filename); - goto out; - } - } else { - /* Don't send provider constraint for other keys */ - skprovider = NULL; - } +} +#endif /*def WITH_XMSS*/ if ((r = ssh_add_identity_constrained(agent_fd, private, comment, - lifetime, confirm, maxsign, skprovider, - dest_constraints, ndest_constraints)) == 0) { + lifetime, confirm, maxsign, skprovider)) == 0) { ret = 0; if (!qflag) { fprintf(stderr, "Identity added: %s (%s)\n", filename, comment); if (lifetime != 0) { fprintf(stderr, - "Lifetime set to %d seconds\n", lifetime); + "Lifetime set to %u seconds\n", lifetime); } if (confirm != 0) { fprintf(stderr, "The user must confirm " @@ -415,8 +425,7 @@ sshkey_free(cert); if ((r = ssh_add_identity_constrained(agent_fd, private, comment, - lifetime, confirm, maxsign, skprovider, - dest_constraints, ndest_constraints)) != 0) { + lifetime, confirm, maxsign, skprovider)) != 0) { error_r(r, "Certificate %s (%s) add failed", certpath, private->cert->key_id); goto out; @@ -426,7 +435,7 @@ fprintf(stderr, "Certificate added: %s (%s)\n", certpath, private->cert->key_id); if (lifetime != 0) { - fprintf(stderr, "Lifetime set to %d seconds\n", + fprintf(stderr, "Lifetime set to %u seconds\n", lifetime); } if (confirm != 0) { @@ -444,8 +453,7 @@ } static int -update_card(int agent_fd, int add, const char *id, int qflag, - struct dest_constraint **dest_constraints, size_t ndest_constraints) +update_card(int agent_fd, int add, const char *id, int qflag) { char *pin = NULL; int r, ret = -1; @@ -457,7 +465,7 @@ } if ((r = ssh_update_card(agent_fd, add, id, pin == NULL ? "" : pin, - lifetime, confirm, dest_constraints, ndest_constraints)) == 0) { + lifetime, confirm)) == 0) { ret = 0; if (!qflag) { fprintf(stderr, "Card %s: %s\n", @@ -477,28 +485,40 @@ { struct sshkey *key = NULL; u_char *sig = NULL; - const char *alg = NULL; size_t slen = 0; int r, ret = -1; char data[1024]; + const char *alg; + ssh_compat ctx_compat = { 0, 0 }; if ((r = sshkey_load_public(filename, &key, NULL)) != 0) { error_r(r, "Couldn't read public key %s", filename); return -1; } + arc4random_buf(data, sizeof(data)); + + alg = sshkey_ssh_name(key); +#ifdef HAVE_EVP_SHA256 if (sshkey_type_plain(key->type) == KEY_RSA) alg = "rsa-sha2-256"; - arc4random_buf(data, sizeof(data)); - if ((r = ssh_agent_sign(agent_fd, key, &sig, &slen, data, sizeof(data), - alg, 0)) != 0) { +#endif + +{ ssh_sign_ctx ctx = { alg, key, &ctx_compat, NULL, NULL }; + + r = Xssh_agent_sign(agent_fd, &ctx, &sig, &slen, data, sizeof(data)); + if (r != 0) { error_r(r, "Agent signature failed for %s", filename); goto done; } - if ((r = sshkey_verify(key, sig, slen, data, sizeof(data), - alg, 0, NULL)) != 0) { +} +{ ssh_verify_ctx ctx = { alg, key, &ctx_compat }; + + r = Xkey_verify(&ctx, sig, slen, data, sizeof(data)); + if (r != 0) { error_r(r, "Signature verification failed for %s", filename); goto done; } +} /* success */ ret = 0; done: @@ -508,7 +528,7 @@ } static int -list_identities(int agent_fd, int do_fp) +list_identities(int agent_fd, int do_fp, int key_only) { char *fp; int r; @@ -533,12 +553,22 @@ sshkey_type(idlist->keys[i])); free(fp); } else { + int print_dn = !key_only && sshkey_is_x509(idlist->keys[i]); + if (print_dn) { + if(!Xkey_write_subject(NULL, + idlist->keys[i], stdout)) { + fprintf(stderr, + "Xkey_write_subject failed\n"); + continue; + } + } else if ((r = sshkey_write(idlist->keys[i], stdout)) != 0) { fprintf(stderr, "sshkey_write: %s\n", ssh_err(r)); continue; } - fprintf(stdout, " %s", idlist->comments[i]); + if (!print_dn) + fprintf(stdout, " %s", idlist->comments[i]); left = sshkey_signatures_left(idlist->keys[i]); if (left > 0) fprintf(stdout, @@ -581,200 +611,29 @@ } static int -load_resident_keys(int agent_fd, const char *skprovider, int qflag, - struct dest_constraint **dest_constraints, size_t ndest_constraints) -{ - struct sshsk_resident_key **srks; - size_t nsrks, i; - struct sshkey *key; - int r, ok = 0; - char *fp; - - pass = read_passphrase("Enter PIN for authenticator: ", RP_ALLOW_STDIN); - if ((r = sshsk_load_resident(skprovider, NULL, pass, 0, - &srks, &nsrks)) != 0) { - error_r(r, "Unable to load resident keys"); - return r; - } - for (i = 0; i < nsrks; i++) { - key = srks[i]->key; - if ((fp = sshkey_fingerprint(key, - fingerprint_hash, SSH_FP_DEFAULT)) == NULL) - fatal_f("sshkey_fingerprint failed"); - if ((r = ssh_add_identity_constrained(agent_fd, key, "", - lifetime, confirm, maxsign, skprovider, - dest_constraints, ndest_constraints)) != 0) { - error("Unable to add key %s %s", - sshkey_type(key), fp); - free(fp); - ok = r; - continue; - } - if (ok == 0) - ok = 1; - if (!qflag) { - fprintf(stderr, "Resident identity added: %s %s\n", - sshkey_type(key), fp); - if (lifetime != 0) { - fprintf(stderr, - "Lifetime set to %d seconds\n", lifetime); - } - if (confirm != 0) { - fprintf(stderr, "The user must confirm " - "each use of the key\n"); - } - } - free(fp); - } - sshsk_free_resident_keys(srks, nsrks); - if (nsrks == 0) - return SSH_ERR_KEY_NOT_FOUND; - return ok == 1 ? 0 : ok; -} - -static int do_file(int agent_fd, int deleting, int key_only, char *file, int qflag, - const char *skprovider, struct dest_constraint **dest_constraints, - size_t ndest_constraints) + const char *skprovider) { if (deleting) { if (delete_file(agent_fd, file, key_only, qflag) == -1) return -1; } else { - if (add_file(agent_fd, file, key_only, qflag, skprovider, - dest_constraints, ndest_constraints) == -1) + if (add_file(agent_fd, file, key_only, qflag, skprovider) == -1) return -1; } return 0; } -/* Append string 's' to a NULL-terminated array of strings */ -static void -stringlist_append(char ***listp, const char *s) -{ - size_t i = 0; - - if (*listp == NULL) - *listp = xcalloc(2, sizeof(**listp)); - else { - for (i = 0; (*listp)[i] != NULL; i++) - ; /* count */ - *listp = xrecallocarray(*listp, i + 1, i + 2, sizeof(**listp)); - } - (*listp)[i] = xstrdup(s); -} - -static void -parse_dest_constraint_hop(const char *s, struct dest_constraint_hop *dch, - char **hostkey_files) -{ - char *user = NULL, *host, *os, *path; - size_t i; - struct hostkeys *hostkeys; - const struct hostkey_entry *hke; - int r, want_ca; - - memset(dch, '\0', sizeof(*dch)); - os = xstrdup(s); - if ((host = strchr(os, '@')) == NULL) - host = os; - else { - *host++ = '\0'; - user = os; - } - cleanhostname(host); - /* Trivial case: username@ (all hosts) */ - if (*host == '\0') { - if (user == NULL) { - fatal("Invalid key destination constraint \"%s\": " - "does not specify user or host", s); - } - dch->user = xstrdup(user); - /* other fields left blank */ - free(os); - return; - } - if (hostkey_files == NULL) - fatal_f("no hostkey files"); - /* Otherwise we need to look up the keys for this hostname */ - hostkeys = init_hostkeys(); - for (i = 0; hostkey_files[i]; i++) { - path = tilde_expand_filename(hostkey_files[i], getuid()); - debug2_f("looking up host keys for \"%s\" in %s", host, path); - load_hostkeys(hostkeys, host, path, 0); - free(path); - } - dch->user = user == NULL ? NULL : xstrdup(user); - dch->hostname = xstrdup(host); - for (i = 0; i < hostkeys->num_entries; i++) { - hke = hostkeys->entries + i; - want_ca = hke->marker == MRK_CA; - if (hke->marker != MRK_NONE && !want_ca) - continue; - debug3_f("%s%s%s: adding %s %skey from %s:%lu as key %u", - user == NULL ? "": user, user == NULL ? "" : "@", - host, sshkey_type(hke->key), want_ca ? "CA " : "", - hke->file, hke->line, dch->nkeys); - dch->keys = xrecallocarray(dch->keys, dch->nkeys, - dch->nkeys + 1, sizeof(*dch->keys)); - dch->key_is_ca = xrecallocarray(dch->key_is_ca, dch->nkeys, - dch->nkeys + 1, sizeof(*dch->key_is_ca)); - if ((r = sshkey_from_private(hke->key, - &(dch->keys[dch->nkeys]))) != 0) - fatal_fr(r, "sshkey_from_private"); - dch->key_is_ca[dch->nkeys] = want_ca; - dch->nkeys++; - } - if (dch->nkeys == 0) - fatal("No host keys found for destination \"%s\"", host); - free_hostkeys(hostkeys); - free(os); - return; -} - -static void -parse_dest_constraint(const char *s, struct dest_constraint ***dcp, - size_t *ndcp, char **hostkey_files) -{ - struct dest_constraint *dc; - char *os, *cp; - - dc = xcalloc(1, sizeof(*dc)); - os = xstrdup(s); - if ((cp = strchr(os, '>')) == NULL) { - /* initial hop; no 'from' hop specified */ - parse_dest_constraint_hop(os, &dc->to, hostkey_files); - } else { - /* two hops specified */ - *(cp++) = '\0'; - parse_dest_constraint_hop(os, &dc->from, hostkey_files); - parse_dest_constraint_hop(cp, &dc->to, hostkey_files); - if (dc->from.user != NULL) { - fatal("Invalid key constraint %s: cannot specify " - "user on 'from' host", os); - } - } - /* XXX eliminate or error on duplicates */ - debug2_f("constraint %zu: %s%s%s (%u keys) > %s%s%s (%u keys)", *ndcp, - dc->from.user ? dc->from.user : "", dc->from.user ? "@" : "", - dc->from.hostname ? dc->from.hostname : "(ORIGIN)", dc->from.nkeys, - dc->to.user ? dc->to.user : "", dc->to.user ? "@" : "", - dc->to.hostname ? dc->to.hostname : "(ANY)", dc->to.nkeys); - *dcp = xrecallocarray(*dcp, *ndcp, *ndcp + 1, sizeof(**dcp)); - (*dcp)[(*ndcp)++] = dc; - free(os); -} - - static void usage(void) { fprintf(stderr, -"usage: ssh-add [-cDdKkLlqvXx] [-E fingerprint_hash] [-H hostkey_file]\n" -" [-h destination_constraint] [-S provider] [-t life]\n" +"usage: ssh-add [-cDdkLlqvXx] [-E fingerprint_hash] [-t life]\n"); #ifdef WITH_XMSS -" [-M maxsign] [-m minleft]\n" + fprintf(stderr, +" [-M maxsign] [-m minleft]\n"); #endif + fprintf(stderr, " [file ...]\n" " ssh-add -s pkcs11\n" " ssh-add -e pkcs11\n" @@ -789,18 +648,21 @@ extern int optind; int agent_fd; char *pkcs11provider = NULL, *skprovider = NULL; - char **dest_constraint_strings = NULL, **hostkey_files = NULL; - int r, i, ch, deleting = 0, ret = 0, key_only = 0, do_download = 0; + int r, i, ch, deleting = 0, ret = 0, key_only = 0; int xflag = 0, lflag = 0, Dflag = 0, qflag = 0, Tflag = 0; SyslogFacility log_facility = SYSLOG_FACILITY_AUTH; LogLevel log_level = SYSLOG_LEVEL_INFO; - struct dest_constraint **dest_constraints = NULL; - size_t ndest_constraints = 0; + ssh_malloc_init(); /* must be called before any mallocs */ /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ sanitise_stdfd(); __progname = ssh_get_progname(argv[0]); + ssh_OpenSSL_startup(); + fill_default_xkalg(); + + log_init(__progname, SYSLOG_LEVEL_INFO, SYSLOG_FACILITY_USER, 1); + seed_rng(); log_init(__progname, log_level, log_facility, 1); @@ -820,12 +682,10 @@ exit(2); } - skprovider = getenv("SSH_SK_PROVIDER"); - - while ((ch = getopt(argc, argv, "vkKlLcdDTxXE:e:h:H:M:m:qs:S:t:")) != -1) { + while ((ch = getopt(argc, argv, "vklLcdDTxXE:e:M:m:qs:S:t:")) != -1) { switch (ch) { case 'v': - if (log_level == SYSLOG_LEVEL_INFO) + if (log_level < SYSLOG_LEVEL_DEBUG1) log_level = SYSLOG_LEVEL_DEBUG1; else if (log_level < SYSLOG_LEVEL_DEBUG3) log_level++; @@ -835,18 +695,9 @@ if (fingerprint_hash == -1) fatal("Invalid hash algorithm \"%s\"", optarg); break; - case 'H': - stringlist_append(&hostkey_files, optarg); - break; - case 'h': - stringlist_append(&dest_constraint_strings, optarg); - break; case 'k': key_only = 1; break; - case 'K': - do_download = 1; - break; case 'l': case 'L': if (lflag != 0) @@ -862,6 +713,7 @@ case 'c': confirm = 1; break; + #ifdef WITH_XMSS case 'm': minleft = (u_int)strtonum(optarg, 1, UINT_MAX, NULL); if (minleft == 0) { @@ -878,6 +730,7 @@ goto done; } break; + #endif /*def WITH_XMSS*/ case 'd': deleting = 1; break; @@ -887,27 +740,22 @@ case 's': pkcs11provider = optarg; break; - case 'S': - skprovider = optarg; - break; case 'e': deleting = 1; pkcs11provider = optarg; break; case 't': - if ((lifetime = convtime(optarg)) == -1 || - lifetime < 0 || (u_long)lifetime > UINT32_MAX) { - fprintf(stderr, "Invalid lifetime\n"); + if (!set_lifetime(optarg)) { ret = 1; goto done; } break; - case 'q': - qflag = 1; - break; case 'T': Tflag = 1; break; + case 'q': + qflag = 1; + break; default: usage(); ret = 1; @@ -923,7 +771,7 @@ ret = 1; goto done; } else if (lflag) { - if (list_identities(agent_fd, lflag == 'l' ? 1 : 0) == -1) + if (list_identities(agent_fd, lflag == 'l' ? 1 : 0, key_only) == -1) ret = 1; goto done; } else if (Dflag) { @@ -932,25 +780,6 @@ goto done; } -#ifdef ENABLE_SK_INTERNAL - if (skprovider == NULL) - skprovider = "internal"; -#endif - - if (hostkey_files == NULL) { - /* use defaults from readconf.c */ - stringlist_append(&hostkey_files, _PATH_SSH_USER_HOSTFILE); - stringlist_append(&hostkey_files, _PATH_SSH_USER_HOSTFILE2); - stringlist_append(&hostkey_files, _PATH_SSH_SYSTEM_HOSTFILE); - stringlist_append(&hostkey_files, _PATH_SSH_SYSTEM_HOSTFILE2); - } - if (dest_constraint_strings != NULL) { - for (i = 0; dest_constraint_strings[i] != NULL; i++) { - parse_dest_constraint(dest_constraint_strings[i], - &dest_constraints, &ndest_constraints, hostkey_files); - } - } - argc -= optind; argv += optind; if (Tflag) { @@ -963,15 +792,7 @@ } if (pkcs11provider != NULL) { if (update_card(agent_fd, !deleting, pkcs11provider, - qflag, dest_constraints, ndest_constraints) == -1) - ret = 1; - goto done; - } - if (do_download) { - if (skprovider == NULL) - fatal("Cannot download keys without provider"); - if (load_resident_keys(agent_fd, skprovider, qflag, - dest_constraints, ndest_constraints) != 0) + qflag) == -1) ret = 1; goto done; } @@ -994,8 +815,7 @@ if (stat(buf, &st) == -1) continue; if (do_file(agent_fd, deleting, key_only, buf, - qflag, skprovider, - dest_constraints, ndest_constraints) == -1) + qflag, skprovider) == -1) ret = 1; else count++; @@ -1005,13 +825,13 @@ } else { for (i = 0; i < argc; i++) { if (do_file(agent_fd, deleting, key_only, - argv[i], qflag, skprovider, - dest_constraints, ndest_constraints) == -1) + argv[i], qflag, skprovider) == -1) ret = 1; } } -done: clear_pass(); + +done: ssh_close_authentication_socket(agent_fd); return ret; } diff -ruN openssh-9.4p1/ssh-agent.0 openssh-9.4p1+x509-14.2.1/ssh-agent.0 --- openssh-9.4p1/ssh-agent.0 2023-08-10 04:11:18.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/ssh-agent.0 2023-08-20 10:07:00.000000000 +0300 @@ -1,26 +1,30 @@ -SSH-AGENT(1) General Commands Manual SSH-AGENT(1) +SSH-AGENT(1) BSD General Commands Manual SSH-AGENT(1) NAME - ssh-agent M-bM-^@M-^S OpenSSH authentication agent + ssh-agent -- Authentication agent SYNOPSIS ssh-agent [-c | -s] [-Dd] [-a bind_address] [-E fingerprint_hash] - [-O option] [-P allowed_providers] [-t life] - ssh-agent [-a bind_address] [-E fingerprint_hash] [-O option] - [-P allowed_providers] [-t life] command [arg ...] + [-P allowed_providers] [-t life] + ssh-agent [-a bind_address] [-E fingerprint_hash] [-P allowed_providers] + [-t life] command [arg ...] ssh-agent [-c | -s] -k DESCRIPTION - ssh-agent is a program to hold private keys used for public key - authentication. Through use of environment variables the agent can be - located and automatically used for authentication when logging in to - other machines using ssh(1). + ssh-agent is a program to hold private keys used for public key authenti- + cation. It may contain X.509 certificates that match private keys and + extra certificates used to build chain of certificates leading to a + trusted certificate authority. + + Through use of environment variables the agent can be located and auto- + matically used for authentication when logging in to other machines using + ssh(1). The options are as follows: -a bind_address - Bind the agent to the UNIX-domain socket bind_address. The - default is $TMPDIR/ssh-XXXXXXXXXX/agent.. + Bind the agent to the UNIX-domain socket bind_address. The de- + fault is $TMPDIR/ssh-XXXXXXXXXX/agent.. -c Generate C-shell commands on stdout. This is the default if SHELL looks like it's a csh style of shell. @@ -32,41 +36,24 @@ fork and will write debug information to standard error. -E fingerprint_hash - Specifies the hash algorithm used when displaying key - fingerprints. Valid options are: M-bM-^@M-^\md5M-bM-^@M-^] and M-bM-^@M-^\sha256M-bM-^@M-^]. The - default is M-bM-^@M-^\sha256M-bM-^@M-^]. + Specifies the hash algorithm used when displaying key finger- + prints. Valid options are: "md5" and "sha256". The default is + "sha256". -k Kill the current agent (given by the SSH_AGENT_PID environment variable). - -O option - Specify an option when starting ssh-agent. Currently two options - are supported: allow-remote-pkcs11 and no-restrict-websafe. - - The allow-remote-pkcs11 option allows clients of a forwarded - ssh-agent to load PKCS#11 or FIDO provider libraries. By default - only local clients may perform this operation. Note that - signalling that an ssh-agent client is remote is performed by - ssh(1), and use of other tools to forward access to the agent - socket, may circumvent this restriction. - - The no-restrict-websafe option instructs ssh-agent to permit - signatures using FIDO keys that might be web authentication - requests. By default, ssh-agent refuses signature requests for - FIDO keys where the key application string does not start with - M-bM-^@M-^\ssh:M-bM-^@M-^] and when the data to be signed does not appear to be a - ssh(1) user authentication request or a ssh-keygen(1) signature. - The default behaviour prevents forwarded access to a FIDO key - from also implicitly forwarding the ability to authenticate to - websites. - -P allowed_providers Specify a pattern-list of acceptable paths for PKCS#11 provider - and FIDO authenticator middleware shared libraries that may be - used with the -S or -s options to ssh-add(1). Libraries that do - not match the pattern list will be refused. See PATTERNS in - ssh_config(5) for a description of pattern-list syntax. The - default list is M-bM-^@M-^\/usr/lib/*,/usr/local/lib/*M-bM-^@M-^]. + shared libraries that may be used with the -s option to + ssh-add(1). Libraries that do not match the pattern list will be + refused. See PATTERNS in ssh_config(5) for a description of pat- + tern-list syntax. For security reasons the default pattern is + "!*" , i.e. does not allow any PKCS#11 provider. + + Note the pattern-list could be redefined at build time. It is + strongly recommended pattern to match only trusted PKCS#11 + provider libraries. -s Generate Bourne shell commands on stdout. This is the default if SHELL does not look like it's a csh style of shell. @@ -91,8 +78,8 @@ The second method is used for a login session. When ssh-agent is started, it prints the shell commands required to set its environment - variables, which in turn can be evaluated in the calling shell, for - example eval `ssh-agent -s`. + variables, which in turn can be evaluated in the calling shell, for exam- + ple eval `ssh-agent -s`. In both cases, ssh(1) looks at these environment variables and uses them to establish a connection to the agent. @@ -100,41 +87,54 @@ The agent initially does not have any private keys. Keys are added using ssh-add(1) or by ssh(1) when AddKeysToAgent is set in ssh_config(5). Multiple identities may be stored in ssh-agent concurrently and ssh(1) - will automatically use them if present. ssh-add(1) is also used to - remove keys from ssh-agent and to query the keys that are held in one. + will automatically use them if present. ssh-add(1) is also used to re- + move keys from ssh-agent and to query the keys that are held in one. Connections to ssh-agent may be forwarded from further remote hosts using - the -A option to ssh(1) (but see the caveats documented therein), - avoiding the need for authentication data to be stored on other machines. - Authentication passphrases and private keys never go over the network: - the connection to the agent is forwarded over SSH remote connections and - the result is returned to the requester, allowing the user access to - their identities anywhere in the network in a secure fashion. + the -A option to ssh(1) (but see the caveats documented therein), avoid- + ing the need for authentication data to be stored on other machines. Au- + thentication passphrases and private keys never go over the network: the + connection to the agent is forwarded over SSH remote connections and the + result is returned to the requester, allowing the user access to their + identities anywhere in the network in a secure fashion. ENVIRONMENT - SSH_AGENT_PID When ssh-agent starts, it stores the name of the agent's - process ID (PID) in this variable. - - SSH_AUTH_SOCK When ssh-agent starts, it creates a UNIX-domain socket and - stores its pathname in this variable. It is accessible - only to the current user, but is easily abused by root or - another instance of the same user. + SSH_AGENT_PID + When ssh-agent starts, it stores the name of the agent's process + ID (PID) in this variable. + + SSH_ASKPASS + If key operation needs a confirmation or passphrase, and DISPLAY + is set ssh-agent will use ssh-askpass(1) to interact with user. + By default will be executed program ssh-askpass located in + "libexec" directory but if SSH_ASKPASS is set, will be executed + program specified by SSH_ASKPASS. Program may open a X11 window + to ask user for confirmation or passphrase. + + Remark: On Android DISPLAY is ignored. + + SSH_AUTH_SOCK + When ssh-agent starts, it creates a UNIX-domain socket and stores + its pathname in this variable. It is accessible only to the cur- + rent user, but is easily abused by root or another instance of + the same user. FILES $TMPDIR/ssh-XXXXXXXXXX/agent. - UNIX-domain sockets used to contain the connection to the - authentication agent. These sockets should only be readable by - the owner. The sockets should get automatically removed when the + UNIX-domain sockets used to contain the connection to the authen- + tication agent. These sockets should only be readable by the + owner. The sockets should get automatically removed when the agent exits. SEE ALSO - ssh(1), ssh-add(1), ssh-keygen(1), ssh_config(5), sshd(8) + ssh(1), ssh-add(1), ssh-askpass(1), ssh-keygen(1), ssh_config(5), sshd(8) AUTHORS - OpenSSH is a derivative of the original and free ssh 1.2.12 release by + PKIX-SSH is a derivative of the original and free ssh 1.2.12 release by Tatu Ylonen. Aaron Campbell, Bob Beck, Markus Friedl, Niels Provos, Theo - de Raadt and Dug Song removed many bugs, re-added newer features and - created OpenSSH. Markus Friedl contributed the support for SSH protocol - versions 1.5 and 2.0. + de Raadt and Dug Song removed many bugs, re-added newer features and cre- + ated OpenSSH. Markus Friedl contributed the support for SSH protocol + versions 1.5 and 2.0. Roumen Petrov contributed support for X.509 cer- + tificates. -OpenBSD 7.3 July 23, 2023 OpenBSD 7.3 +BSD 23 Jul 2023 BSD diff -ruN openssh-9.4p1/ssh-agent.1 openssh-9.4p1+x509-14.2.1/ssh-agent.1 --- openssh-9.4p1/ssh-agent.1 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/ssh-agent.1 2023-08-20 10:07:00.000000000 +0300 @@ -1,4 +1,4 @@ -.\" $OpenBSD: ssh-agent.1,v 1.78 2023/07/23 20:04:45 naddy Exp $ +.\" $OpenBSD: ssh-agent.1,v 1.75 2022/10/07 06:00:58 jmc Exp $ .\" .\" Author: Tatu Ylonen .\" Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -13,6 +13,7 @@ .\" Copyright (c) 1999,2000 Markus Friedl. All rights reserved. .\" Copyright (c) 1999 Aaron Campbell. All rights reserved. .\" Copyright (c) 1999 Theo de Raadt. All rights reserved. +.\" Copyright (c) 2002-2023 Roumen Petrov. All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions @@ -34,25 +35,31 @@ .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.Dd $Mdocdate: July 23 2023 $ +.\" Implement .Dd with the Mdocdate RCS keyword +.rn Dd xD +.de Dd +.ie \\$1$Mdocdate: \{\ +. xD \\$3 \\$2 \\$4 +.\} +.el .xD \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 +.. +.Dd $Mdocdate: Jul 23 2023 $ .Dt SSH-AGENT 1 .Os .Sh NAME .Nm ssh-agent -.Nd OpenSSH authentication agent +.Nd Authentication agent .Sh SYNOPSIS .Nm ssh-agent .Op Fl c | s .Op Fl \&Dd .Op Fl a Ar bind_address .Op Fl E Ar fingerprint_hash -.Op Fl O Ar option .Op Fl P Ar allowed_providers .Op Fl t Ar life .Nm ssh-agent .Op Fl a Ar bind_address .Op Fl E Ar fingerprint_hash -.Op Fl O Ar option .Op Fl P Ar allowed_providers .Op Fl t Ar life .Ar command Op Ar arg ... @@ -62,6 +69,10 @@ .Sh DESCRIPTION .Nm is a program to hold private keys used for public key authentication. +It may contain X.509 certificates that match private keys and +extra certificates used to build chain of certificates +leading to a trusted certificate authority. +.Pp Through use of environment variables the agent can be located and automatically used for authentication when logging in to other machines using @@ -104,59 +115,22 @@ Kill the current agent (given by the .Ev SSH_AGENT_PID environment variable). -.It Fl O Ar option -Specify an option when starting -.Nm . -Currently two options are supported: -.Cm allow-remote-pkcs11 -and -.Cm no-restrict-websafe . -.Pp -The -.Cm allow-remote-pkcs11 -option allows clients of a forwarded -.Nm -to load PKCS#11 or FIDO provider libraries. -By default only local clients may perform this operation. -Note that signalling that an -.Nm -client is remote is performed by -.Xr ssh 1 , -and use of other tools to forward access to the agent socket, may circumvent -this restriction. -.Pp -The -.Cm no-restrict-websafe -option instructs -.Nm -to permit signatures using FIDO keys that might be web authentication -requests. -By default, -.Nm -refuses signature requests for FIDO keys where the key application string -does not start with -.Dq ssh: -and when the data to be signed does not appear to be a -.Xr ssh 1 -user authentication request or a -.Xr ssh-keygen 1 -signature. -The default behaviour prevents forwarded access to a FIDO key from also -implicitly forwarding the ability to authenticate to websites. .It Fl P Ar allowed_providers -Specify a pattern-list of acceptable paths for PKCS#11 provider and FIDO -authenticator middleware shared libraries that may be used with the -.Fl S -or +Specify a pattern-list of acceptable paths for PKCS#11 provider shared +libraries that may be used with the .Fl s -options to +option to .Xr ssh-add 1 . Libraries that do not match the pattern list will be refused. See PATTERNS in .Xr ssh_config 5 for a description of pattern-list syntax. -The default list is -.Dq /usr/lib/*,/usr/local/lib/* . +For security reasons the default pattern is +.Dq !* +, i.e. does not allow any PKCS#11 provider. +.Pp +Note the pattern-list could be redefined at build time. +It is strongly recommended pattern to match only trusted PKCS#11 provider libraries. .It Fl s Generate Bourne shell commands on .Dv stdout . @@ -234,11 +208,32 @@ allowing the user access to their identities anywhere in the network in a secure fashion. .Sh ENVIRONMENT -.Bl -tag -width "SSH_AGENT_PID" +.Bl -tag -width Ds .It Ev SSH_AGENT_PID When .Nm starts, it stores the name of the agent's process ID (PID) in this variable. +.It Ev SSH_ASKPASS +If key operation needs a confirmation or passphrase, and +.Ev DISPLAY +is set +.Nm +will use +.Xr ssh-askpass 1 +to interact with user. +By default will be executed program +.Nm ssh-askpass +located in +.Dq libexec +directory but if +.Ev SSH_ASKPASS +is set, will be executed program specified by +.Ev SSH_ASKPASS . +Program may open a X11 window to ask user for confirmation or passphrase. +.Pp +Remark: On Android +.Ev DISPLAY +is ignored. .It Ev SSH_AUTH_SOCK When .Nm @@ -259,12 +254,13 @@ .Sh SEE ALSO .Xr ssh 1 , .Xr ssh-add 1 , +.Xr ssh-askpass 1 , .Xr ssh-keygen 1 , .Xr ssh_config 5 , .Xr sshd 8 .Sh AUTHORS .An -nosplit -OpenSSH is a derivative of the original and free ssh 1.2.12 release by +PKIX-SSH is a derivative of the original and free ssh 1.2.12 release by .An Tatu Ylonen . .An Aaron Campbell , Bob Beck , Markus Friedl , Niels Provos , Theo de Raadt and @@ -272,3 +268,5 @@ removed many bugs, re-added newer features and created OpenSSH. .An Markus Friedl contributed the support for SSH protocol versions 1.5 and 2.0. +.An Roumen Petrov +contributed support for X.509 certificates. diff -ruN openssh-9.4p1/ssh-agent.c openssh-9.4p1+x509-14.2.1/ssh-agent.c --- openssh-9.4p1/ssh-agent.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/ssh-agent.c 2023-08-20 10:07:01.000000000 +0300 @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-agent.c,v 1.300 2023/07/19 13:56:33 djm Exp $ */ +/* $OpenBSD: ssh-agent.c,v 1.299 2023/07/10 04:51:26 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -12,6 +12,7 @@ * called by a name other than "ssh" or "Secure Shell". * * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. + * Copyright (c) 2002-2023 Roumen Petrov. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -36,11 +37,9 @@ #include "includes.h" -#include #include #include #include -#include #ifdef HAVE_SYS_TIME_H # include #endif @@ -51,7 +50,10 @@ #ifdef WITH_OPENSSL #include -#include "openbsd-compat/openssl-compat.h" +#include "evp-compat.h" +#ifdef HAVE_FIPSCHECK_H +# include +#endif #endif #include @@ -62,6 +64,10 @@ #endif #ifdef HAVE_POLL_H # include +#else +# ifdef HAVE_SYS_POLL_H +# include +# endif #endif #include #include @@ -76,37 +82,26 @@ #include "xmalloc.h" #include "ssh.h" -#include "ssh2.h" #include "sshbuf.h" -#include "sshkey.h" +#include "ssh-x509.h" +#include "ssh-xkalg.h" #include "authfd.h" +#include "compat.h" #include "log.h" #include "misc.h" #include "digest.h" #include "ssherr.h" #include "match.h" -#include "msg.h" -#include "pathnames.h" #include "ssh-pkcs11.h" -#include "sk-api.h" -#include "myproposal.h" #ifndef DEFAULT_ALLOWED_PROVIDERS -# define DEFAULT_ALLOWED_PROVIDERS "/usr/lib*/*,/usr/local/lib*/*" +# define DEFAULT_ALLOWED_PROVIDERS "!*" #endif /* Maximum accepted message length */ -#define AGENT_MAX_LEN (256*1024) +#define AGENT_MAX_LEN (256*1024) /* Maximum bytes to read from client socket */ -#define AGENT_RBUF_LEN (4096) -/* Maximum number of recorded session IDs/hostkeys per connection */ -#define AGENT_MAX_SESSION_IDS 16 -/* Maximum size of session ID */ -#define AGENT_MAX_SID_LEN 128 -/* Maximum number of destination constraints to accept on a key */ -#define AGENT_MAX_DEST_CONSTRAINTS 1024 - -/* XXX store hostkey_sid in a refcounted tree */ +#define AGENT_RBUF_LEN (4096) typedef enum { AUTH_UNUSED = 0, @@ -114,20 +109,12 @@ AUTH_CONNECTION = 2, } sock_type; -struct hostkey_sid { - struct sshkey *key; - struct sshbuf *sid; - int forwarded; -}; - typedef struct socket_entry { int fd; sock_type type; struct sshbuf *input; struct sshbuf *output; struct sshbuf *request; - size_t nsession_ids; - struct hostkey_sid *session_ids; } SocketEntry; u_int sockets_alloc = 0; @@ -140,9 +127,6 @@ char *provider; time_t death; u_int confirm; - char *sk_provider; - struct dest_constraint *dest_constraints; - size_t ndest_constraints; } Identity; struct idtable { @@ -166,14 +150,8 @@ char socket_name[PATH_MAX]; char socket_dir[PATH_MAX]; -/* Pattern-list of allowed PKCS#11/Security key paths */ -static char *allowed_providers; - -/* - * Allows PKCS11 providers or SK keys that use non-internal providers to - * be added over a remote connection (identified by session-bind@openssh.com). - */ -static int remote_add_provider; +/* Pattern-list of allowed PKCS#11 paths */ +static char *allowed_providers = NULL; /* locking */ #define LOCK_SIZE 32 @@ -186,27 +164,35 @@ extern char *__progname; /* Default lifetime in seconds (0 == forever) */ -static int lifetime = 0; +static u_int lifetime = 0; +static int/*bool*/ +set_lifetime(const char *val) +{ long t = convtime(val); + if (t == -1) { + fprintf(stderr, "Invalid lifetime\n"); + return 0; + } +/* Note u_int32_t is size used in communication to agent + * (see SSH_AGENT_CONSTRAIN_LIFETIME). */ +#if SIZEOF_LONG_INT > SIZEOF_INT + if (t > UINT32_MAX) { + fprintf(stderr, "Lifetime too high\n"); + return 0; + } +#endif + lifetime = (u_int)t; /*safe cast*/ + return 1; +} static int fingerprint_hash = SSH_FP_HASH_DEFAULT; -/* Refuse signing of non-SSH messages for web-origin FIDO keys */ -static int restrict_websafe = 1; - static void close_socket(SocketEntry *e) { - size_t i; - close(e->fd); sshbuf_free(e->input); sshbuf_free(e->output); sshbuf_free(e->request); - for (i = 0; i < e->nsession_ids; i++) { - sshkey_free(e->session_ids[i].key); - sshbuf_free(e->session_ids[i].sid); - } - free(e->session_ids); memset(e, '\0', sizeof(*e)); e->fd = -1; e->type = AUTH_UNUSED; @@ -221,252 +207,19 @@ } static void -free_dest_constraint_hop(struct dest_constraint_hop *dch) -{ - u_int i; - - if (dch == NULL) - return; - free(dch->user); - free(dch->hostname); - for (i = 0; i < dch->nkeys; i++) - sshkey_free(dch->keys[i]); - free(dch->keys); - free(dch->key_is_ca); -} - -static void -free_dest_constraints(struct dest_constraint *dcs, size_t ndcs) -{ - size_t i; - - for (i = 0; i < ndcs; i++) { - free_dest_constraint_hop(&dcs[i].from); - free_dest_constraint_hop(&dcs[i].to); - } - free(dcs); -} - -static void free_identity(Identity *id) { sshkey_free(id->key); free(id->provider); free(id->comment); - free(id->sk_provider); - free_dest_constraints(id->dest_constraints, id->ndest_constraints); free(id); } -/* - * Match 'key' against the key/CA list in a destination constraint hop - * Returns 0 on success or -1 otherwise. - */ -static int -match_key_hop(const char *tag, const struct sshkey *key, - const struct dest_constraint_hop *dch) -{ - const char *reason = NULL; - const char *hostname = dch->hostname ? dch->hostname : "(ORIGIN)"; - u_int i; - char *fp; - - if (key == NULL) - return -1; - /* XXX logspam */ - if ((fp = sshkey_fingerprint(key, SSH_FP_HASH_DEFAULT, - SSH_FP_DEFAULT)) == NULL) - fatal_f("fingerprint failed"); - debug3_f("%s: entering hostname %s, requested key %s %s, %u keys avail", - tag, hostname, sshkey_type(key), fp, dch->nkeys); - free(fp); - for (i = 0; i < dch->nkeys; i++) { - if (dch->keys[i] == NULL) - return -1; - /* XXX logspam */ - if ((fp = sshkey_fingerprint(dch->keys[i], SSH_FP_HASH_DEFAULT, - SSH_FP_DEFAULT)) == NULL) - fatal_f("fingerprint failed"); - debug3_f("%s: key %u: %s%s %s", tag, i, - dch->key_is_ca[i] ? "CA " : "", - sshkey_type(dch->keys[i]), fp); - free(fp); - if (!sshkey_is_cert(key)) { - /* plain key */ - if (dch->key_is_ca[i] || - !sshkey_equal(key, dch->keys[i])) - continue; - return 0; - } - /* certificate */ - if (!dch->key_is_ca[i]) - continue; - if (key->cert == NULL || key->cert->signature_key == NULL) - return -1; /* shouldn't happen */ - if (!sshkey_equal(key->cert->signature_key, dch->keys[i])) - continue; - if (sshkey_cert_check_host(key, hostname, 1, - SSH_ALLOWED_CA_SIGALGS, &reason) != 0) { - debug_f("cert %s / hostname %s rejected: %s", - key->cert->key_id, hostname, reason); - continue; - } - return 0; - } - return -1; -} - -/* Check destination constraints on an identity against the hostkey/user */ -static int -permitted_by_dest_constraints(const struct sshkey *fromkey, - const struct sshkey *tokey, Identity *id, const char *user, - const char **hostnamep) -{ - size_t i; - struct dest_constraint *d; - - if (hostnamep != NULL) - *hostnamep = NULL; - for (i = 0; i < id->ndest_constraints; i++) { - d = id->dest_constraints + i; - /* XXX remove logspam */ - debug2_f("constraint %zu %s%s%s (%u keys) > %s%s%s (%u keys)", - i, d->from.user ? d->from.user : "", - d->from.user ? "@" : "", - d->from.hostname ? d->from.hostname : "(ORIGIN)", - d->from.nkeys, - d->to.user ? d->to.user : "", d->to.user ? "@" : "", - d->to.hostname ? d->to.hostname : "(ANY)", d->to.nkeys); - - /* Match 'from' key */ - if (fromkey == NULL) { - /* We are matching the first hop */ - if (d->from.hostname != NULL || d->from.nkeys != 0) - continue; - } else if (match_key_hop("from", fromkey, &d->from) != 0) - continue; - - /* Match 'to' key */ - if (tokey != NULL && match_key_hop("to", tokey, &d->to) != 0) - continue; - - /* Match user if specified */ - if (d->to.user != NULL && user != NULL && - !match_pattern(user, d->to.user)) - continue; - - /* successfully matched this constraint */ - if (hostnamep != NULL) - *hostnamep = d->to.hostname; - debug2_f("allowed for hostname %s", - d->to.hostname == NULL ? "*" : d->to.hostname); - return 0; - } - /* no match */ - debug2_f("%s identity \"%s\" not permitted for this destination", - sshkey_type(id->key), id->comment); - return -1; -} - -/* - * Check whether hostkeys on a SocketEntry and the optionally specified user - * are permitted by the destination constraints on the Identity. - * Returns 0 on success or -1 otherwise. - */ -static int -identity_permitted(Identity *id, SocketEntry *e, char *user, - const char **forward_hostnamep, const char **last_hostnamep) -{ - size_t i; - const char **hp; - struct hostkey_sid *hks; - const struct sshkey *fromkey = NULL; - const char *test_user; - char *fp1, *fp2; - - /* XXX remove logspam */ - debug3_f("entering: key %s comment \"%s\", %zu socket bindings, " - "%zu constraints", sshkey_type(id->key), id->comment, - e->nsession_ids, id->ndest_constraints); - if (id->ndest_constraints == 0) - return 0; /* unconstrained */ - if (e->nsession_ids == 0) - return 0; /* local use */ - /* - * Walk through the hops recorded by session_id and try to find a - * constraint that satisfies each. - */ - for (i = 0; i < e->nsession_ids; i++) { - hks = e->session_ids + i; - if (hks->key == NULL) - fatal_f("internal error: no bound key"); - /* XXX remove logspam */ - fp1 = fp2 = NULL; - if (fromkey != NULL && - (fp1 = sshkey_fingerprint(fromkey, SSH_FP_HASH_DEFAULT, - SSH_FP_DEFAULT)) == NULL) - fatal_f("fingerprint failed"); - if ((fp2 = sshkey_fingerprint(hks->key, SSH_FP_HASH_DEFAULT, - SSH_FP_DEFAULT)) == NULL) - fatal_f("fingerprint failed"); - debug3_f("socketentry fd=%d, entry %zu %s, " - "from hostkey %s %s to user %s hostkey %s %s", - e->fd, i, hks->forwarded ? "FORWARD" : "AUTH", - fromkey ? sshkey_type(fromkey) : "(ORIGIN)", - fromkey ? fp1 : "", user ? user : "(ANY)", - sshkey_type(hks->key), fp2); - free(fp1); - free(fp2); - /* - * Record the hostnames for the initial forwarding and - * the final destination. - */ - hp = NULL; - if (i == e->nsession_ids - 1) - hp = last_hostnamep; - else if (i == 0) - hp = forward_hostnamep; - /* Special handling for final recorded binding */ - test_user = NULL; - if (i == e->nsession_ids - 1) { - /* Can only check user at final hop */ - test_user = user; - /* - * user is only presented for signature requests. - * If this is the case, make sure last binding is not - * for a forwarding. - */ - if (hks->forwarded && user != NULL) { - error_f("tried to sign on forwarding hop"); - return -1; - } - } else if (!hks->forwarded) { - error_f("tried to forward though signing bind"); - return -1; - } - if (permitted_by_dest_constraints(fromkey, hks->key, id, - test_user, hp) != 0) - return -1; - fromkey = hks->key; - } - /* - * Another special case: if the last bound session ID was for a - * forwarding, and this function is not being called to check a sign - * request (i.e. no 'user' supplied), then only permit the key if - * there is a permission that would allow it to be used at another - * destination. This hides keys that are allowed to be used to - * authenticate *to* a host but not permitted for *use* beyond it. - */ - hks = &e->session_ids[e->nsession_ids - 1]; - if (hks->forwarded && user == NULL && - permitted_by_dest_constraints(hks->key, NULL, id, - NULL, NULL) != 0) { - debug3_f("key permitted at host but not after"); - return -1; - } - - /* success */ - return 0; +static int/*bool*/ +key_match(const struct sshkey *key, struct sshkey *found) { + return sshkey_is_x509(found) + ? sshkey_equal_public(key, found) + : sshkey_equal(key, found); } /* return matching private key for given public key */ @@ -476,7 +229,7 @@ Identity *id; TAILQ_FOREACH(id, &idtab->idlist, next) { - if (sshkey_equal(key, id->key)) + if (key_match(key, id->key)) return (id); } return (NULL); @@ -516,343 +269,103 @@ process_request_identities(SocketEntry *e) { Identity *id; - struct sshbuf *msg, *keys; + struct sshbuf *msg; int r; - u_int nentries = 0; - - debug2_f("entering"); - if ((msg = sshbuf_new()) == NULL || (keys = sshbuf_new()) == NULL) + if ((msg = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); + if ((r = sshbuf_put_u8(msg, SSH2_AGENT_IDENTITIES_ANSWER)) != 0 || + (r = sshbuf_put_u32(msg, idtab->nentries)) != 0) + fatal_fr(r, "compose"); TAILQ_FOREACH(id, &idtab->idlist, next) { - /* identity not visible, don't include in response */ - if (identity_permitted(id, e, NULL, NULL, NULL) != 0) - continue; - if ((r = sshkey_puts_opts(id->key, keys, - SSHKEY_SERIALIZE_INFO)) != 0 || - (r = sshbuf_put_cstring(keys, id->comment)) != 0) { + if ((r = Akey_puts_opts(id->key, msg, SSHKEY_SERIALIZE_INFO)) != 0 || + (r = sshbuf_put_cstring(msg, id->comment)) != 0) { error_fr(r, "compose key/comment"); continue; } - nentries++; } - debug2_f("replying with %u allowed of %u available keys", - nentries, idtab->nentries); - if ((r = sshbuf_put_u8(msg, SSH2_AGENT_IDENTITIES_ANSWER)) != 0 || - (r = sshbuf_put_u32(msg, nentries)) != 0 || - (r = sshbuf_putb(msg, keys)) != 0) - fatal_fr(r, "compose"); if ((r = sshbuf_put_stringb(e->output, msg)) != 0) fatal_fr(r, "enqueue"); sshbuf_free(msg); - sshbuf_free(keys); } -static char * -agent_decode_alg(struct sshkey *key, u_int flags) +static const char* +agent_recode_alg(const char *pkalg, u_int flags) { - if (key->type == KEY_RSA) { +#ifdef HAVE_EVP_SHA256 + if (strcmp(pkalg, "ssh-rsa") == 0) { if (flags & SSH_AGENT_RSA_SHA2_256) return "rsa-sha2-256"; - else if (flags & SSH_AGENT_RSA_SHA2_512) + if (flags & SSH_AGENT_RSA_SHA2_512) return "rsa-sha2-512"; - } else if (key->type == KEY_RSA_CERT) { - if (flags & SSH_AGENT_RSA_SHA2_256) - return "rsa-sha2-256-cert-v01@openssh.com"; - else if (flags & SSH_AGENT_RSA_SHA2_512) - return "rsa-sha2-512-cert-v01@openssh.com"; } - return NULL; -} - -/* - * Attempt to parse the contents of a buffer as a SSH publickey userauth - * request, checking its contents for consistency and matching the embedded - * key against the one that is being used for signing. - * Note: does not modify msg buffer. - * Optionally extract the username, session ID and/or hostkey from the request. - */ -static int -parse_userauth_request(struct sshbuf *msg, const struct sshkey *expected_key, - char **userp, struct sshbuf **sess_idp, struct sshkey **hostkeyp) -{ - struct sshbuf *b = NULL, *sess_id = NULL; - char *user = NULL, *service = NULL, *method = NULL, *pkalg = NULL; - int r; - u_char t, sig_follows; - struct sshkey *mkey = NULL, *hostkey = NULL; - - if (userp != NULL) - *userp = NULL; - if (sess_idp != NULL) - *sess_idp = NULL; - if (hostkeyp != NULL) - *hostkeyp = NULL; - if ((b = sshbuf_fromb(msg)) == NULL) - fatal_f("sshbuf_fromb"); - - /* SSH userauth request */ - if ((r = sshbuf_froms(b, &sess_id)) != 0) - goto out; - if (sshbuf_len(sess_id) == 0) { - r = SSH_ERR_INVALID_FORMAT; - goto out; - } - if ((r = sshbuf_get_u8(b, &t)) != 0 || /* SSH2_MSG_USERAUTH_REQUEST */ - (r = sshbuf_get_cstring(b, &user, NULL)) != 0 || /* server user */ - (r = sshbuf_get_cstring(b, &service, NULL)) != 0 || /* service */ - (r = sshbuf_get_cstring(b, &method, NULL)) != 0 || /* method */ - (r = sshbuf_get_u8(b, &sig_follows)) != 0 || /* sig-follows */ - (r = sshbuf_get_cstring(b, &pkalg, NULL)) != 0 || /* alg */ - (r = sshkey_froms(b, &mkey)) != 0) /* key */ - goto out; - if (t != SSH2_MSG_USERAUTH_REQUEST || - sig_follows != 1 || - strcmp(service, "ssh-connection") != 0 || - !sshkey_equal(expected_key, mkey) || - sshkey_type_from_name(pkalg) != expected_key->type) { - r = SSH_ERR_INVALID_FORMAT; - goto out; - } - if (strcmp(method, "publickey-hostbound-v00@openssh.com") == 0) { - if ((r = sshkey_froms(b, &hostkey)) != 0) - goto out; - } else if (strcmp(method, "publickey") != 0) { - r = SSH_ERR_INVALID_FORMAT; - goto out; - } - if (sshbuf_len(b) != 0) { - r = SSH_ERR_INVALID_FORMAT; - goto out; - } - /* success */ - r = 0; - debug3_f("well formed userauth"); - if (userp != NULL) { - *userp = user; - user = NULL; - } - if (sess_idp != NULL) { - *sess_idp = sess_id; - sess_id = NULL; - } - if (hostkeyp != NULL) { - *hostkeyp = hostkey; - hostkey = NULL; - } - out: - sshbuf_free(b); - sshbuf_free(sess_id); - free(user); - free(service); - free(method); - free(pkalg); - sshkey_free(mkey); - sshkey_free(hostkey); - return r; -} - -/* - * Attempt to parse the contents of a buffer as a SSHSIG signature request. - * Note: does not modify buffer. - */ -static int -parse_sshsig_request(struct sshbuf *msg) -{ - int r; - struct sshbuf *b; - - if ((b = sshbuf_fromb(msg)) == NULL) - fatal_f("sshbuf_fromb"); - - if ((r = sshbuf_cmp(b, 0, "SSHSIG", 6)) != 0 || - (r = sshbuf_consume(b, 6)) != 0 || - (r = sshbuf_get_cstring(b, NULL, NULL)) != 0 || /* namespace */ - (r = sshbuf_get_string_direct(b, NULL, NULL)) != 0 || /* reserved */ - (r = sshbuf_get_cstring(b, NULL, NULL)) != 0 || /* hashalg */ - (r = sshbuf_get_string_direct(b, NULL, NULL)) != 0) /* H(msg) */ - goto out; - if (sshbuf_len(b) != 0) { - r = SSH_ERR_INVALID_FORMAT; - goto out; - } - /* success */ - r = 0; - out: - sshbuf_free(b); - return r; -} - -/* - * This function inspects a message to be signed by a FIDO key that has a - * web-like application string (i.e. one that does not begin with "ssh:". - * It checks that the message is one of those expected for SSH operations - * (pubkey userauth, sshsig, CA key signing) to exclude signing challenges - * for the web. - */ -static int -check_websafe_message_contents(struct sshkey *key, struct sshbuf *data) -{ - if (parse_userauth_request(data, key, NULL, NULL, NULL) == 0) { - debug_f("signed data matches public key userauth request"); - return 1; - } - if (parse_sshsig_request(data) == 0) { - debug_f("signed data matches SSHSIG signature request"); - return 1; - } - - /* XXX check CA signature operation */ - - error("web-origin key attempting to sign non-SSH message"); - return 0; -} - -static int -buf_equal(const struct sshbuf *a, const struct sshbuf *b) -{ - if (sshbuf_ptr(a) == NULL || sshbuf_ptr(b) == NULL) - return SSH_ERR_INVALID_ARGUMENT; - if (sshbuf_len(a) != sshbuf_len(b)) - return SSH_ERR_INVALID_FORMAT; - if (timingsafe_bcmp(sshbuf_ptr(a), sshbuf_ptr(b), sshbuf_len(a)) != 0) - return SSH_ERR_INVALID_FORMAT; - return 0; +#else + UNUSED(flags); +#endif /*def HAVE_EVP_SHA256*/ + return pkalg; } /* ssh2 only */ static void process_sign_request2(SocketEntry *e) { + const u_char *data; u_char *signature = NULL; - size_t slen = 0; - u_int compat = 0, flags; - int r, ok = -1, retried = 0; - char *fp = NULL, *pin = NULL, *prompt = NULL; - char *user = NULL, *sig_dest = NULL; - const char *fwd_host = NULL, *dest_host = NULL; - struct sshbuf *msg = NULL, *data = NULL, *sid = NULL; - struct sshkey *key = NULL, *hostkey = NULL; + size_t dlen, slen = 0; + ssh_compat ctx_compat = { 0, 0 }; + u_int flags; + int r, ok = -1; + struct sshbuf *msg; + struct sshkey *key = NULL; + char *pkalg = NULL; struct identity *id; - struct notifier_ctx *notifier = NULL; - debug_f("entering"); - - if ((msg = sshbuf_new()) == NULL || (data = sshbuf_new()) == NULL) + if ((msg = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); - if ((r = sshkey_froms(e->request, &key)) != 0 || - (r = sshbuf_get_stringb(e->request, data)) != 0 || + +{ u_char *blob = NULL; + size_t blen; + + if ((r = sshbuf_get_string(e->request, &blob, &blen)) != 0 || + (r = parse_key_from_blob(blob, blen, &key, &pkalg)) != 0) { + free(blob); + error_fr(r, "parse key"); + goto send; + } + free(blob); +} + if ( + (r = sshbuf_get_string_direct(e->request, &data, &dlen)) != 0 || (r = sshbuf_get_u32(e->request, &flags)) != 0) { error_fr(r, "parse"); goto send; } + if (flags & SSH_AGENT_RFC6187_OPAQUE_ECDSA_SIGNATURE) + ctx_compat.extra = SSHX_RFC6187_ASN1_OPAQUE_ECDSA_SIGNATURE; if ((id = lookup_identity(key)) == NULL) { - verbose_f("%s key not found", sshkey_type(key)); + error_f("%s key not found", sshkey_type(key)); goto send; } - if ((fp = sshkey_fingerprint(key, SSH_FP_HASH_DEFAULT, - SSH_FP_DEFAULT)) == NULL) - fatal_f("fingerprint failed"); - - if (id->ndest_constraints != 0) { - if (e->nsession_ids == 0) { - logit_f("refusing use of destination-constrained key " - "to sign on unbound connection"); - goto send; - } - if (parse_userauth_request(data, key, &user, &sid, - &hostkey) != 0) { - logit_f("refusing use of destination-constrained key " - "to sign an unidentified signature"); - goto send; - } - /* XXX logspam */ - debug_f("user=%s", user); - if (identity_permitted(id, e, user, &fwd_host, &dest_host) != 0) - goto send; - /* XXX display fwd_host/dest_host in askpass UI */ - /* - * Ensure that the session ID is the most recent one - * registered on the socket - it should have been bound by - * ssh immediately before userauth. - */ - if (buf_equal(sid, - e->session_ids[e->nsession_ids - 1].sid) != 0) { - error_f("unexpected session ID (%zu listed) on " - "signature request for target user %s with " - "key %s %s", e->nsession_ids, user, - sshkey_type(id->key), fp); - goto send; - } - /* - * Ensure that the hostkey embedded in the signature matches - * the one most recently bound to the socket. An exception is - * made for the initial forwarding hop. - */ - if (e->nsession_ids > 1 && hostkey == NULL) { - error_f("refusing use of destination-constrained key: " - "no hostkey recorded in signature for forwarded " - "connection"); - goto send; - } - if (hostkey != NULL && !sshkey_equal(hostkey, - e->session_ids[e->nsession_ids - 1].key)) { - error_f("refusing use of destination-constrained key: " - "mismatch between hostkey in request and most " - "recently bound session"); - goto send; - } - xasprintf(&sig_dest, "public key authentication request for " - "user \"%s\" to listed host", user); - } - if (id->confirm && confirm_key(id, sig_dest) != 0) { - verbose_f("user refused key"); + if (id->confirm && confirm_key(id, NULL) != 0) { + debug_f("user refused key"); goto send; } - if (sshkey_is_sk(id->key)) { - if (restrict_websafe && - strncmp(id->key->sk_application, "ssh:", 4) != 0 && - !check_websafe_message_contents(key, data)) { - /* error already logged */ - goto send; - } - if (id->key->sk_flags & SSH_SK_USER_PRESENCE_REQD) { - notifier = notify_start(0, - "Confirm user presence for key %s %s%s%s", - sshkey_type(id->key), fp, - sig_dest == NULL ? "" : "\n", - sig_dest == NULL ? "" : sig_dest); - } - } - retry_pin: - if ((r = sshkey_sign(id->key, &signature, &slen, - sshbuf_ptr(data), sshbuf_len(data), agent_decode_alg(key, flags), - id->sk_provider, pin, compat)) != 0) { - debug_fr(r, "sshkey_sign"); - if (pin == NULL && !retried && sshkey_is_sk(id->key) && - r == SSH_ERR_KEY_WRONG_PASSPHRASE) { - notify_complete(notifier, NULL); - notifier = NULL; - /* XXX include sig_dest */ - xasprintf(&prompt, "Enter PIN%sfor %s key %s: ", - (id->key->sk_flags & SSH_SK_USER_PRESENCE_REQD) ? - " and confirm user presence " : " ", - sshkey_type(id->key), fp); - pin = read_passphrase(prompt, RP_USE_ASKPASS); - retried = 1; - goto retry_pin; - } - error_fr(r, "sshkey_sign"); +{ const char *alg = agent_recode_alg(pkalg, flags); + ssh_sign_ctx ctx = { alg, id->key, &ctx_compat, NULL, NULL }; + + r = Xkey_sign(&ctx, &signature, &slen, data, dlen); +} + if (r != 0) { + error_fr(r, "Xkey_sign"); goto send; } /* Success */ ok = 0; - debug_f("good signature"); send: - notify_complete(notifier, "User presence confirmed"); - + free(pkalg); + sshkey_free(key); if (ok == 0) { if ((r = sshbuf_put_u8(msg, SSH2_AGENT_SIGN_RESPONSE)) != 0 || (r = sshbuf_put_string(msg, signature, slen)) != 0) @@ -863,18 +376,8 @@ if ((r = sshbuf_put_stringb(e->output, msg)) != 0) fatal_fr(r, "enqueue"); - sshbuf_free(sid); - sshbuf_free(data); sshbuf_free(msg); - sshkey_free(key); - sshkey_free(hostkey); - free(fp); free(signature); - free(sig_dest); - free(user); - free(prompt); - if (pin != NULL) - freezero(pin, strlen(pin)); } /* shared */ @@ -885,18 +388,14 @@ struct sshkey *key = NULL; Identity *id; - debug2_f("entering"); - if ((r = sshkey_froms(e->request, &key)) != 0) { - error_fr(r, "parse key"); + if ((r = Akey_gets(e->request, &key)) != 0) { + error_fr(r, "get key"); goto done; } if ((id = lookup_identity(key)) == NULL) { debug_f("key not found"); goto done; } - /* identity not visible, cannot be removed */ - if (identity_permitted(id, e, NULL, NULL, NULL) != 0) - goto done; /* error already logged */ /* We have this key, free it. */ if (idtab->nentries < 1) fatal_f("internal error: nentries %d", idtab->nentries); @@ -914,7 +413,6 @@ { Identity *id; - debug2_f("entering"); /* Loop over all identities and clear the keys. */ for (id = TAILQ_FIRST(&idtab->idlist); id; id = TAILQ_FIRST(&idtab->idlist)) { @@ -956,237 +454,125 @@ } static int -parse_dest_constraint_hop(struct sshbuf *b, struct dest_constraint_hop *dch) +parse_key_constraint_sk_provider(struct sshbuf *m, char *ext_name, + int *sk_provider_set, char **sk_providerp) { - u_char key_is_ca; - size_t elen = 0; int r; - struct sshkey *k = NULL; - char *fp; - memset(dch, '\0', sizeof(*dch)); - if ((r = sshbuf_get_cstring(b, &dch->user, NULL)) != 0 || - (r = sshbuf_get_cstring(b, &dch->hostname, NULL)) != 0 || - (r = sshbuf_get_string_direct(b, NULL, &elen)) != 0) { - error_fr(r, "parse"); - goto out; - } - if (elen != 0) { - error_f("unsupported extensions (len %zu)", elen); - r = SSH_ERR_FEATURE_UNSUPPORTED; - goto out; - } - if (*dch->hostname == '\0') { - free(dch->hostname); - dch->hostname = NULL; - } - if (*dch->user == '\0') { - free(dch->user); - dch->user = NULL; - } - while (sshbuf_len(b) != 0) { - dch->keys = xrecallocarray(dch->keys, dch->nkeys, - dch->nkeys + 1, sizeof(*dch->keys)); - dch->key_is_ca = xrecallocarray(dch->key_is_ca, dch->nkeys, - dch->nkeys + 1, sizeof(*dch->key_is_ca)); - if ((r = sshkey_froms(b, &k)) != 0 || - (r = sshbuf_get_u8(b, &key_is_ca)) != 0) - goto out; - if ((fp = sshkey_fingerprint(k, SSH_FP_HASH_DEFAULT, - SSH_FP_DEFAULT)) == NULL) - fatal_f("fingerprint failed"); - debug3_f("%s%s%s: adding %skey %s %s", - dch->user == NULL ? "" : dch->user, - dch->user == NULL ? "" : "@", - dch->hostname, key_is_ca ? "CA " : "", sshkey_type(k), fp); - free(fp); - dch->keys[dch->nkeys] = k; - dch->key_is_ca[dch->nkeys] = key_is_ca != 0; - dch->nkeys++; - k = NULL; /* transferred */ - } - /* success */ - r = 0; - out: - sshkey_free(k); - return r; -} + if (strcmp(ext_name, "sk-provider@openssh.com") != 0) + return SSH_ERR_FEATURE_UNSUPPORTED; -static int -parse_dest_constraint(struct sshbuf *m, struct dest_constraint *dc) -{ - struct sshbuf *b = NULL, *frombuf = NULL, *tobuf = NULL; - int r; - size_t elen = 0; - - debug3_f("entering"); - - memset(dc, '\0', sizeof(*dc)); - if ((r = sshbuf_froms(m, &b)) != 0 || - (r = sshbuf_froms(b, &frombuf)) != 0 || - (r = sshbuf_froms(b, &tobuf)) != 0 || - (r = sshbuf_get_string_direct(b, NULL, &elen)) != 0) { - error_fr(r, "parse"); - goto out; - } - if ((r = parse_dest_constraint_hop(frombuf, &dc->from)) != 0 || - (r = parse_dest_constraint_hop(tobuf, &dc->to)) != 0) - goto out; /* already logged */ - if (elen != 0) { - error_f("unsupported extensions (len %zu)", elen); - r = SSH_ERR_FEATURE_UNSUPPORTED; - goto out; - } - debug2_f("parsed %s (%u keys) > %s%s%s (%u keys)", - dc->from.hostname ? dc->from.hostname : "(ORIGIN)", dc->from.nkeys, - dc->to.user ? dc->to.user : "", dc->to.user ? "@" : "", - dc->to.hostname ? dc->to.hostname : "(ANY)", dc->to.nkeys); - /* check consistency */ - if ((dc->from.hostname == NULL) != (dc->from.nkeys == 0) || - dc->from.user != NULL) { - error_f("inconsistent \"from\" specification"); - r = SSH_ERR_INVALID_FORMAT; - goto out; + if (sk_providerp == NULL) { + error_f("%s not valid here", ext_name); + return SSH_ERR_INVALID_ARGUMENT; } - if (dc->to.hostname == NULL || dc->to.nkeys == 0) { - error_f("incomplete \"to\" specification"); - r = SSH_ERR_INVALID_FORMAT; - goto out; + if (*sk_provider_set) { + error_f("%s already set", ext_name); + return SSH_ERR_INVALID_ARGUMENT; } - /* success */ - r = 0; - out: - sshbuf_free(b); - sshbuf_free(frombuf); - sshbuf_free(tobuf); - return r; -} - -static int -parse_key_constraint_extension(struct sshbuf *m, char **sk_providerp, - struct dest_constraint **dcsp, size_t *ndcsp) -{ - char *ext_name = NULL; - int r; - struct sshbuf *b = NULL; - if ((r = sshbuf_get_cstring(m, &ext_name, NULL)) != 0) { - error_fr(r, "parse constraint extension"); - goto out; + r = sshbuf_get_cstring(m, sk_providerp, NULL); + if (r != 0) { + error_fr(r, "parse %s", ext_name); + return r; } - debug_f("constraint ext %s", ext_name); - if (strcmp(ext_name, "sk-provider@openssh.com") == 0) { - if (sk_providerp == NULL) { - error_f("%s not valid here", ext_name); - r = SSH_ERR_INVALID_FORMAT; - goto out; - } - if (*sk_providerp != NULL) { - error_f("%s already set", ext_name); - r = SSH_ERR_INVALID_FORMAT; - goto out; - } - if ((r = sshbuf_get_cstring(m, sk_providerp, NULL)) != 0) { - error_fr(r, "parse %s", ext_name); - goto out; - } - } else if (strcmp(ext_name, - "restrict-destination-v00@openssh.com") == 0) { - if (*dcsp != NULL) { - error_f("%s already set", ext_name); - goto out; - } - if ((r = sshbuf_froms(m, &b)) != 0) { - error_fr(r, "parse %s outer", ext_name); - goto out; - } - while (sshbuf_len(b) != 0) { - if (*ndcsp >= AGENT_MAX_DEST_CONSTRAINTS) { - error_f("too many %s constraints", ext_name); - goto out; - } - *dcsp = xrecallocarray(*dcsp, *ndcsp, *ndcsp + 1, - sizeof(**dcsp)); - if ((r = parse_dest_constraint(b, - *dcsp + (*ndcsp)++)) != 0) - goto out; /* error already logged */ - } - } else { - error_f("unsupported constraint \"%s\"", ext_name); - r = SSH_ERR_FEATURE_UNSUPPORTED; - goto out; - } - /* success */ - r = 0; - out: - free(ext_name); - sshbuf_free(b); - return r; + + *sk_provider_set = 1; + return 0; } static int -parse_key_constraints(struct sshbuf *m, struct sshkey *k, time_t *deathp, - u_int *secondsp, int *confirmp, char **sk_providerp, - struct dest_constraint **dcsp, size_t *ndcsp) +parse_key_constraints(struct sshbuf *m, struct sshkey *k, + u_int *secondsp, int *confirmp, char **sk_providerp) { - u_char ctype; int r; - u_int seconds, maxsign = 0; + int lifetime_set = 0, confirm_set = 0; + int maxsign_set = 0, sk_provider_set = 0; while (sshbuf_len(m)) { + u_char ctype; if ((r = sshbuf_get_u8(m, &ctype)) != 0) { error_fr(r, "parse constraint type"); goto out; } switch (ctype) { - case SSH_AGENT_CONSTRAIN_LIFETIME: - if (*deathp != 0) { + case SSH_AGENT_CONSTRAIN_LIFETIME: { + u_int32_t seconds; + + if (secondsp == NULL) { + error_f("lifetime not valid here"); + r = SSH_ERR_INVALID_ARGUMENT; + goto out; + } + if (lifetime_set) { error_f("lifetime already set"); - r = SSH_ERR_INVALID_FORMAT; + r = SSH_ERR_INVALID_ARGUMENT; goto out; } if ((r = sshbuf_get_u32(m, &seconds)) != 0) { error_fr(r, "parse lifetime constraint"); goto out; } - *deathp = monotime() + seconds; + lifetime_set = 1; *secondsp = seconds; - break; + } break; case SSH_AGENT_CONSTRAIN_CONFIRM: - if (*confirmp != 0) { + if (confirm_set) { error_f("confirm already set"); - r = SSH_ERR_INVALID_FORMAT; + r = SSH_ERR_INVALID_ARGUMENT; goto out; } + confirm_set = 1; *confirmp = 1; break; - case SSH_AGENT_CONSTRAIN_MAXSIGN: + case SSH_AGENT_CONSTRAIN_MAXSIGN: { + u_int32_t maxsign; + if (k == NULL) { error_f("maxsign not valid here"); - r = SSH_ERR_INVALID_FORMAT; + r = SSH_ERR_INVALID_ARGUMENT; goto out; } - if (maxsign != 0) { + if (maxsign_set) { error_f("maxsign already set"); - r = SSH_ERR_INVALID_FORMAT; + r = SSH_ERR_INVALID_ARGUMENT; goto out; } if ((r = sshbuf_get_u32(m, &maxsign)) != 0) { error_fr(r, "parse maxsign constraint"); goto out; } + maxsign_set = 1; + /* same as ssh-add */ + if (maxsign == 0) { + error_f("non alloved maxsign value"); + r = SSH_ERR_INVALID_ARGUMENT; + goto out; + } if ((r = sshkey_enable_maxsign(k, maxsign)) != 0) { error_fr(r, "enable maxsign"); goto out; } - break; - case SSH_AGENT_CONSTRAIN_EXTENSION: - if ((r = parse_key_constraint_extension(m, - sk_providerp, dcsp, ndcsp)) != 0) - goto out; /* error already logged */ - break; + } break; + case SSH_AGENT_CONSTRAIN_EXTENSION: { + char *ext_name; + + if ((r = sshbuf_get_cstring(m, &ext_name, NULL)) != 0) { + error_fr(r, "parse constraint extension"); + goto out; + } + debug_f("constraint ext %s", ext_name); + + r = parse_key_constraint_sk_provider(m, ext_name, + &sk_provider_set, sk_providerp); + + if (r == SSH_ERR_FEATURE_UNSUPPORTED) + error_f("unsupported constraint \"%s\"", ext_name); + free(ext_name); + if (r != 0) goto out; + } break; default: - error_f("Unknown constraint %d", ctype); + error_f("unknown constraint %d", ctype); r = SSH_ERR_FEATURE_UNSUPPORTED; goto out; } @@ -1200,113 +586,66 @@ static void process_add_identity(SocketEntry *e) { - Identity *id; int success = 0, confirm = 0; - char *fp, *comment = NULL, *sk_provider = NULL; - char canonical_provider[PATH_MAX]; - time_t death = 0; + char *comment = NULL, *sk_provider = NULL; u_int seconds = 0; - struct dest_constraint *dest_constraints = NULL; - size_t ndest_constraints = 0; + time_t death = 0; struct sshkey *k = NULL; - int r = SSH_ERR_INTERNAL_ERROR; + int r; - debug2_f("entering"); if ((r = sshkey_private_deserialize(e->request, &k)) != 0 || k == NULL || (r = sshbuf_get_cstring(e->request, &comment, NULL)) != 0) { error_fr(r, "parse"); goto out; } - if (parse_key_constraints(e->request, k, &death, &seconds, &confirm, - &sk_provider, &dest_constraints, &ndest_constraints) != 0) { - error_f("failed to parse constraints"); + if (parse_key_constraints(e->request, k, &seconds, &confirm, + &sk_provider) != 0) { + /* error already logged */ sshbuf_reset(e->request); goto out; } - - if (sk_provider != NULL) { - if (!sshkey_is_sk(k)) { - error("Cannot add provider: %s is not an " - "authenticator-hosted key", sshkey_type(k)); - goto out; - } - if (strcasecmp(sk_provider, "internal") == 0) { - debug_f("internal provider"); - } else { - if (e->nsession_ids != 0 && !remote_add_provider) { - verbose("failed add of SK provider \"%.100s\": " - "remote addition of providers is disabled", - sk_provider); - goto out; - } - if (realpath(sk_provider, canonical_provider) == NULL) { - verbose("failed provider \"%.100s\": " - "realpath: %s", sk_provider, - strerror(errno)); - goto out; - } - free(sk_provider); - sk_provider = xstrdup(canonical_provider); - if (match_pattern_list(sk_provider, - allowed_providers, 0) != 1) { - error("Refusing add key: " - "provider %s not allowed", sk_provider); - goto out; - } - } - } if ((r = sshkey_shield_private(k)) != 0) { error_fr(r, "shield private"); goto out; } - if (lifetime && !death) - death = monotime() + lifetime; - if ((id = lookup_identity(k)) == NULL) { + if (lifetime != 0 || seconds != 0) { + u_int timeoffset = seconds != 0 ? seconds : lifetime; + death = monotime(); + if (death > (time_t)(death + timeoffset)) { + debug3_f("now lifetime is too high"); + /* forever */ + death = 0; + } else + death += timeoffset; + } +{ Identity *id = lookup_identity(k); + if (id == NULL) { id = xcalloc(1, sizeof(Identity)); TAILQ_INSERT_TAIL(&idtab->idlist, id, next); /* Increment the number of identities. */ idtab->nentries++; } else { - /* identity not visible, do not update */ - if (identity_permitted(id, e, NULL, NULL, NULL) != 0) - goto out; /* error already logged */ /* key state might have been updated */ sshkey_free(id->key); free(id->comment); - free(id->sk_provider); - free_dest_constraints(id->dest_constraints, - id->ndest_constraints); } /* success */ id->key = k; id->comment = comment; id->death = death; id->confirm = confirm; - id->sk_provider = sk_provider; - id->dest_constraints = dest_constraints; - id->ndest_constraints = ndest_constraints; - - if ((fp = sshkey_fingerprint(k, SSH_FP_HASH_DEFAULT, - SSH_FP_DEFAULT)) == NULL) - fatal_f("sshkey_fingerprint failed"); - debug_f("add %s %s \"%.100s\" (life: %u) (confirm: %u) " - "(provider: %s) (destination constraints: %zu)", - sshkey_ssh_name(k), fp, comment, seconds, confirm, - sk_provider == NULL ? "none" : sk_provider, ndest_constraints); - free(fp); + free(sk_provider); /*TODO*/ +} /* transferred */ k = NULL; comment = NULL; sk_provider = NULL; - dest_constraints = NULL; - ndest_constraints = 0; success = 1; out: free(sk_provider); free(comment); sshkey_free(k); - free_dest_constraints(dest_constraints, ndest_constraints); send_status(e, success); } @@ -1320,7 +659,6 @@ static u_int fail_count = 0; size_t pwlen; - debug2_f("entering"); /* * This is deliberately fatal: the user has requested that we lock, * but we can't parse their request properly. The only safe thing to @@ -1383,29 +721,18 @@ process_add_smartcard_key(SocketEntry *e) { char *provider = NULL, *pin = NULL, canonical_provider[PATH_MAX]; - char **comments = NULL; - int r, i, count = 0, success = 0, confirm = 0; - u_int seconds = 0; + int r, success = 0, confirm = 0; time_t death = 0; - struct sshkey **keys = NULL, *k; - Identity *id; - struct dest_constraint *dest_constraints = NULL; - size_t ndest_constraints = 0; - debug2_f("entering"); if ((r = sshbuf_get_cstring(e->request, &provider, NULL)) != 0 || (r = sshbuf_get_cstring(e->request, &pin, NULL)) != 0) { error_fr(r, "parse"); goto send; } - if (parse_key_constraints(e->request, NULL, &death, &seconds, &confirm, - NULL, &dest_constraints, &ndest_constraints) != 0) { - error_f("failed to parse constraints"); - goto send; - } - if (e->nsession_ids != 0 && !remote_add_provider) { - verbose("failed PKCS#11 add of \"%.100s\": remote addition of " - "providers is disabled", provider); + if (parse_key_constraints(e->request, NULL, NULL, &confirm, + NULL) != 0) { + /* error already logged */ + sshbuf_reset(e->request); goto send; } if (realpath(provider, canonical_provider) == NULL) { @@ -1419,43 +746,49 @@ goto send; } debug_f("add %.100s", canonical_provider); - if (lifetime && !death) - death = monotime() + lifetime; + if (lifetime != 0) { + death = monotime(); + if (death > (time_t)(death + lifetime)) { + debug3_f("now lifetime is too high"); + /* forever */ + death = 0; + } else + death += lifetime; + } + +{ + int i, count; + struct sshkey **keys; + char **comments; count = pkcs11_add_provider(canonical_provider, pin, &keys, &comments); for (i = 0; i < count; i++) { - k = keys[i]; - if (lookup_identity(k) == NULL) { - id = xcalloc(1, sizeof(Identity)); - id->key = k; - keys[i] = NULL; /* transferred */ - id->provider = xstrdup(canonical_provider); - if (*comments[i] != '\0') { - id->comment = comments[i]; - comments[i] = NULL; /* transferred */ - } else { - id->comment = xstrdup(canonical_provider); - } - id->death = death; - id->confirm = confirm; - id->dest_constraints = dest_constraints; - id->ndest_constraints = ndest_constraints; - dest_constraints = NULL; /* transferred */ - ndest_constraints = 0; - TAILQ_INSERT_TAIL(&idtab->idlist, id, next); - idtab->nentries++; - success = 1; + struct sshkey *k = keys[i]; + Identity *id; + + if (lookup_identity(k) != NULL) { + sshkey_free(keys[i]); + free(comments[i]); + continue; } - /* XXX update constraints for existing keys */ - sshkey_free(keys[i]); - free(comments[i]); + + id = xcalloc(1, sizeof(Identity)); + id->key = k; + id->provider = xstrdup(canonical_provider); + id->comment = comments[i]; + id->death = death; + id->confirm = confirm; + TAILQ_INSERT_TAIL(&idtab->idlist, id, next); + idtab->nentries++; + success = 1; } -send: - free(pin); - free(provider); free(keys); free(comments); - free_dest_constraints(dest_constraints, ndest_constraints); +} +send: + if (pin != NULL) + freezero(pin, strlen(pin)); + free(provider); send_status(e, success); } @@ -1466,7 +799,6 @@ int r, success = 0; Identity *id, *nxt; - debug2_f("entering"); if ((r = sshbuf_get_cstring(e->request, &provider, NULL)) != 0 || (r = sshbuf_get_cstring(e->request, &pin, NULL)) != 0) { error_fr(r, "parse"); @@ -1502,106 +834,6 @@ } #endif /* ENABLE_PKCS11 */ -static int -process_ext_session_bind(SocketEntry *e) -{ - int r, sid_match, key_match; - struct sshkey *key = NULL; - struct sshbuf *sid = NULL, *sig = NULL; - char *fp = NULL; - size_t i; - u_char fwd = 0; - - debug2_f("entering"); - if ((r = sshkey_froms(e->request, &key)) != 0 || - (r = sshbuf_froms(e->request, &sid)) != 0 || - (r = sshbuf_froms(e->request, &sig)) != 0 || - (r = sshbuf_get_u8(e->request, &fwd)) != 0) { - error_fr(r, "parse"); - goto out; - } - if ((fp = sshkey_fingerprint(key, SSH_FP_HASH_DEFAULT, - SSH_FP_DEFAULT)) == NULL) - fatal_f("fingerprint failed"); - /* check signature with hostkey on session ID */ - if ((r = sshkey_verify(key, sshbuf_ptr(sig), sshbuf_len(sig), - sshbuf_ptr(sid), sshbuf_len(sid), NULL, 0, NULL)) != 0) { - error_fr(r, "sshkey_verify for %s %s", sshkey_type(key), fp); - goto out; - } - /* check whether sid/key already recorded */ - for (i = 0; i < e->nsession_ids; i++) { - if (!e->session_ids[i].forwarded) { - error_f("attempt to bind session ID to socket " - "previously bound for authentication attempt"); - r = -1; - goto out; - } - sid_match = buf_equal(sid, e->session_ids[i].sid) == 0; - key_match = sshkey_equal(key, e->session_ids[i].key); - if (sid_match && key_match) { - debug_f("session ID already recorded for %s %s", - sshkey_type(key), fp); - r = 0; - goto out; - } else if (sid_match) { - error_f("session ID recorded against different key " - "for %s %s", sshkey_type(key), fp); - r = -1; - goto out; - } - /* - * new sid with previously-seen key can happen, e.g. multiple - * connections to the same host. - */ - } - /* record new key/sid */ - if (e->nsession_ids >= AGENT_MAX_SESSION_IDS) { - error_f("too many session IDs recorded"); - goto out; - } - e->session_ids = xrecallocarray(e->session_ids, e->nsession_ids, - e->nsession_ids + 1, sizeof(*e->session_ids)); - i = e->nsession_ids++; - debug_f("recorded %s %s (slot %zu of %d)", sshkey_type(key), fp, i, - AGENT_MAX_SESSION_IDS); - e->session_ids[i].key = key; - e->session_ids[i].forwarded = fwd != 0; - key = NULL; /* transferred */ - /* can't transfer sid; it's refcounted and scoped to request's life */ - if ((e->session_ids[i].sid = sshbuf_new()) == NULL) - fatal_f("sshbuf_new"); - if ((r = sshbuf_putb(e->session_ids[i].sid, sid)) != 0) - fatal_fr(r, "sshbuf_putb session ID"); - /* success */ - r = 0; - out: - free(fp); - sshkey_free(key); - sshbuf_free(sid); - sshbuf_free(sig); - return r == 0 ? 1 : 0; -} - -static void -process_extension(SocketEntry *e) -{ - int r, success = 0; - char *name; - - debug2_f("entering"); - if ((r = sshbuf_get_cstring(e->request, &name, NULL)) != 0) { - error_fr(r, "parse"); - goto send; - } - if (strcmp(name, "session-bind@openssh.com") == 0) - success = process_ext_session_bind(e); - else - debug_f("unsupported extension \"%s\"", name); - free(name); -send: - send_status(e, success); -} /* * dispatch incoming message. * returns 1 on success, 0 for incomplete messages or -1 on error. @@ -1694,9 +926,6 @@ process_remove_smartcard_key(e); break; #endif /* ENABLE_PKCS11 */ - case SSH_AGENTC_EXTENSION: - process_extension(e); - break; default: /* Unknown message. Respond with failure. */ error("Unknown message %d", type); @@ -1712,8 +941,6 @@ { u_int i, old_alloc, new_alloc; - debug_f("type = %s", type == AUTH_CONNECTION ? "CONNECTION" : - (type == AUTH_SOCKET ? "SOCKET" : "UNKNOWN")); set_nonblock(fd); if (fd > max_fd) @@ -1793,11 +1020,10 @@ if ((r = sshbuf_put(sockets[socknum].input, buf, len)) != 0) fatal_fr(r, "compose"); explicit_bzero(buf, sizeof(buf)); - for (;;) { - if ((r = process_message(socknum)) == -1) - return -1; - else if (r == 0) - break; + while(1) { + r = process_message(socknum); + if (r == -1) return -1; + if (r == 0) break; } return 0; } @@ -1850,7 +1076,7 @@ /* Process events */ switch (sockets[socknum].type) { case AUTH_SOCKET: - if ((pfd[i].revents & (POLLIN|POLLERR)) == 0) + if ((pfd[i].revents & (POLLIN|POLLHUP|POLLERR)) == 0) break; if (npfd > maxfds) { debug3("out of fds (active %u >= limit %u); " @@ -1974,12 +1200,16 @@ cleanup_exit(int i) { cleanup_socket(); +#ifdef ENABLE_PKCS11 + pkcs11_terminate(); +#endif _exit(i); } static void cleanup_handler(int sig) { + UNUSED(sig); cleanup_socket(); #ifdef ENABLE_PKCS11 pkcs11_terminate(); @@ -2006,9 +1236,9 @@ { fprintf(stderr, "usage: ssh-agent [-c | -s] [-Dd] [-a bind_address] [-E fingerprint_hash]\n" - " [-O option] [-P allowed_providers] [-t life]\n" - " ssh-agent [-a bind_address] [-E fingerprint_hash] [-O option]\n" - " [-P allowed_providers] [-t life] command [arg ...]\n" + " [-P allowed_providers] [-t life]\n" + " ssh-agent [-a bind_address] [-E fingerprint_hash] [-P allowed_providers]\n" + " [-t life] command [arg ...]\n" " ssh-agent [-c | -s] -k\n"); exit(1); } @@ -2019,9 +1249,6 @@ int c_flag = 0, d_flag = 0, D_flag = 0, k_flag = 0, s_flag = 0; int sock, ch, result, saved_errno; char *shell, *format, *pidstr, *agentsocket = NULL; -#ifdef HAVE_SETRLIMIT - struct rlimit rlim; -#endif extern int optind; extern char *optarg; pid_t pid; @@ -2033,6 +1260,10 @@ size_t npfd = 0; u_int maxfds; + socket_name[0] = '\0'; + socket_dir[0] = '\0'; + + ssh_malloc_init(); /* must be called before any mallocs */ /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ sanitise_stdfd(); @@ -2042,15 +1273,26 @@ platform_disable_tracing(0); /* strict=no */ -#ifdef RLIMIT_NOFILE - if (getrlimit(RLIMIT_NOFILE, &rlim) == -1) - fatal("%s: getrlimit: %s", __progname, strerror(errno)); + __progname = ssh_get_progname(av[0]); + + ssh_OpenSSL_startup(); +#ifdef OPENSSL_FIPS + if (FIPS_mode()) { + #ifdef HAVE_FIPSCHECK_H + if (!FIPSCHECK_verify(NULL, NULL)) + fatal("FIPS integrity verification test failed."); + #endif + fprintf(stderr, "%s runs in FIPS mode\n", __progname); + } +#endif /*def OPENSSL_FIPS*/ +#ifdef ENABLE_PKCS11 + ERR_load_PKCS11_strings(); #endif + fill_default_xkalg(); - __progname = ssh_get_progname(av[0]); seed_rng(); - while ((ch = getopt(ac, av, "cDdksE:a:O:P:t:")) != -1) { + while ((ch = getopt(ac, av, "cDdksE:a:P:t:")) != -1) { switch (ch) { case 'E': fingerprint_hash = ssh_digest_alg_by_name(optarg); @@ -2065,14 +1307,6 @@ case 'k': k_flag++; break; - case 'O': - if (strcmp(optarg, "no-restrict-websafe") == 0) - restrict_websafe = 0; - else if (strcmp(optarg, "allow-remote-pkcs11") == 0) - remote_add_provider = 1; - else - fatal("Unknown -O option"); - break; case 'P': if (allowed_providers != NULL) fatal("-P option already specified"); @@ -2097,8 +1331,7 @@ agentsocket = optarg; break; case 't': - if ((lifetime = convtime(optarg)) == -1) { - fprintf(stderr, "Invalid lifetime\n"); + if (!set_lifetime(optarg)) { usage(); } break; @@ -2154,10 +1387,28 @@ * a few spare for libc / stack protectors / sanitisers, etc. */ #define SSH_AGENT_MIN_FDS (3+1+1+1+4) +{ +#if defined(HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE) + rlim_t lim; +{ struct rlimit rlim; + + if (getrlimit(RLIMIT_NOFILE, &rlim) == -1) + fatal("%s: getrlimit RLIMIT_NOFILE: %s", __progname, strerror(errno)); if (rlim.rlim_cur < SSH_AGENT_MIN_FDS) fatal("%s: file descriptor rlimit %lld too low (minimum %u)", __progname, (long long)rlim.rlim_cur, SSH_AGENT_MIN_FDS); - maxfds = rlim.rlim_cur - SSH_AGENT_MIN_FDS; + lim = rlim.rlim_cur; + if (lim == RLIM_INFINITY) + lim = SSH_SYSFDMAX; +} +#else + long lim = SSH_SYSFDMAX; + if (lim < SSH_AGENT_MIN_FDS) + fatal("%s: file descriptor limit %ld too low (minimum %u)", + __progname, lim, SSH_AGENT_MIN_FDS); +#endif + maxfds = MINIMUM(lim, UINT_MAX) - SSH_AGENT_MIN_FDS; +} parent_pid = getpid(); @@ -2168,12 +1419,20 @@ perror("mkdtemp: private socket dir"); exit(1); } - snprintf(socket_name, sizeof socket_name, "%s/agent.%ld", socket_dir, - (long)parent_pid); + { int r = snprintf(socket_name, sizeof socket_name, "%s/agent.%ld", + socket_dir, (long)parent_pid); + if (r < 0 || r > (int)sizeof(socket_name)) { + fprintf(stderr, "too long socket path\n"); + exit(1); + } + } } else { /* Try to use specified agent socket */ - socket_dir[0] = '\0'; - strlcpy(socket_name, agentsocket, sizeof socket_name); + if (strlcpy(socket_name, agentsocket, sizeof socket_name) + > sizeof(socket_name)) { + fprintf(stderr, "too long agent socket path\n"); + exit(1); + } } /* @@ -2234,7 +1493,7 @@ log_init(__progname, SYSLOG_LEVEL_INFO, SYSLOG_FACILITY_AUTH, 0); if (setsid() == -1) { - error("setsid: %s", strerror(errno)); + error_f("setsid: %s", strerror(errno)); cleanup_exit(1); } @@ -2242,13 +1501,16 @@ if (stdfd_devnull(1, 1, 1) == -1) error_f("stdfd_devnull failed"); -#ifdef HAVE_SETRLIMIT +#if defined(HAVE_SETRLIMIT) && defined(RLIMIT_CORE) +{ struct rlimit rlim; + /* deny core dumps, since memory contains unencrypted private keys */ rlim.rlim_cur = rlim.rlim_max = 0; if (setrlimit(RLIMIT_CORE, &rlim) == -1) { - error("setrlimit RLIMIT_CORE: %s", strerror(errno)); + error_f("setrlimit RLIMIT_CORE: %s", strerror(errno)); cleanup_exit(1); } +} #endif skip: diff -ruN openssh-9.4p1/ssh_api.c openssh-9.4p1+x509-14.2.1/ssh_api.c --- openssh-9.4p1/ssh_api.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/ssh_api.c 2023-08-20 10:07:01.000000000 +0300 @@ -1,6 +1,7 @@ /* $OpenBSD: ssh_api.c,v 1.27 2021/04/03 06:18:41 djm Exp $ */ /* * Copyright (c) 2012 Markus Friedl. All rights reserved. + * Copyright (c) 2014-2021 Roumen Petrov. All rights reserved. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -23,10 +24,10 @@ #include #include "ssh_api.h" -#include "compat.h" +#include "evp-compat.h" #include "log.h" #include "authfile.h" -#include "sshkey.h" +#include "sshxkey.h" #include "misc.h" #include "ssh2.h" #include "version.h" @@ -34,8 +35,6 @@ #include "ssherr.h" #include "sshbuf.h" -#include "openbsd-compat/openssl-compat.h" - #include int _ssh_exchange_banner(struct ssh *); @@ -43,54 +42,73 @@ int _ssh_read_banner(struct ssh *, struct sshbuf *); int _ssh_order_hostkeyalgs(struct ssh *); int _ssh_verify_host_key(struct sshkey *, struct ssh *); -struct sshkey *_ssh_host_public_key(int, int, struct ssh *); -struct sshkey *_ssh_host_private_key(int, int, struct ssh *); -int _ssh_host_key_sign(struct ssh *, struct sshkey *, struct sshkey *, - u_char **, size_t *, const u_char *, size_t, const char *); +struct sshkey *_ssh_host_public_key(const char*, struct ssh *); +struct sshkey *_ssh_host_private_key(const char*, struct ssh *); /* * stubs for the server side implementation of kex. * disable privsep so our stubs will never be called. */ int use_privsep = 0; -int mm_sshkey_sign(struct sshkey *, u_char **, u_int *, - const u_char *, u_int, const char *, const char *, const char *, u_int); #ifdef WITH_OPENSSL -DH *mm_choose_dh(int, int, int); -#endif +/* fake implementation for client objects. + * real for daemon is in monitor_wrap. + */ +EVP_PKEY* mm_kex_new_dh_group_bits(int, int, int); -int -mm_sshkey_sign(struct sshkey *key, u_char **sigp, u_int *lenp, - const u_char *data, u_int datalen, const char *alg, - const char *sk_provider, const char *sk_pin, u_int compat) +EVP_PKEY* +mm_kex_new_dh_group_bits(int min, int nbits, int max) { - return (-1); + UNUSED(min); UNUSED(nbits); UNUSED(max); + return NULL; } +#endif -#ifdef WITH_OPENSSL -DH * -mm_choose_dh(int min, int nbits, int max) -{ - return (NULL); +static int +_ssh_host_key_sign( + struct ssh *ssh, ssh_sign_ctx *ctx, + struct sshkey *pub, u_char **sigp, size_t *lenp, + const u_char *data, size_t datalen +){ + UNUSED(ssh); + UNUSED(pub); + return Xkey_sign(ctx, sigp, lenp, data, datalen); } -#endif /* API */ +static int crypto_status = 0; + +void +ssh_crypto_init() { + if (!crypto_status) { +#ifdef WITH_OPENSSL + ssh_OpenSSL_startup(); +#endif /* WITH_OPENSSL */ + crypto_status = 1; + } +} + +void +ssh_crypto_fini() { + if (crypto_status) { +#ifdef WITH_OPENSSL + ssh_OpenSSL_shuthdown(); +#endif /* WITH_OPENSSL */ + crypto_status = 0; + } +} + int ssh_init(struct ssh **sshp, int is_server, struct kex_params *kex_params) { char *myproposal[PROPOSAL_MAX] = { KEX_CLIENT }; struct ssh *ssh; char **proposal; - static int called; int r; - if (!called) { - seed_rng(); - called = 1; - } + ssh_crypto_init(); if ((ssh = ssh_packet_set_connection(NULL, -1, -1)) == NULL) return SSH_ERR_ALLOC_FAIL; @@ -103,40 +121,13 @@ ssh_free(ssh); return r; } - ssh->kex->server = is_server; if (is_server) { -#ifdef WITH_OPENSSL - ssh->kex->kex[KEX_DH_GRP1_SHA1] = kex_gen_server; - ssh->kex->kex[KEX_DH_GRP14_SHA1] = kex_gen_server; - ssh->kex->kex[KEX_DH_GRP14_SHA256] = kex_gen_server; - ssh->kex->kex[KEX_DH_GRP16_SHA512] = kex_gen_server; - ssh->kex->kex[KEX_DH_GRP18_SHA512] = kex_gen_server; - ssh->kex->kex[KEX_DH_GEX_SHA1] = kexgex_server; - ssh->kex->kex[KEX_DH_GEX_SHA256] = kexgex_server; -# ifdef OPENSSL_HAS_ECC - ssh->kex->kex[KEX_ECDH_SHA2] = kex_gen_server; -# endif -#endif /* WITH_OPENSSL */ - ssh->kex->kex[KEX_C25519_SHA256] = kex_gen_server; - ssh->kex->kex[KEX_KEM_SNTRUP761X25519_SHA512] = kex_gen_server; - ssh->kex->load_host_public_key=&_ssh_host_public_key; - ssh->kex->load_host_private_key=&_ssh_host_private_key; - ssh->kex->sign=&_ssh_host_key_sign; + kex_set_callbacks_server(ssh->kex); + ssh->kex->find_host_public_key=&_ssh_host_public_key; + ssh->kex->find_host_private_key=&_ssh_host_private_key; + ssh->kex->xsign=&_ssh_host_key_sign; } else { -#ifdef WITH_OPENSSL - ssh->kex->kex[KEX_DH_GRP1_SHA1] = kex_gen_client; - ssh->kex->kex[KEX_DH_GRP14_SHA1] = kex_gen_client; - ssh->kex->kex[KEX_DH_GRP14_SHA256] = kex_gen_client; - ssh->kex->kex[KEX_DH_GRP16_SHA512] = kex_gen_client; - ssh->kex->kex[KEX_DH_GRP18_SHA512] = kex_gen_client; - ssh->kex->kex[KEX_DH_GEX_SHA1] = kexgex_client; - ssh->kex->kex[KEX_DH_GEX_SHA256] = kexgex_client; -# ifdef OPENSSL_HAS_ECC - ssh->kex->kex[KEX_ECDH_SHA2] = kex_gen_client; -# endif -#endif /* WITH_OPENSSL */ - ssh->kex->kex[KEX_C25519_SHA256] = kex_gen_client; - ssh->kex->kex[KEX_KEM_SNTRUP761X25519_SHA512] = kex_gen_client; + kex_set_callbacks_client(ssh->kex); ssh->kex->verify_host_key =&_ssh_verify_host_key; } *sshp = ssh; @@ -147,17 +138,20 @@ ssh_free(struct ssh *ssh) { struct key_entry *k; + int is_server; - if (ssh == NULL) - return; + if (ssh == NULL) return; + /* NOTE ssh_packet_close free ssh->kex */ + is_server = ssh->kex != NULL && ssh->kex->server; + ssh_packet_close(ssh); /* * we've only created the public keys variants in case we * are a acting as a server. */ while ((k = TAILQ_FIRST(&ssh->public_keys)) != NULL) { TAILQ_REMOVE(&ssh->public_keys, k, next); - if (ssh->kex && ssh->kex->server) + if (is_server) sshkey_free(k->key); free(k); } @@ -165,7 +159,6 @@ TAILQ_REMOVE(&ssh->private_keys, k, next); free(k); } - ssh_packet_close(ssh); free(ssh); } @@ -388,13 +381,16 @@ debug("Remote protocol version %d.%d, remote software version %.100s", remote_major, remote_minor, remote_version); - compat_banner(ssh, remote_version); + ssh_set_compatibility(ssh, remote_version); + if (remote_major == 1 && remote_minor == 99) { remote_major = 2; remote_minor = 0; } - if (remote_major != 2) + if (remote_major != 2) { r = SSH_ERR_PROTOCOL_MISMATCH; + goto out; + } debug("Remote version string %.100s", cp); out: @@ -427,7 +423,6 @@ int _ssh_exchange_banner(struct ssh *ssh) { - struct kex *kex = ssh->kex; int r; /* @@ -436,7 +431,7 @@ */ r = 0; - if (kex->server) { + if (ssh->kex->server) { if (sshbuf_len(ssh->kex->server_version) == 0) r = _ssh_send_banner(ssh, ssh->kex->server_version); if (r == 0 && @@ -464,30 +459,28 @@ } struct sshkey * -_ssh_host_public_key(int type, int nid, struct ssh *ssh) +_ssh_host_public_key(const char* pkalg, struct ssh *ssh) { struct key_entry *k; - debug3_f("need %d", type); + debug3_f("need %s", pkalg); TAILQ_FOREACH(k, &ssh->public_keys, next) { debug3_f("check %s", sshkey_type(k->key)); - if (k->key->type == type && - (type != KEY_ECDSA || k->key->ecdsa_nid == nid)) + if (sshkey_match_pkalg(k->key, pkalg)) return (k->key); } return (NULL); } struct sshkey * -_ssh_host_private_key(int type, int nid, struct ssh *ssh) +_ssh_host_private_key(const char* pkalg, struct ssh *ssh) { struct key_entry *k; - debug3_f("need %d", type); + debug3_f("need %s", pkalg); TAILQ_FOREACH(k, &ssh->private_keys, next) { debug3_f("check %s", sshkey_type(k->key)); - if (k->key->type == type && - (type != KEY_ECDSA || k->key->ecdsa_nid == nid)) + if (sshkey_match_pkalg(k->key, pkalg)) return (k->key); } return (NULL); @@ -559,12 +552,3 @@ kex_prop_free(proposal); return r; } - -int -_ssh_host_key_sign(struct ssh *ssh, struct sshkey *privkey, - struct sshkey *pubkey, u_char **signature, size_t *slen, - const u_char *data, size_t dlen, const char *alg) -{ - return sshkey_sign(privkey, signature, slen, data, dlen, - alg, NULL, NULL, ssh->compat); -} diff -ruN openssh-9.4p1/ssh_api.h openssh-9.4p1+x509-14.2.1/ssh_api.h --- openssh-9.4p1/ssh_api.h 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/ssh_api.h 2023-08-20 10:07:00.000000000 +0300 @@ -1,6 +1,7 @@ /* $OpenBSD: ssh_api.h,v 1.2 2018/04/10 00:10:49 djm Exp $ */ /* * Copyright (c) 2012 Markus Friedl. All rights reserved. + * Copyright (c) 2018 Roumen Petrov. All rights reserved. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -37,6 +38,21 @@ /* public SSH API functions */ /* + * ssh_crypto_init() initialize cryptographic library. + */ +void ssh_crypto_init(void); + +/* + * ssh_crypto_fini() finalize cryptographic library - release resources. + */ +void ssh_crypto_fini(void); + +/* + * release ssh connection state. + */ +void ssh_free(struct ssh *); + +/* * ssh_init() create a ssh connection object with given (optional) * key exchange parameters. */ diff -ruN openssh-9.4p1/sshbuf.c openssh-9.4p1+x509-14.2.1/sshbuf.c --- openssh-9.4p1/sshbuf.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/sshbuf.c 2023-08-20 10:07:01.000000000 +0300 @@ -36,7 +36,7 @@ fflush(stdout); \ } while (0) #else -# define SSHBUF_TELL(what) +# define SSHBUF_TELL(what) #endif struct sshbuf { @@ -185,10 +185,8 @@ sshbuf_free(buf->parent); buf->parent = NULL; - if (!buf->readonly) { - explicit_bzero(buf->d, buf->alloc); - free(buf->d); - } + if (!buf->readonly) + freezero(buf->d, buf->alloc); freezero(buf, sizeof(*buf)); } diff -ruN openssh-9.4p1/sshbuf-getput-basic.c openssh-9.4p1+x509-14.2.1/sshbuf-getput-basic.c --- openssh-9.4p1/sshbuf-getput-basic.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/sshbuf-getput-basic.c 2023-08-20 10:07:01.000000000 +0300 @@ -1,4 +1,4 @@ -/* $OpenBSD: sshbuf-getput-basic.c,v 1.13 2022/05/25 06:03:44 djm Exp $ */ +/* $OpenBSD: sshbuf-getput-basic.c,v 1.11 2020/06/05 03:25:35 djm Exp $ */ /* * Copyright (c) 2011 Damien Miller * diff -ruN openssh-9.4p1/sshbuf-getput-crypto.c openssh-9.4p1+x509-14.2.1/sshbuf-getput-crypto.c --- openssh-9.4p1/sshbuf-getput-crypto.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/sshbuf-getput-crypto.c 2023-08-20 10:07:01.000000000 +0300 @@ -1,6 +1,7 @@ /* $OpenBSD: sshbuf-getput-crypto.c,v 1.10 2022/05/25 06:03:44 djm Exp $ */ /* * Copyright (c) 2011 Damien Miller + * Copyright (c) 2020-2023 Roumen Petrov * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -15,6 +16,15 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifndef USE_OPENSSL_PROVIDER +/* TODO: implement OpenSSL 4.0 API, as OpenSSL 3.* is quite nonfunctional */ +# define OPENSSL_SUPPRESS_DEPRECATED +#endif + #define SSHBUF_INTERNAL #include "includes.h" @@ -24,10 +34,6 @@ #include #ifdef WITH_OPENSSL -#include -#ifdef OPENSSL_HAS_ECC -# include -#endif /* OPENSSL_HAS_ECC */ #include "ssherr.h" #include "sshbuf.h" @@ -35,24 +41,17 @@ int sshbuf_get_bignum2(struct sshbuf *buf, BIGNUM **valp) { - BIGNUM *v; const u_char *d; size_t len; int r; - if (valp != NULL) - *valp = NULL; + if (valp != NULL) *valp = NULL; if ((r = sshbuf_get_bignum2_bytes_direct(buf, &d, &len)) != 0) return r; - if (valp != NULL) { - if ((v = BN_new()) == NULL || - BN_bin2bn(d, len, v) == NULL) { - BN_clear_free(v); - return SSH_ERR_ALLOC_FAIL; - } - *valp = v; - } - return 0; + if (valp == NULL) return 0; + + *valp = BN_bin2bn(d, len, NULL); + return *valp != NULL ? 0 : SSH_ERR_ALLOC_FAIL; } #ifdef OPENSSL_HAS_ECC @@ -123,7 +122,7 @@ SSHBUF_ABORT(); return SSH_ERR_INTERNAL_ERROR; } - return 0; + return 0; } #endif /* OPENSSL_HAS_ECC */ @@ -177,4 +176,41 @@ EC_KEY_get0_group(v)); } #endif /* OPENSSL_HAS_ECC */ + +/* + * This is almost exactly the bignum1 encoding, but with 32 bit for length + * instead of 16. + */ +int +sshbuf_get_bignum1x(struct sshbuf *buf, BIGNUM **valp) { + int r; + u_int32_t bignum_bits; + int bytes; + BIGNUM *val; + + if ((r = sshbuf_get_u32(buf, &bignum_bits)) != 0) + return r; + + bytes = (bignum_bits + 7) / 8; + if (sshbuf_len(buf) < (size_t)bytes) + return SSH_ERR_NO_BUFFER_SPACE; + + val = BN_bin2bn(sshbuf_ptr(buf), bytes, NULL); + if (val == NULL) + return SSH_ERR_ALLOC_FAIL; + + if ((r = sshbuf_consume(buf, bytes)) != 0) { + r = SSH_ERR_INTERNAL_ERROR; + goto out; + } + + /* success */ + *valp = val; + val = NULL; + r = 0; + +out: + BN_clear_free(val); + return r; +} #endif /* WITH_OPENSSL */ diff -ruN openssh-9.4p1/sshbuf.h openssh-9.4p1+x509-14.2.1/sshbuf.h --- openssh-9.4p1/sshbuf.h 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/sshbuf.h 2023-08-20 10:07:00.000000000 +0300 @@ -1,6 +1,7 @@ /* $OpenBSD: sshbuf.h,v 1.28 2022/12/02 04:40:27 djm Exp $ */ /* * Copyright (c) 2011 Damien Miller + * Copyright (c) 2020-2022 Roumen Petrov * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -216,6 +217,7 @@ int sshbuf_get_bignum2_bytes_direct(struct sshbuf *buf, const u_char **valp, size_t *lenp); #ifdef WITH_OPENSSL +int sshbuf_get_bignum1x(struct sshbuf *buf, BIGNUM **valp); int sshbuf_get_bignum2(struct sshbuf *buf, BIGNUM **valp); int sshbuf_put_bignum2(struct sshbuf *buf, const BIGNUM *v); # ifdef OPENSSL_HAS_ECC @@ -238,8 +240,6 @@ /* Encode the contents of the buffer as base64 */ char *sshbuf_dtob64_string(const struct sshbuf *buf, int wrap); int sshbuf_dtob64(const struct sshbuf *d, struct sshbuf *b64, int wrap); -/* RFC4648 "base64url" encoding variant */ -int sshbuf_dtourlb64(const struct sshbuf *d, struct sshbuf *b64, int wrap); /* Decode base64 data and append it to the buffer */ int sshbuf_b64tod(struct sshbuf *buf, const char *b64); @@ -278,6 +278,7 @@ */ char *sshbuf_dup_string(struct sshbuf *buf); +int sshbuf_allocate_fd(int fd, struct sshbuf *b); /* * Fill a buffer from a file descriptor or filename. Both allocate the * buffer for the caller. diff -ruN openssh-9.4p1/sshbuf-io.c openssh-9.4p1+x509-14.2.1/sshbuf-io.c --- openssh-9.4p1/sshbuf-io.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/sshbuf-io.c 2023-08-20 10:07:01.000000000 +0300 @@ -1,6 +1,7 @@ /* $OpenBSD: sshbuf-io.c,v 1.2 2020/01/25 23:28:06 djm Exp $ */ /* * Copyright (c) 2011 Damien Miller + * Copyright (c) 2020 Roumen Petrov * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -29,6 +30,16 @@ #include "sshbuf.h" #include "atomicio.h" +/* grow buffer to avoid reallocation for large files */ +int +sshbuf_allocate_fd(int fd, struct sshbuf *b) +{ + struct stat st; + return fstat(fd, &st) != -1 && st.st_size > 0 + ? sshbuf_allocate(b, st.st_size) + : 0; +} + /* Load a file from a fd into a buffer */ int sshbuf_load_fd(int fd, struct sshbuf **blobp) @@ -80,20 +91,17 @@ int sshbuf_load_file(const char *path, struct sshbuf **bufp) { - int r, fd, oerrno; + int r, fd; *bufp = NULL; if ((fd = open(path, O_RDONLY)) == -1) return SSH_ERR_SYSTEM_ERROR; - if ((r = sshbuf_load_fd(fd, bufp)) != 0) - goto out; - /* success */ - r = 0; - out: - oerrno = errno; + r = sshbuf_load_fd(fd, bufp); + +{ int oerrno = errno; close(fd); - if (r != 0) - errno = oerrno; + errno = oerrno; +} return r; } @@ -105,13 +113,15 @@ if ((fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644)) == -1) return SSH_ERR_SYSTEM_ERROR; if (atomicio(vwrite, fd, sshbuf_mutable_ptr(buf), - sshbuf_len(buf)) != sshbuf_len(buf) || close(fd) != 0) { + sshbuf_len(buf)) != sshbuf_len(buf)) { oerrno = errno; close(fd); unlink(path); errno = oerrno; return SSH_ERR_SYSTEM_ERROR; } + oerrno = errno; + close(fd); + errno = oerrno; return 0; } - diff -ruN openssh-9.4p1/sshbuf-misc.c openssh-9.4p1+x509-14.2.1/sshbuf-misc.c --- openssh-9.4p1/sshbuf-misc.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/sshbuf-misc.c 2023-08-20 10:07:01.000000000 +0300 @@ -168,49 +168,6 @@ return 0; } -int -sshbuf_dtourlb64(const struct sshbuf *d, struct sshbuf *b64, int wrap) -{ - int r = SSH_ERR_INTERNAL_ERROR; - u_char *p; - struct sshbuf *b = NULL; - size_t i, l; - - if ((b = sshbuf_new()) == NULL) - return SSH_ERR_ALLOC_FAIL; - /* Encode using regular base64; we'll transform it once done */ - if ((r = sshbuf_dtob64(d, b, wrap)) != 0) - goto out; - /* remove padding from end of encoded string*/ - for (;;) { - l = sshbuf_len(b); - if (l <= 1 || sshbuf_ptr(b) == NULL) { - r = SSH_ERR_INTERNAL_ERROR; - goto out; - } - if (sshbuf_ptr(b)[l - 1] != '=') - break; - if ((r = sshbuf_consume_end(b, 1)) != 0) - goto out; - } - /* Replace characters with rfc4648 equivalents */ - l = sshbuf_len(b); - if ((p = sshbuf_mutable_ptr(b)) == NULL) { - r = SSH_ERR_INTERNAL_ERROR; - goto out; - } - for (i = 0; i < l; i++) { - if (p[i] == '+') - p[i] = '-'; - else if (p[i] == '/') - p[i] = '_'; - } - r = sshbuf_putb(b64, b); - out: - sshbuf_free(b); - return r; -} - char * sshbuf_dup_string(struct sshbuf *buf) { @@ -275,7 +232,6 @@ sshbuf_read(int fd, struct sshbuf *buf, size_t maxlen, size_t *rlen) { int r, oerrno; - size_t adjust; ssize_t rr; u_char *d; @@ -287,17 +243,19 @@ oerrno = errno; /* Adjust the buffer to include only what was actually read */ - if ((adjust = maxlen - (rr > 0 ? rr : 0)) != 0) { - if ((r = sshbuf_consume_end(buf, adjust)) != 0) { - /* avoid returning uninitialised data to caller */ - memset(d + rr, '\0', adjust); +{ size_t adjust = maxlen - MAX(rr, 0); + if (adjust != 0) { + /* avoid returning uninitialised data to caller */ + memset(d + MAX(rr, 0), '\0', adjust); + if ((r = sshbuf_consume_end(buf, adjust)) != 0) return SSH_ERR_INTERNAL_ERROR; /* shouldn't happen */ - } } +} if (rr < 0) { errno = oerrno; return SSH_ERR_SYSTEM_ERROR; - } else if (rr == 0) { + } + if (rr == 0) { errno = EPIPE; return SSH_ERR_SYSTEM_ERROR; } diff -ruN openssh-9.4p1/ssh.c openssh-9.4p1+x509-14.2.1/ssh.c --- openssh-9.4p1/ssh.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/ssh.c 2023-08-20 10:07:01.000000000 +0300 @@ -19,6 +19,8 @@ * Modified to work with SSLeay by Niels Provos * in Canada (German citizen). * + * Copyright (c) 2002-2023 Roumen Petrov. All rights reserved. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -65,7 +67,6 @@ #include #include #include -#include #include #include #include @@ -77,8 +78,16 @@ #include #include #endif -#include "openbsd-compat/openssl-compat.h" + +#ifdef HAVE_FIPSCHECK_H +# include +#endif + #include "openbsd-compat/sys-queue.h" +#ifdef LDAP_ENABLED +/* OpenSSL extension defined in ssh_ldap.c */ +extern void ERR_load_SSHLDAP_strings(void); +#endif #include "xmalloc.h" #include "ssh.h" @@ -90,6 +99,8 @@ #include "sshbuf.h" #include "channels.h" #include "sshkey.h" +#include "ssh-x509.h" +#include "key-eng.h" #include "authfd.h" #include "authfile.h" #include "pathnames.h" @@ -114,12 +125,17 @@ #endif extern char *__progname; +extern struct sshkey *previous_host_key; /* sshconnect.c */ /* Saves a copy of argv for setproctitle emulation */ #ifndef HAVE_SETPROCTITLE static char **saved_av; #endif +/* used in ssh-x509.c */ +extern int (*pssh_x509store_verify_cert)(X509 *cert, STACK_OF(X509) *untrusted); +extern STACK_OF(X509)* (*pssh_x509store_build_certchain)(X509 *cert, STACK_OF(X509) *untrusted); + /* Flag indicating whether debug mode is on. May be set on the command line. */ int debug_flag = 0; @@ -162,7 +178,7 @@ struct sockaddr_storage hostaddr; /* Private host keys. */ -Sensitive sensitive_data; +static Sensitive sensitive_data; /* command to be executed */ struct sshbuf *command; @@ -179,10 +195,20 @@ static void usage(void) { +#undef USAGE_OPENSSL_ENGINE +#ifndef USE_OPENSSL_ENGINE +# define USAGE_OPENSSL_ENGINE +#else +# define USAGE_OPENSSL_ENGINE \ +" [-G engineconfigfile]\n" +#endif fprintf(stderr, -"usage: ssh [-46AaCfGgKkMNnqsTtVvXxYy] [-B bind_interface] [-b bind_address]\n" +"usage: ssh [-46AaCdfgKkMNnqsTtVvXxYy] [-B bind_interface] [-b bind_address]\n" " [-c cipher_spec] [-D [bind_address:]port] [-E log_file]\n" -" [-e escape_char] [-F configfile] [-I pkcs11] [-i identity_file]\n" +" [-e escape_char] [-F configfile]\n" +USAGE_OPENSSL_ENGINE +" [-I pkcs11]\n" +" [-i identity_file]\n" " [-J destination] [-L address] [-l login_name] [-m mac_spec]\n" " [-O ctl_cmd] [-o option] [-P tag] [-p port] [-Q query_option]\n" " [-R address] [-S ctl_path] [-W host:port] [-w local_tun[:remote_tun]]\n" @@ -252,7 +278,6 @@ resolve_host(const char *name, int port, int logerr, char *cname, size_t clen) { char strport[NI_MAXSERV]; - const char *errstr = NULL; struct addrinfo hints, *res; int gaierr; LogLevel loglevel = SYSLOG_LEVEL_DEBUG1; @@ -278,6 +303,7 @@ return NULL; } if (cname != NULL && res->ai_canonname != NULL) { + const char *errstr; if (!valid_domain(res->ai_canonname, 0, &errstr)) { error("ignoring bad CNAME \"%s\" for host \"%s\": %s", res->ai_canonname, name, errstr); @@ -361,12 +387,12 @@ } if ((gaierr = getnameinfo(res->ai_addr, res->ai_addrlen, addr, sizeof(addr), NULL, 0, NI_NUMERICHOST)) != 0) { - debug_f("Could not format address for name %.100s: %s", + debug_f("could not format address for name %.100s: %s", name, ssh_gai_strerror(gaierr)); goto fail; } if (strlcpy(caddr, addr, clen) >= clen) { - error_f("host \"%s\" addr \"%s\" too long (max %lu)", + debug_f("host \"%s\" addr \"%s\" too long (max %lu)", name, addr, (u_long)clen); if (clen > 0) *caddr = '\0'; @@ -491,8 +517,6 @@ } /* Attempt each supplied suffix */ for (i = 0; i < options.num_canonical_domains; i++) { - if (strcasecmp(options.canonical_domains[i], "none") == 0) - break; xasprintf(&fullhost, "%s.%s.", *hostp, options.canonical_domains[i]); debug3_f("attempting \"%s\" => \"%s\"", *hostp, fullhost); @@ -521,7 +545,7 @@ } /* - * Check the result of hostkey loading, ignoring some errors and either + * Check the result of indentity loading, ignoring some errors and either * discarding the key or fatal()ing for others. */ static void @@ -529,14 +553,18 @@ { switch (r) { case 0: - /* Check RSA keys size and discard if undersized */ + #if 0 + /* NOTE: key size is validated on read, sign and verify */ + /* Check keys size and discard if undersized */ if (k != NULL && *k != NULL && - (r = sshkey_check_rsa_length(*k, - options.required_rsa_size)) != 0) { + (r = sshkey_check_length(*k)) != 0) { error_r(r, "load %s \"%s\"", message, path); free(*k); *k = NULL; } + #else + UNUSED(k); + #endif break; case SSH_ERR_INTERNAL_ERROR: case SSH_ERR_ALLOC_FAIL: @@ -634,17 +662,19 @@ int i, r, opt, exit_status, use_syslog, direct, timeout_ms; int was_addr, config_test = 0, opt_terminated = 0, want_final_pass = 0; char *p, *cp, *line, *argv0, *logfile; - char cname[NI_MAXHOST], thishost[NI_MAXHOST]; +#ifdef USE_OPENSSL_ENGINE + char *engconfig = NULL; +#endif + char cname[NI_MAXHOST]; struct stat st; struct passwd *pw; extern int optind, optreset; extern char *optarg; struct Forward fwd; struct addrinfo *addrs = NULL; - size_t n, len; - u_int j; struct ssh_conn_info *cinfo = NULL; + ssh_malloc_init(); /* must be called before any mallocs */ /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ sanitise_stdfd(); @@ -654,7 +684,30 @@ */ closefrom(STDERR_FILENO + 1); - __progname = ssh_get_progname(av[0]); + argv0 = av[0]; + __progname = ssh_get_progname(argv0); + ssh_OpenSSL_startup(); +#ifdef OPENSSL_FIPS + if (FIPS_mode()) { + #ifdef HAVE_FIPSCHECK_H + if (!FIPSCHECK_verify(NULL, NULL)) + fatal("FIPS integrity verification test failed."); + #endif + fprintf(stderr, "%s runs in FIPS mode\n", __progname); + } +#endif /*def OPENSSL_FIPS*/ + ssh_engines_startup(); +#ifdef WITH_OPENSSL + ssh_OpenSSL_load_error_strings(); +#ifdef LDAP_ENABLED + ERR_load_SSHLDAP_strings(); +#endif +#ifdef ENABLE_PKCS11 + ERR_load_PKCS11_strings(); +#endif +#endif + pssh_x509store_verify_cert = ssh_x509store_verify_cert; + pssh_x509store_build_certchain = ssh_x509store_build_certchain; #ifndef HAVE_SETPROCTITLE /* Prepare for later setproctitle emulation */ @@ -705,11 +758,16 @@ host = NULL; use_syslog = 0; logfile = NULL; - argv0 = av[0]; again: - while ((opt = getopt(ac, av, "1246ab:c:e:fgi:kl:m:no:p:qstvx" - "AB:CD:E:F:GI:J:KL:MNO:P:Q:R:S:TVw:W:XYy")) != -1) { /* HUZdhjruz */ +#ifdef USE_OPENSSL_ENGINE +# define ENGCONFIG "G:" +#else +# define ENGCONFIG "" +#endif + + while ((opt = getopt(ac, av, "1246ab:c:de:fgi:kl:m:no:p:qstvx" + "AB:CD:E:F:" ENGCONFIG "I:J:KL:MNO:P:Q:R:S:TVw:W:XYy")) != -1) { switch (opt) { case '1': fatal("SSH protocol v.1 is no longer supported"); @@ -742,7 +800,7 @@ case 'E': logfile = optarg; break; - case 'G': + case 'd': config_test = 1; break; case 'Y': @@ -779,49 +837,48 @@ break; case 'Q': cp = NULL; - if (strcmp(optarg, "cipher") == 0 || - strcasecmp(optarg, "Ciphers") == 0) + if (strcmp(optarg, "cipher") == 0) cp = cipher_alg_list('\n', 0); else if (strcmp(optarg, "cipher-auth") == 0) cp = cipher_alg_list('\n', 1); - else if (strcmp(optarg, "mac") == 0 || - strcasecmp(optarg, "MACs") == 0) + else if (strcmp(optarg, "mac") == 0) cp = mac_alg_list('\n'); - else if (strcmp(optarg, "kex") == 0 || - strcasecmp(optarg, "KexAlgorithms") == 0) + else if (strcmp(optarg, "kex") == 0) cp = kex_alg_list('\n'); else if (strcmp(optarg, "key") == 0) cp = sshkey_alg_list(0, 0, 0, '\n'); + else if (strcmp(optarg, "key-alg") == 0) + cp = sshkey_alg_list(0, 0, 1, '\n'); else if (strcmp(optarg, "key-cert") == 0) cp = sshkey_alg_list(1, 0, 0, '\n'); else if (strcmp(optarg, "key-plain") == 0) cp = sshkey_alg_list(0, 1, 0, '\n'); - else if (strcmp(optarg, "key-ca-sign") == 0 || - strcasecmp(optarg, "CASignatureAlgorithms") == 0) + else if (strcmp(optarg, "key-ca-sign") == 0) + #if 0 /* Duplicate, see "sig"! */ cp = sshkey_alg_list(0, 1, 1, '\n'); - else if (strcmp(optarg, "key-sig") == 0 || - strcasecmp(optarg, "PubkeyAcceptedKeyTypes") == 0 || /* deprecated name */ - strcasecmp(optarg, "PubkeyAcceptedAlgorithms") == 0 || - strcasecmp(optarg, "HostKeyAlgorithms") == 0 || - strcasecmp(optarg, "HostbasedKeyTypes") == 0 || /* deprecated name */ - strcasecmp(optarg, "HostbasedAcceptedKeyTypes") == 0 || /* deprecated name */ - strcasecmp(optarg, "HostbasedAcceptedAlgorithms") == 0) - cp = sshkey_alg_list(0, 0, 1, '\n'); + #else + cp = xstrdup(""); + #endif else if (strcmp(optarg, "sig") == 0) + #if 0 /* Useless and faulty! + Algorithm determine key type, how to encode key material + and signature (algorithm and encoding format). */ cp = sshkey_alg_list(0, 1, 1, '\n'); + #else + cp = xstrdup(""); + #endif else if (strcmp(optarg, "protocol-version") == 0) cp = xstrdup("2"); else if (strcmp(optarg, "compression") == 0) { cp = xstrdup(compression_alg_list(0)); - len = strlen(cp); - for (n = 0; n < len; n++) - if (cp[n] == ',') - cp[n] = '\n'; + for (p = cp; *p != '\0'; p++) + if (*p == ',') + *p = '\n'; } else if (strcmp(optarg, "help") == 0) { cp = xstrdup( - "cipher\ncipher-auth\ncompression\nkex\n" - "key\nkey-cert\nkey-plain\nkey-sig\nmac\n" - "protocol-version\nsig"); + "cipher\ncipher-auth\ncompression\nkex" + "\nkey\nkey-alg\nkey-cert\nkey-plain" + "\nmac\nprotocol-version"); } if (cp == NULL) fatal("Unsupported query \"%s\"", optarg); @@ -843,13 +900,26 @@ options.gss_deleg_creds = 1; break; case 'i': - p = tilde_expand_filename(optarg, getuid()); - if (stat(p, &st) == -1) + { int external = ( +#ifdef USE_OPENSSL_ENGINE + (strncmp(optarg, "engine:", 7) == 0) || +#endif +#ifdef USE_OPENSSL_STORE2 + (strncmp(optarg, "store:", 6) == 0) || +#endif + 0 + ); + p = !external + ? tilde_expand_filename(optarg, getuid()) + : NULL; + } + if (p != NULL && + stat(p, &st) == -1) fprintf(stderr, "Warning: Identity file %s " "not accessible: %s.\n", p, strerror(errno)); else - add_identity_file(&options, NULL, p, 1); + add_identity_file(&options, NULL, p != NULL ? p : optarg, 1); free(p); break; case 'I': @@ -881,7 +951,7 @@ case 'v': if (debug_flag == 0) { debug_flag = 1; - options.log_level = SYSLOG_LEVEL_DEBUG1; + options.log_level = SYSLOG_LEVEL_VERBOSE; } else { if (options.log_level < SYSLOG_LEVEL_DEBUG3) { debug_flag++; @@ -891,7 +961,7 @@ break; case 'V': fprintf(stderr, "%s, %s\n", - SSH_RELEASE, SSH_OPENSSL_VERSION); + SSH_RELEASE, ssh_OpenSSL_version_text()); exit(0); break; case 'w': @@ -943,7 +1013,8 @@ } break; case 'c': - if (!ciphers_valid(*optarg == '+' || *optarg == '^' ? + if (*optarg != '-' && + !ciphers_valid(*optarg == '+' || *optarg == '^' ? optarg + 1 : optarg)) { fprintf(stderr, "Unknown cipher type '%s'\n", optarg); @@ -953,14 +1024,15 @@ options.ciphers = xstrdup(optarg); break; case 'm': - if (mac_valid(optarg)) { - free(options.macs); - options.macs = xstrdup(optarg); - } else { + if (*optarg != '-' && + !mac_valid(*optarg == '+' || *optarg == '^' ? + optarg + 1 : optarg)) { fprintf(stderr, "Unknown mac type '%s'\n", optarg); exit(255); } + free(options.macs); + options.macs = xstrdup(optarg); break; case 'M': if (options.control_master == SSHCTL_MASTER_YES) @@ -1061,6 +1133,11 @@ case 'F': config = optarg; break; +#ifdef USE_OPENSSL_ENGINE + case 'G': + engconfig = optarg; + break; +#endif default: usage(); } @@ -1143,7 +1220,11 @@ } } - ssh_signal(SIGPIPE, SIG_IGN); /* ignore SIGPIPE early */ + /* + * Ignore SIGPIPE early, for instance before muxclient() which performs + * operations that could cause signal. + */ + ssh_signal(SIGPIPE, SIG_IGN); /* * Initialize "log" output. Since we are the client all output @@ -1153,7 +1234,7 @@ fatal("Can't specify both -y and -E"); if (logfile != NULL) log_redirect_stderr_to(logfile); - log_init(argv0, + log_init(__progname, options.log_level == SYSLOG_LEVEL_NOT_SET ? SYSLOG_LEVEL_INFO : options.log_level, options.log_facility == SYSLOG_FACILITY_NOT_SET ? @@ -1161,7 +1242,33 @@ !use_syslog); if (debug_flag) - logit("%s, %s", SSH_RELEASE, SSH_OPENSSL_VERSION); + logit("%s, %s", SSH_RELEASE, ssh_OpenSSL_version_text()); + +#ifdef USE_OPENSSL_ENGINE + /* process per-user engine configuration file */ +{ char *filename = NULL; + + if (engconfig == NULL) + engconfig = getenv(SSH_ENGINE_CONF_ENV); + if (engconfig == NULL) + xasprintf(&filename, "%s/%s", pw->pw_dir, + _PATH_SSH_ENGINE_CONFFILE); /*fatal on error*/ + else + filename = engconfig; + + r = process_engconfig_file(filename); + if (!r) { + if (engconfig != NULL) + debug("cannot process engine config file %s:" + " %s", engconfig, strerror(errno)); + else + debug("cannot process default engine config file:" + " %s", strerror(errno)); + } + if (filename != engconfig) + free(filename); +} +#endif /* Parse the configuration files */ process_config_files(options.host_arg, pw, 0, &want_final_pass); @@ -1175,7 +1282,8 @@ if (options.hostname != NULL) { /* NB. Please keep in sync with readconf.c:match_cfg_line() */ cp = percent_expand(options.hostname, - "h", host, (char *)NULL); + "h", host, + (char *)NULL); free(host); host = cp; free(options.hostname); @@ -1269,10 +1377,10 @@ fatal("jumphost loop via %s", options.jump_host); /* - * Try to use SSH indicated by argv[0], but fall back to - * "ssh" if it appears unavailable. + * Try to use SSH executable indicated by argv[0], but fall + * back to "ssh" if it is not executable. */ - if (strchr(argv0, '/') != NULL && access(argv0, X_OK) != 0) + if (strchr(sshbin, '/') != NULL && access(sshbin, X_OK) != 0) sshbin = "ssh"; /* Consistency check */ @@ -1298,7 +1406,7 @@ config == NULL ? "" : config, /* Optional "-v" arguments if -v set */ debug_flag ? " -" : "", - debug_flag, "vvv", + debug_flag, "vvvv", /* Mandatory hostname */ options.jump_host); debug("Setting implicit ProxyCommand from ProxyJump: %s", @@ -1317,7 +1425,14 @@ options.proxy_use_fdpass) fatal("ProxyCommand=- and ProxyUseFDPass are incompatible"); if (options.update_hostkeys == SSH_UPDATE_HOSTKEYS_ASK) { - if (options.control_persist && options.control_path != NULL) { + if (options.log_level < SYSLOG_LEVEL_INFO) { + /* no point logging anything; user won't see it */ + options.update_hostkeys = 0; + } else if (options.batch_mode) { + debug("UpdateHostKeys=ask is incompatible with " + "batch mode; disabling"); + options.update_hostkeys = 0; + } else if (options.control_persist && options.control_path != NULL) { debug("UpdateHostKeys=ask is incompatible with " "ControlPersist; disabling"); options.update_hostkeys = 0; @@ -1327,9 +1442,6 @@ debug("UpdateHostKeys=ask is incompatible with " "remote command execution; disabling"); options.update_hostkeys = 0; - } else if (options.log_level < SYSLOG_LEVEL_INFO) { - /* no point logging anything; user won't see it */ - options.update_hostkeys = 0; } } if (options.connection_attempts <= 0) @@ -1346,12 +1458,8 @@ "to execute."); /* reinit */ - log_init(argv0, options.log_level, options.log_facility, !use_syslog); - for (j = 0; j < options.num_log_verbose; j++) { - if (strcasecmp(options.log_verbose[j], "none") == 0) - break; - log_verbose_add(options.log_verbose[j]); - } + log_init(__progname, options.log_level, options.log_facility, !use_syslog); + log_verbose_init(options.log_verbose, options.num_log_verbose); if (options.request_tty == REQUEST_TTY_YES || options.request_tty == REQUEST_TTY_FORCE) @@ -1377,23 +1485,25 @@ /* Set up strings used to percent_expand() arguments */ cinfo = xcalloc(1, sizeof(*cinfo)); +{ char thishost[NI_MAXHOST]; if (gethostname(thishost, sizeof(thishost)) == -1) fatal("gethostname: %s", strerror(errno)); cinfo->thishost = xstrdup(thishost); thishost[strcspn(thishost, ".")] = '\0'; cinfo->shorthost = xstrdup(thishost); +} xasprintf(&cinfo->portstr, "%d", options.port); xasprintf(&cinfo->uidstr, "%llu", (unsigned long long)pw->pw_uid); cinfo->keyalias = xstrdup(options.host_key_alias ? options.host_key_alias : options.host_arg); - cinfo->conn_hash_hex = ssh_connection_hash(cinfo->thishost, host, - cinfo->portstr, options.user); cinfo->host_arg = xstrdup(options.host_arg); cinfo->remhost = xstrdup(host); cinfo->remuser = xstrdup(options.user); cinfo->homedir = xstrdup(pw->pw_dir); cinfo->locuser = xstrdup(pw->pw_name); + cinfo->conn_hash_hex = ssh_connection_hash(cinfo->thishost, + cinfo->remhost, cinfo->portstr, cinfo->remuser); /* * Expand tokens in arguments. NB. LocalCommand is expanded later, @@ -1403,8 +1513,8 @@ if (options.remote_command != NULL) { debug3("expanding RemoteCommand: %s", options.remote_command); cp = options.remote_command; - options.remote_command = default_client_percent_expand(cp, - cinfo); + options.remote_command = + default_client_percent_expand(cp, cinfo); debug3("expanded RemoteCommand: %s", options.remote_command); free(cp); if ((r = sshbuf_put(command, options.remote_command, @@ -1415,40 +1525,43 @@ if (options.control_path != NULL) { cp = tilde_expand_filename(options.control_path, getuid()); free(options.control_path); - options.control_path = default_client_percent_dollar_expand(cp, - cinfo); + options.control_path = + default_client_percent_dollar_expand(cp, cinfo); free(cp); } - if (options.identity_agent != NULL) { - p = tilde_expand_filename(options.identity_agent, getuid()); - cp = default_client_percent_dollar_expand(p, cinfo); - free(p); + if (options.identity_agent != NULL && + strcmp(options.identity_agent, SSH_AUTHSOCKET_ENV_NAME) != 0 && + strcmp(options.identity_agent, "none") != 0) { + cp = tilde_expand_filename(options.identity_agent, getuid()); free(options.identity_agent); - options.identity_agent = cp; + options.identity_agent = + default_client_percent_dollar_expand(cp, cinfo); + free(cp); } if (options.revoked_host_keys != NULL) { - p = tilde_expand_filename(options.revoked_host_keys, getuid()); - cp = default_client_percent_dollar_expand(p, cinfo); - free(p); + cp = tilde_expand_filename(options.revoked_host_keys, getuid()); free(options.revoked_host_keys); - options.revoked_host_keys = cp; + options.revoked_host_keys = + default_client_percent_dollar_expand(cp, cinfo); + free(cp); } - if (options.forward_agent_sock_path != NULL) { - p = tilde_expand_filename(options.forward_agent_sock_path, + if (options.forward_agent && + options.forward_agent_sock_path != NULL) { + cp = tilde_expand_filename(options.forward_agent_sock_path, getuid()); - cp = default_client_percent_dollar_expand(p, cinfo); - free(p); free(options.forward_agent_sock_path); - options.forward_agent_sock_path = cp; - if (stat(options.forward_agent_sock_path, &st) != 0) { + options.forward_agent_sock_path = + default_client_percent_dollar_expand(cp, cinfo); + if (stat(options.forward_agent_sock_path, &st) == -1) { error("Cannot forward agent socket path \"%s\": %s", options.forward_agent_sock_path, strerror(errno)); if (options.exit_on_forward_failure) cleanup_exit(255); } + free(cp); } if (options.num_system_hostfiles > 0 && @@ -1470,17 +1583,17 @@ options.user_hostfiles[0] = NULL; options.num_user_hostfiles = 0; } - for (j = 0; j < options.num_user_hostfiles; j++) { - if (options.user_hostfiles[j] == NULL) - continue; - cp = tilde_expand_filename(options.user_hostfiles[j], getuid()); - p = default_client_percent_dollar_expand(cp, cinfo); - if (strcmp(options.user_hostfiles[j], p) != 0) - debug3("expanded UserKnownHostsFile '%s' -> " - "'%s'", options.user_hostfiles[j], p); - free(options.user_hostfiles[j]); + for (i = 0; (u_int)i < options.num_user_hostfiles; i++) { + p = options.user_hostfiles[i]; + if (p == NULL) continue; + cp = tilde_expand_filename(p, getuid()); + options.user_hostfiles[i] = + default_client_percent_dollar_expand(cp, cinfo); + if (strcmp(options.user_hostfiles[i], p) != 0) + debug3("expanded UserKnownHostsFile path " + "'%s' -> '%s'", p, options.user_hostfiles[i]); free(cp); - options.user_hostfiles[j] = p; + free(p); } for (i = 0; i < options.num_local_forwards; i++) { @@ -1530,22 +1643,6 @@ exit(0); } - /* Expand SecurityKeyProvider if it refers to an environment variable */ - if (options.sk_provider != NULL && *options.sk_provider == '$' && - strlen(options.sk_provider) > 1) { - if ((cp = getenv(options.sk_provider + 1)) == NULL) { - debug("Authenticator provider %s did not resolve; " - "disabling", options.sk_provider); - free(options.sk_provider); - options.sk_provider = NULL; - } else { - debug2("resolved SecurityKeyProvider %s => %s", - options.sk_provider, cp); - free(options.sk_provider); - options.sk_provider = xstrdup(cp); - } - } - if (muxclient_command != 0 && options.control_path == NULL) fatal("No ControlPath specified for \"-O\" command"); if (options.control_path != NULL) { @@ -1609,7 +1706,7 @@ check_load(sshkey_load_public(p, &(sensitive_data.keys[o]), NULL), \ &(sensitive_data.keys[o]), p, "pubkey"); \ if (sensitive_data.keys[o] != NULL) { \ - debug2("hostbased key %d: %s key from \"%s\"", o, \ + debug3("hostbased key %d: %s key from \"%s\"", o, \ sshkey_ssh_name(sensitive_data.keys[o]), p); \ loaded++; \ } \ @@ -1620,25 +1717,31 @@ check_load(sshkey_load_cert(p, &(sensitive_data.keys[o])), \ &(sensitive_data.keys[o]), p, "cert"); \ if (sensitive_data.keys[o] != NULL) { \ - debug2("hostbased key %d: %s cert from \"%s\"", o, \ + debug3("hostbased key %d: %s cert from \"%s\"", o, \ sshkey_ssh_name(sensitive_data.keys[o]), p); \ loaded++; \ } \ } while (0) if (options.hostbased_authentication == 1) { - L_CERT(_PATH_HOST_ECDSA_KEY_FILE, 0); - L_CERT(_PATH_HOST_ED25519_KEY_FILE, 1); + L_CERT(_PATH_HOST_ED25519_KEY_FILE, 0); +#ifdef OPENSSL_HAS_ECC + L_CERT(_PATH_HOST_ECDSA_KEY_FILE, 1); +#endif L_CERT(_PATH_HOST_RSA_KEY_FILE, 2); L_CERT(_PATH_HOST_DSA_KEY_FILE, 3); - L_PUBKEY(_PATH_HOST_ECDSA_KEY_FILE, 4); - L_PUBKEY(_PATH_HOST_ED25519_KEY_FILE, 5); + L_PUBKEY(_PATH_HOST_ED25519_KEY_FILE, 4); +#ifdef OPENSSL_HAS_ECC + L_PUBKEY(_PATH_HOST_ECDSA_KEY_FILE, 5); +#endif L_PUBKEY(_PATH_HOST_RSA_KEY_FILE, 6); L_PUBKEY(_PATH_HOST_DSA_KEY_FILE, 7); +#ifdef WITH_XMSS L_CERT(_PATH_HOST_XMSS_KEY_FILE, 8); L_PUBKEY(_PATH_HOST_XMSS_KEY_FILE, 9); +#endif if (loaded == 0) - debug("HostbasedAuthentication enabled but no " + verbose("HostbasedAuthentication enabled but no " "local public host keys could be loaded."); } } @@ -1653,6 +1756,11 @@ unsetenv(SSH_AUTHSOCKET_ENV_NAME); } else { cp = options.identity_agent; + /* + * If identity_agent represents an environment variable + * then recheck that it is valid since token expand + * may have changed it and substitute its value. + */ /* legacy (limited) format */ if (cp[0] == '$' && cp[1] != '{') { if (!valid_env_name(cp + 1)) { @@ -1680,7 +1788,6 @@ forward_agent_sock_path = xstrdup(p); else options.forward_agent = 0; - free(cp); } else { forward_agent_sock_path = cp; } @@ -1729,7 +1836,8 @@ skip_connect: exit_status = ssh_session2(ssh, cinfo); ssh_conn_info_free(cinfo); - ssh_packet_close(ssh); + (void)ssh_packet_close(ssh); + free(ssh); if (options.control_path != NULL && muxserver_sock != -1) unlink(options.control_path); @@ -1737,6 +1845,15 @@ /* Kill ProxyCommand if it is running. */ ssh_kill_proxy_command(); + /* clean-up some memory - goal is to ensure more clean OpenSSL shuthdown */ + sshkey_free(previous_host_key); + previous_host_key = NULL; + + cleanup_options(&options); + + ssh_engines_shutdown(); + ssh_OpenSSL_shuthdown(); + return exit_status; } @@ -1758,10 +1875,7 @@ /* Child: master process continues mainloop */ break; default: - /* - * Parent: set up mux client to connect to backgrounded - * master. - */ + /* Parent: set up mux client to connect to backgrounded master */ debug2_f("background process is %ld", (long)pid); options.stdin_null = ostdin_null_flag; options.request_tty = orequest_tty; @@ -1775,8 +1889,10 @@ /* muxclient() doesn't return on success. */ fatal("Failed to connect to new control master"); } - if (stdfd_devnull(1, 1, !(log_is_on_stderr() && debug_flag)) == -1) +{ int keep_stderr = debug_flag && log_is_on_stderr(); + if (stdfd_devnull(1, 1, !keep_stderr) == -1) error_f("stdfd_devnull failed"); +} daemon(1, 1); setproctitle("%s [mux]", options.control_path); } @@ -1791,14 +1907,16 @@ options.fork_after_authentication = 0; if (daemon(1, 1) == -1) fatal("daemon() failed: %.200s", strerror(errno)); - if (stdfd_devnull(1, 1, !(log_is_on_stderr() && debug_flag)) == -1) +{ int keep_stderr = debug_flag && log_is_on_stderr(); + if (stdfd_devnull(1, 1, !keep_stderr) == -1) error_f("stdfd_devnull failed"); } +} static void forwarding_success(void) { - if (forward_confirms_pending == -1) + if (forward_confirms_pending < 0) return; if (--forward_confirms_pending == 0) { debug_f("all expected forwarding replies received"); @@ -1815,25 +1933,27 @@ ssh_confirm_remote_forward(struct ssh *ssh, int type, u_int32_t seq, void *ctxt) { struct Forward *rfwd = (struct Forward *)ctxt; - u_int port; int r; + UNUSED(seq); /* XXX verbose() on failure? */ +{ const char *connect_path = rfwd->connect_path != NULL + ? rfwd->connect_path : rfwd->connect_host; debug("remote forward %s for: listen %s%s%d, connect %s:%d", type == SSH2_MSG_REQUEST_SUCCESS ? "success" : "failure", rfwd->listen_path ? rfwd->listen_path : rfwd->listen_host ? rfwd->listen_host : "", (rfwd->listen_path || rfwd->listen_host) ? ":" : "", - rfwd->listen_port, rfwd->connect_path ? rfwd->connect_path : - rfwd->connect_host, rfwd->connect_port); + rfwd->listen_port, connect_path, rfwd->connect_port); if (rfwd->listen_path == NULL && rfwd->listen_port == 0) { if (type == SSH2_MSG_REQUEST_SUCCESS) { + u_int32_t port; if ((r = sshpkt_get_u32(ssh, &port)) != 0) fatal_fr(r, "parse packet"); if (port > 65535) { error("Invalid allocated port %u for remote " - "forward to %s:%d", port, - rfwd->connect_host, rfwd->connect_port); + "forward to %s:%d", (unsigned)port, + connect_path, rfwd->connect_port); /* Ensure failure processing runs below */ type = SSH2_MSG_REQUEST_FAILURE; channel_update_permission(ssh, @@ -1842,8 +1962,7 @@ rfwd->allocated_port = (int)port; logit("Allocated port %u for remote " "forward to %s:%d", - rfwd->allocated_port, rfwd->connect_path ? - rfwd->connect_path : rfwd->connect_host, + rfwd->allocated_port, connect_path, rfwd->connect_port); channel_update_permission(ssh, rfwd->handle, rfwd->allocated_port); @@ -1852,6 +1971,7 @@ channel_update_permission(ssh, rfwd->handle, -1); } } +} if (type == SSH2_MSG_REQUEST_FAILURE) { if (options.exit_on_forward_failure) { @@ -1876,6 +1996,10 @@ static void client_cleanup_stdio_fwd(struct ssh *ssh, int id, int force, void *arg) { + UNUSED(ssh); + UNUSED(id); + UNUSED(force); + UNUSED(arg); debug("stdio forwarding: done"); cleanup_exit(0); } @@ -1883,6 +2007,9 @@ static void ssh_stdio_confirm(struct ssh *ssh, int id, int success, void *arg) { + UNUSED(ssh); + UNUSED(id); + UNUSED(arg); if (!success) fatal("stdio forwarding failed"); } @@ -1890,6 +2017,8 @@ static void ssh_tun_confirm(struct ssh *ssh, int id, int success, void *arg) { + UNUSED(ssh); + UNUSED(arg); if (!success) { error("Tunnel forwarding failed"); if (options.exit_on_forward_failure) @@ -1969,8 +2098,8 @@ options.permitted_remote_opens, options.num_permitted_remote_opens); - if (options.exit_on_forward_failure) - forward_confirms_pending = 0; /* track pending requests */ + forward_confirms_pending = 0; /* track pending requests */ + /* Initiate local TCP/IP port forwardings. */ for (i = 0; i < options.num_local_forwards; i++) { debug("Local connections to %.200s:%d forwarded to remote " @@ -2006,34 +2135,40 @@ options.remote_forwards[i].connect_path : options.remote_forwards[i].connect_host, options.remote_forwards[i].connect_port); - if ((options.remote_forwards[i].handle = + options.remote_forwards[i].handle = channel_request_remote_forwarding(ssh, - &options.remote_forwards[i])) >= 0) { + &options.remote_forwards[i]); + if (options.remote_forwards[i].handle < 0) { + if (options.exit_on_forward_failure) + fatal("Could not request remote forwarding."); + else + logit("Warning: Could not request remote " + "forwarding."); + } else { client_register_global_confirm( ssh_confirm_remote_forward, &options.remote_forwards[i]); forward_confirms_pending++; - } else if (options.exit_on_forward_failure) - fatal("Could not request remote forwarding."); - else - logit("Warning: Could not request remote forwarding."); + } } /* Initiate tunnel forwarding. */ if (options.tun_open != SSH_TUNMODE_NO) { if ((*ifname = client_request_tun_fwd(ssh, options.tun_open, options.tun_local, - options.tun_remote, ssh_tun_confirm, NULL)) != NULL) + options.tun_remote, ssh_tun_confirm, NULL)) == NULL) { + if (options.exit_on_forward_failure) + fatal("Could not request tunnel forwarding."); + else + error("Could not request tunnel forwarding."); + } else forward_confirms_pending++; - else if (options.exit_on_forward_failure) - fatal("Could not request tunnel forwarding."); - else - error("Could not request tunnel forwarding."); } if (forward_confirms_pending > 0) { debug_f("expecting replies for %d forwards", forward_confirms_pending); - } + } else + forward_confirms_pending = -1; } static void @@ -2059,6 +2194,7 @@ int r, interactive = tty_flag; char *proto = NULL, *data = NULL; + UNUSED(arg); if (!success) return; /* No need for error message, channels code sends one */ @@ -2091,7 +2227,7 @@ options.ip_qos_interactive, options.ip_qos_bulk); if ((term = lookup_env_in_list("TERM", options.setenv, - options.num_setenv)) == NULL || *term == '\0') + options.num_setenv)) == NULL) term = getenv("TERM"); client_session2_setup(ssh, id, tty_flag, options.session_type == SESSION_TYPE_SUBSYSTEM, term, @@ -2127,7 +2263,7 @@ window, packetmax, CHAN_EXTENDED_WRITE, "client-session", CHANNEL_NONBLOCK_STDIO); - debug3_f("channel_new: %d", c->self); + debug2_f("channel %d", c->self); channel_send_open(ssh, c->self); if (options.session_type != SESSION_TYPE_NONE) @@ -2174,6 +2310,9 @@ * async rfwd replies have been received for ExitOnForwardFailure). */ if (options.control_persist && muxserver_sock != -1) { + if ((options.session_type != SESSION_TYPE_NONE || + options.stdio_forward_host != NULL)) + need_controlpersist_detach = 1; ostdin_null_flag = options.stdin_null; osession_type = options.session_type; orequest_tty = options.request_tty; @@ -2182,9 +2321,6 @@ options.stdin_null = 1; options.session_type = SESSION_TYPE_NONE; tty_flag = 0; - if ((osession_type != SESSION_TYPE_NONE || - options.stdio_forward_host != NULL)) - need_controlpersist_detach = 1; options.fork_after_authentication = 1; } /* @@ -2204,7 +2340,7 @@ /* If we don't expect to open a new session, then disallow it */ if (options.control_master == SSHCTL_MASTER_NO && - (ssh->compat & SSH_NEW_OPENSSH)) { + ssh_compat_fellows(ssh, SSH_NEW_OPENSSH)) { debug("Requesting no-more-sessions@openssh.com"); if ((r = sshpkt_start(ssh, SSH2_MSG_GLOBAL_REQUEST)) != 0 || (r = sshpkt_put_cstring(ssh, @@ -2225,7 +2361,7 @@ * NB. this can only happen after LocalCommand has completed, * as it may want to write to stdout. */ - if (!need_controlpersist_detach && stdfd_devnull(0, 1, 0) == -1) + if (stdfd_devnull(0, !need_controlpersist_detach, 0) == -1) error_f("stdfd_devnull failed"); /* @@ -2233,8 +2369,7 @@ * forwarding requests, then let ssh continue in the background. */ if (options.fork_after_authentication) { - if (options.exit_on_forward_failure && - options.num_remote_forwards > 0) { + if (forward_confirms_pending > 0) { debug("deferring postauth fork until remote forward " "confirmation received"); } else @@ -2259,11 +2394,6 @@ char *certificate_files[SSH_MAX_CERTIFICATE_FILES]; struct sshkey *certificates[SSH_MAX_CERTIFICATE_FILES]; int certificate_file_userprovided[SSH_MAX_CERTIFICATE_FILES]; -#ifdef ENABLE_PKCS11 - struct sshkey **keys = NULL; - char **comments = NULL; - int nkeys; -#endif /* PKCS11 */ n_ids = n_certs = 0; memset(identity_files, 0, sizeof(identity_files)); @@ -2276,6 +2406,11 @@ sizeof(certificate_file_userprovided)); #ifdef ENABLE_PKCS11 +{ + struct sshkey **keys; + char **comments; + int nkeys; + if (options.pkcs11_provider != NULL && options.num_identity_files < SSH_MAX_IDENTITY_FILES && (pkcs11_init(!options.batch_mode) == 0) && @@ -2287,6 +2422,7 @@ free(comments[i]); continue; } + x509key_build_chain(keys[i]); identity_keys[n_ids] = keys[i]; identity_files[n_ids] = comments[i]; /* transferred */ n_ids++; @@ -2294,6 +2430,7 @@ free(keys); free(comments); } +} #endif /* ENABLE_PKCS11 */ for (i = 0; i < options.num_identity_files; i++) { if (n_ids >= SSH_MAX_IDENTITY_FILES || @@ -2401,6 +2538,7 @@ pid_t pid; int status; + UNUSED(sig); while ((pid = waitpid(-1, &status, WNOHANG)) > 0 || (pid == -1 && errno == EINTR)) ; diff -ruN openssh-9.4p1/ssh_config openssh-9.4p1+x509-14.2.1/ssh_config --- openssh-9.4p1/ssh_config 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/ssh_config 2023-08-20 10:07:00.000000000 +0300 @@ -37,6 +37,17 @@ # Ciphers aes128-ctr,aes192-ctr,aes256-ctr,aes128-cbc,3des-cbc # MACs hmac-md5,hmac-sha1,umac-64@openssh.com # EscapeChar ~ +# AllowedCertPurpose sslserver +# MandatoryCRL no +# CACertificateFile /etc/ssh/ca/ca-bundle.crt +# CACertificatePath /etc/ssh/ca/crt +# CARevocationFile /etc/ssh/ca/ca-bundle.crl +# CARevocationPath /etc/ssh/ca/crl +# UserCACertificateFile ~/.ssh/ca-bundle.crt +# UserCACertificatePath ~/.ssh/crt +# UserCARevocationFile ~/.ssh/ca-bundle.crl +# UserCARevocationPath ~/.ssh/crl +# VAType none # Tunnel no # TunnelDevice any:any # PermitLocalCommand no diff -ruN openssh-9.4p1/ssh_config.0 openssh-9.4p1+x509-14.2.1/ssh_config.0 --- openssh-9.4p1/ssh_config.0 2023-08-10 04:11:19.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/ssh_config.0 2023-08-20 10:07:00.000000000 +0300 @@ -1,11 +1,11 @@ -SSH_CONFIG(5) File Formats Manual SSH_CONFIG(5) +SSH_CONFIG(5) BSD File Formats Manual SSH_CONFIG(5) NAME - ssh_config M-bM-^@M-^S OpenSSH client configuration file + ssh_config -- Secure shell client configuration files DESCRIPTION - ssh(1) obtains configuration data from the following sources in the - following order: + ssh(1) obtains configuration data from the following sources in the fol- + lowing order: 1. command-line options 2. user's configuration file (~/.ssh/config) @@ -18,53 +18,53 @@ usually the one given on the command line (see the CanonicalizeHostname option for exceptions). - Since the first obtained value for each parameter is used, more host- - specific declarations should be given near the beginning of the file, and + Since the first obtained value for each parameter is used, more host-spe- + cific declarations should be given near the beginning of the file, and general defaults at the end. The file contains keyword-argument pairs, one per line. Lines starting - with M-bM-^@M-^X#M-bM-^@M-^Y and empty lines are interpreted as comments. Arguments may - optionally be enclosed in double quotes (") in order to represent - arguments containing spaces. Configuration options may be separated by - whitespace or optional whitespace and exactly one M-bM-^@M-^X=M-bM-^@M-^Y; the latter format - is useful to avoid the need to quote whitespace when specifying - configuration options using the ssh, scp, and sftp -o option. + with '#' and empty lines are interpreted as comments. Arguments may op- + tionally be enclosed in double quotes (") in order to represent arguments + containing spaces. Configuration options may be separated by whitespace + or optional whitespace and exactly one '='; the latter format is useful + to avoid the need to quote whitespace when specifying configuration op- + tions using the ssh, scp, and sftp -o option. - The possible keywords and their meanings are as follows (note that - keywords are case-insensitive and arguments are case-sensitive): + The possible keywords and their meanings are as follows (note that key- + words are case-insensitive and arguments are case-sensitive): Host Restricts the following declarations (up to the next Host or Match keyword) to be only for those hosts that match one of the patterns given after the keyword. If more than one pattern is - provided, they should be separated by whitespace. A single M-bM-^@M-^X*M-bM-^@M-^Y + provided, they should be separated by whitespace. A single '*' as a pattern can be used to provide global defaults for all hosts. The host is usually the hostname argument given on the - command line (see the CanonicalizeHostname keyword for - exceptions). + command line (see the CanonicalizeHostname keyword for excep- + tions). - A pattern entry may be negated by prefixing it with an - exclamation mark (M-bM-^@M-^X!M-bM-^@M-^Y). If a negated entry is matched, then the - Host entry is ignored, regardless of whether any other patterns - on the line match. Negated matches are therefore useful to - provide exceptions for wildcard matches. + A pattern entry may be negated by prefixing it with an exclama- + tion mark ('!'). If a negated entry is matched, then the Host + entry is ignored, regardless of whether any other patterns on the + line match. Negated matches are therefore useful to provide ex- + ceptions for wildcard matches. See PATTERNS for more information on patterns. Match Restricts the following declarations (up to the next Host or Match keyword) to be used only when the conditions following the - Match keyword are satisfied. Match conditions are specified - using one or more criteria or the single token all which always + Match keyword are satisfied. Match conditions are specified us- + ing one or more criteria or the single token all which always matches. The available criteria keywords are: canonical, final, exec, localnetwork, host, originalhost, Tag, user, and localuser. The all criteria must appear alone or immediately after canonical - or final. Other criteria may be combined arbitrarily. All - criteria but all, canonical, and final require an argument. - Criteria may be negated by prepending an exclamation mark (M-bM-^@M-^X!M-bM-^@M-^Y). + or final. Other criteria may be combined arbitrarily. All cri- + teria but all, canonical, and final require an argument. Crite- + ria may be negated by prepending an exclamation mark ('!'). The canonical keyword matches only when the configuration file is being re-parsed after hostname canonicalization (see the - CanonicalizeHostname option). This may be useful to specify - conditions that work with canonical host names only. + CanonicalizeHostname option). This may be useful to specify con- + ditions that work with canonical host names only. The final keyword requests that the configuration be re-parsed (regardless of whether CanonicalizeHostname is enabled), and @@ -72,32 +72,32 @@ enabled, then canonical and final match during the same pass. The exec keyword executes the specified command under the user's - shell. If the command returns a zero exit status then the - condition is considered true. Commands containing whitespace - characters must be quoted. Arguments to exec accept the tokens - described in the TOKENS section. + shell. If the command returns a zero exit status then the condi- + tion is considered true. Commands containing whitespace charac- + ters must be quoted. Arguments to exec accept the tokens de- + scribed in the TOKENS section. The localnetwork keyword matches the addresses of active local network interfaces against the supplied list of networks in CIDR - format. This may be convenient for varying the effective - configuration on devices that roam between networks. Note that - network address is not a trustworthy criteria in many situations - (e.g. when the network is automatically configured using DHCP) - and so caution should be applied if using it to control security- - sensitive configuration. - - The other keywords' criteria must be single entries or comma- - separated lists and may use the wildcard and negation operators - described in the PATTERNS section. The criteria for the host - keyword are matched against the target hostname, after any - substitution by the Hostname or CanonicalizeHostname options. - The originalhost keyword matches against the hostname as it was - specified on the command-line. The tagged keyword matches a tag - name specified by a prior Tag directive or on the ssh(1) command- - line using the -P flag. The user keyword matches against the - target username on the remote host. The localuser keyword - matches against the name of the local user running ssh(1) (this - keyword may be useful in system-wide ssh_config files). + format. This may be convenient for varying the effective config- + uration on devices that roam between networks. Note that network + address is not a trustworthy criteria in many situations (e.g. + when the network is automatically configured using DHCP) and so + caution should be applied if using it to control security-sensi- + tive configuration. + + The other keywords' criteria must be single entries or comma-sep- + arated lists and may use the wildcard and negation operators de- + scribed in the PATTERNS section. The criteria for the host key- + word are matched against the target hostname, after any substitu- + tion by the Hostname or CanonicalizeHostname options. The + originalhost keyword matches against the hostname as it was spec- + ified on the command-line. The tagged keyword matches a tag name + specified by a prior Tag directive or on the ssh(1) command-line + using the -P flag. The user keyword matches against the target + username on the remote host. The localuser keyword matches + against the name of the local user running ssh(1) (this keyword + may be useful in system-wide ssh_config files). AddKeysToAgent Specifies whether keys should be automatically added to a running @@ -105,7 +105,7 @@ from a file, the key and its passphrase are added to the agent with the default lifetime, as if by ssh-add(1). If this option is set to ask, ssh(1) will require confirmation using the - SSH_ASKPASS program before adding a key (see ssh-add(1) for + ssh-askpass(1) program before adding a key (see ssh-add(1) for details). If this option is set to confirm, each use of the key must be confirmed, as if the -c option was specified to ssh-add(1). If this option is set to no, no keys are added to @@ -114,39 +114,88 @@ of sshd_config(5) to specify the key's lifetime in ssh-agent(1), after which it will automatically be removed. The argument must be no (the default), yes, confirm (optionally followed by a time - interval), ask or a time interval. + interval), ask, or a time interval. AddressFamily - Specifies which address family to use when connecting. Valid - arguments are any (the default), inet (use IPv4 only), or inet6 + Specifies which address family to use when connecting. Valid ar- + guments are any (the default), inet (use IPv4 only), or inet6 (use IPv6 only). + AllowedCertPurpose + The intended use for the X.509 server certificate. Without this + option no chain verification will be done. Currently accepted + uses are case insensitive: + sslserver | SSL server | SSL_server | server + only SSL-server purpose + any | Any Purpose | Any_Purpose | AnyPurpose + allow any purpose + skip | '' (empty) + do not check purpose + The default is sslserver. + BatchMode If set to yes, user interaction such as password prompts and host - key confirmation requests will be disabled. This option is - useful in scripts and other batch jobs where no user is present - to interact with ssh(1). The argument must be yes or no (the - default). + key confirmation requests will be disabled. This option is use- + ful in scripts and other batch jobs where no user is present to + interact with ssh(1). The argument must be yes or no (the de- + fault). BindAddress - Use the specified address on the local machine as the source - address of the connection. Only useful on systems with more than + Use the specified address on the local machine as the source ad- + dress of the connection. Only useful on systems with more than one address. BindInterface Use the address of the specified interface on the local machine as the source address of the connection. + CACertificateFile + "X509 store" option: This file contain multiple certificates of + certificate signers in PEM format concatenated together. The de- + fault is /etc/ssh/ca/ca-bundle.crt. + + CACertificatePath + "X509 store" option: "Hash dir" with certificates of certificate + signers. Each certificate should be stored in separate file with + name [HASH].[NUMBER], where [HASH] is certificate hash value and + [NUMBER] is an integer starting from zero. The default is + /etc/ssh/ca/crt. + + CAldapVersion + "X509 store" option: Specifies LDAP protocol version. The de- + fault depend from LDAP library. + + CAldapURL + "X509 store" option: Specifies hostport and dn of LDAP URLs (Uni- + form Resource Locators) as detailed in RFC 2255. The rest of URL + is build internally. Because of options parser limitation use + '%3D' instead of '=' ! LDAP initialization method may require + URL to be escaped, i.e. use '%2C' instead of ',' (comma). Es- + caped URL don't depend from LDAP initialization method. + + CARevocationFile + "X509 store" option: This file contain multiple "Certificate + Revocation List" (CRL) of certificate signers in PEM format con- + catenated together. The default is /etc/ssh/ca/ca-bundle.crl. + + CARevocationPath + "X509 store" option: "Hash dir" with "Certificate Revocation + List" (CRL) of certificate signers. Each CRL should be stored in + separate file with name [HASH].r[NUMBER], where [HASH] is CRL + hash value and [NUMBER] is an integer starting from zero. The de- + fault is /etc/ssh/ca/crl. + CanonicalDomains When CanonicalizeHostname is enabled, this option specifies the - list of domain suffixes in which to search for the specified - destination host. + list of domain suffixes in which to search for the specified des- + tination host. The default value of none ignores any domain suf- + fixes. CanonicalizeFallbackLocal - Specifies whether to fail with an error when hostname - canonicalization fails. The default, yes, will attempt to look - up the unqualified hostname using the system resolver's search - rules. A value of no will cause ssh(1) to fail instantly if + Specifies whether to fail with an error when hostname canonical- + ization fails. The default, yes, will attempt to look up the un- + qualified hostname using the system resolver's search rules. A + value of no will cause ssh(1) to fail instantly if CanonicalizeHostname is enabled and the target hostname cannot be found in any of the domains specified by CanonicalDomains. @@ -158,18 +207,18 @@ ssh(1) will attempt to canonicalize the hostname specified on the command line using the CanonicalDomains suffixes and CanonicalizePermittedCNAMEs rules. If CanonicalizeHostname is - set to always, then canonicalization is applied to proxied - connections too. + set to always, then canonicalization is applied to proxied con- + nections too. - If this option is enabled, then the configuration files are - processed again using the new target name to pick up any new - configuration in matching Host and Match stanzas. A value of - none disables the use of a ProxyJump host. + If this option is enabled, then the configuration files are pro- + cessed again using the new target name to pick up any new config- + uration in matching Host and Match stanzas. A value of none dis- + ables the use of a ProxyJump host. CanonicalizeMaxDots - Specifies the maximum number of dot characters in a hostname - before canonicalization is disabled. The default, 1, allows a - single dot (i.e. hostname.subdomain). + Specifies the maximum number of dot characters in a hostname be- + fore canonicalization is disabled. The default, 1, allows a sin- + gle dot (i.e. hostname.subdomain). CanonicalizePermittedCNAMEs Specifies rules to determine whether CNAMEs should be followed @@ -180,66 +229,66 @@ list of domains that they may resolve to. For example, "*.a.example.com:*.b.example.com,*.c.example.com" - will allow hostnames matching "*.a.example.com" to be - canonicalized to names in the "*.b.example.com" or - "*.c.example.com" domains. + will allow hostnames matching "*.a.example.com" to be canonical- + ized to names in the "*.b.example.com" or "*.c.example.com" do- + mains. A single argument of "none" causes no CNAMEs to be considered for canonicalization. This is the default behaviour. CASignatureAlgorithms - Specifies which algorithms are allowed for signing of - certificates by certificate authorities (CAs). The default is: - - ssh-ed25519,ecdsa-sha2-nistp256, - ecdsa-sha2-nistp384,ecdsa-sha2-nistp521, - sk-ssh-ed25519@openssh.com, - sk-ecdsa-sha2-nistp256@openssh.com, - rsa-sha2-512,rsa-sha2-256 - - If the specified list begins with a M-bM-^@M-^X+M-bM-^@M-^Y character, then the - specified algorithms will be appended to the default set instead - of replacing them. If the specified list begins with a M-bM-^@M-^X-M-bM-^@M-^Y - character, then the specified algorithms (including wildcards) - will be removed from the default set instead of replacing them. + Specifies which algorithms are allowed for signing of custom cer- + tificates by custom certificate authorities (CAs). The default + is: + + ssh-ed25519, + ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521, + rsa-sha2-512,rsa-sha2-256,ssh-rsa + + If the specified list begins with a '+' character, then the spec- + ified algorithms will be appended to the default set instead of + replacing them. If the specified list begins with a '-' charac- + ter, then the specified algorithms (including wildcards) will be + removed from the default set instead of replacing them. - ssh(1) will not accept host certificates signed using algorithms - other than those specified. + ssh(1) will not accept custom host certificates signed using al- + gorithms other than those specified. CertificateFile - Specifies a file from which the user's certificate is read. A - corresponding private key must be provided separately in order to - use this certificate either from an IdentityFile directive or -i - flag to ssh(1), via ssh-agent(1), or via a PKCS11Provider or - SecurityKeyProvider. + Specifies a file from which the user's OpenSSH custom certificate + is read. A corresponding private key must be provided separately + in order to use this OpenSSH custom certificate either from an + IdentityFile directive or -i flag to ssh(1), via ssh-agent(1), or + via a PKCS11Provider. Arguments to CertificateFile may use the tilde syntax to refer to - a user's home directory, the tokens described in the TOKENS - section and environment variables as described in the ENVIRONMENT + a user's home directory, the tokens described in the TOKENS sec- + tion and environment variables as described in the ENVIRONMENT VARIABLES section. It is possible to have multiple certificate files specified in - configuration files; these certificates will be tried in - sequence. Multiple CertificateFile directives will add to the - list of certificates used for authentication. + configuration files; these OpenSSH custom certificates will be + tried in sequence. Multiple CertificateFile directives will add + to the list of OpenSSH custom certificates used for authentica- + tion. CheckHostIP If set to yes, ssh(1) will additionally check the host IP address - in the known_hosts file. This allows it to detect if a host key + in the known hosts files. This allows it to detect if a host key changed due to DNS spoofing and will add addresses of destination - hosts to ~/.ssh/known_hosts in the process, regardless of the - setting of StrictHostKeyChecking. If the option is set to no + hosts to user known hosts files, in the process, regardless of + the setting of StrictHostKeyChecking. If the option is set to no (the default), the check will not be executed. Ciphers Specifies the ciphers allowed and their order of preference. Multiple ciphers must be comma-separated. If the specified list - begins with a M-bM-^@M-^X+M-bM-^@M-^Y character, then the specified ciphers will be + begins with a '+' character, then the specified ciphers will be appended to the default set instead of replacing them. If the - specified list begins with a M-bM-^@M-^X-M-bM-^@M-^Y character, then the specified + specified list begins with a '-' character, then the specified ciphers (including wildcards) will be removed from the default set instead of replacing them. If the specified list begins with - a M-bM-^@M-^X^M-bM-^@M-^Y character, then the specified ciphers will be placed at the + a '^' character, then the specified ciphers will be placed at the head of the default set. The supported ciphers are: @@ -268,25 +317,25 @@ Specifies that all local, remote, and dynamic port forwardings specified in the configuration files or on the command line be cleared. This option is primarily useful when used from the - ssh(1) command line to clear port forwardings set in - configuration files, and is automatically set by scp(1) and - sftp(1). The argument must be yes or no (the default). + ssh(1) command line to clear port forwardings set in configura- + tion files, and is automatically set by scp(1) and sftp(1). The + argument must be yes or no (the default). Compression Specifies whether to use compression. The argument must be yes or no (the default). ConnectionAttempts - Specifies the number of tries (one per second) to make before - exiting. The argument must be an integer. This may be useful in + Specifies the number of tries (one per second) to make before ex- + iting. The argument must be an integer. This may be useful in scripts if the connection sometimes fails. The default is 1. ConnectTimeout Specifies the timeout (in seconds) used when connecting to the SSH server, instead of using the default system TCP timeout. This timeout is applied both to establishing the connection and - to performing the initial SSH protocol handshake and key - exchange. + to performing the initial SSH protocol handshake and key ex- + change. ControlMaster Enables the sharing of multiple sessions over a single network @@ -294,20 +343,20 @@ on a control socket specified using the ControlPath argument. Additional sessions can connect to this socket using the same ControlPath with ControlMaster set to no (the default). These - sessions will try to reuse the master instance's network - connection rather than initiating new ones, but will fall back to - connecting normally if the control socket does not exist, or is - not listening. - - Setting this to ask will cause ssh(1) to listen for control - connections, but require confirmation using ssh-askpass(1). If - the ControlPath cannot be opened, ssh(1) will continue without - connecting to a master instance. - - X11 and ssh-agent(1) forwarding is supported over these - multiplexed connections, however the display and agent forwarded - will be the one belonging to the master connection i.e. it is not - possible to forward multiple displays or agents. + sessions will try to reuse the master instance's network connec- + tion rather than initiating new ones, but will fall back to con- + necting normally if the control socket does not exist, or is not + listening. + + Setting this to ask will cause ssh(1) to listen for control con- + nections, but require confirmation using ssh-askpass(1). If the + ControlPath cannot be opened, ssh(1) will continue without con- + necting to a master instance. + + X11 and ssh-agent(1) forwarding is supported over these multi- + plexed connections, however the display and agent forwarded will + be the one belonging to the master connection i.e. it is not pos- + sible to forward multiple displays or agents. Two additional options allow for opportunistic multiplexing: try to use a master connection but fall back to creating a new one if @@ -315,32 +364,31 @@ The latter requires confirmation like the ask option. ControlPath - Specify the path to the control socket used for connection - sharing as described in the ControlMaster section above or the - string none to disable connection sharing. Arguments to - ControlPath may use the tilde syntax to refer to a user's home - directory, the tokens described in the TOKENS section and - environment variables as described in the ENVIRONMENT VARIABLES - section. It is recommended that any ControlPath used for - opportunistic connection sharing include at least %h, %p, and %r - (or alternatively %C) and be placed in a directory that is not - writable by other users. This ensures that shared connections - are uniquely identified. + Specify the path to the control socket used for connection shar- + ing as described in the ControlMaster section above or the string + none to disable connection sharing. Arguments to ControlPath may + use the tilde syntax to refer to a user's home directory, the to- + kens described in the TOKENS section and environment variables as + described in the ENVIRONMENT VARIABLES section. It is recom- + mended that any ControlPath used for opportunistic connection + sharing include at least %h, %p, and %r (or alternatively %C) and + be placed in a directory that is not writable by other users. + This ensures that shared connections are uniquely identified. ControlPersist When used in conjunction with ControlMaster, specifies that the master connection should remain open in the background (waiting - for future client connections) after the initial client - connection has been closed. If set to no (the default), then the - master connection will not be placed into the background, and - will close as soon as the initial client connection is closed. - If set to yes or 0, then the master connection will remain in the - background indefinitely (until killed or closed via a mechanism - such as the "ssh -O exit"). If set to a time in seconds, or a - time in any of the formats documented in sshd_config(5), then the - backgrounded master connection will automatically terminate after - it has remained idle (with no client connections) for the - specified time. + for future client connections) after the initial client connec- + tion has been closed. If set to no (the default), then the mas- + ter connection will not be placed into the background, and will + close as soon as the initial client connection is closed. If set + to yes or 0, then the master connection will remain in the back- + ground indefinitely (until killed or closed via a mechanism such + as the "ssh -O exit"). If set to a time in seconds, or a time in + any of the formats documented in sshd_config(5), then the back- + grounded master connection will automatically terminate after it + has remained idle (with no client connections) for the specified + time. DynamicForward Specifies that a TCP port on the local machine be forwarded over @@ -349,12 +397,12 @@ The argument must be [bind_address:]port. IPv6 addresses can be specified by enclosing addresses in square brackets. By default, - the local port is bound in accordance with the GatewayPorts - setting. However, an explicit bind_address may be used to bind - the connection to a specific address. The bind_address of - localhost indicates that the listening port be bound for local - use only, while an empty address or M-bM-^@M-^X*M-bM-^@M-^Y indicates that the port - should be available from all interfaces. + the local port is bound in accordance with the GatewayPorts set- + ting. However, an explicit bind_address may be used to bind the + connection to a specific address. The bind_address of localhost + indicates that the listening port be bound for local use only, + while an empty address or '*' indicates that the port should be + available from all interfaces. Currently the SOCKS4 and SOCKS5 protocols are supported, and ssh(1) will act as a SOCKS server. Multiple forwardings may be @@ -362,62 +410,63 @@ line. Only the superuser can forward privileged ports. EnableEscapeCommandline - Enables the command line option in the EscapeChar menu for - interactive sessions (default M-bM-^@M-^X~CM-bM-^@M-^Y). By default, the command - line is disabled. + Enables the command line option in the EscapeChar menu for inter- + active sessions (default '~C'). By default, the command line is + enabled unless system support pledge(2). EnableSSHKeysign Setting this option to yes in the global client configuration file /etc/ssh/ssh_config enables the use of the helper program ssh-keysign(8) during HostbasedAuthentication. The argument must be yes or no (the default). This option should be placed in the - non-hostspecific section. See ssh-keysign(8) for more - information. + non-hostspecific section. See ssh-keysign(8) for more informa- + tion. EscapeChar - Sets the escape character (default: M-bM-^@M-^X~M-bM-^@M-^Y). The escape character + Sets the escape character (default: '~'). The escape character can also be set on the command line. The argument should be a - single character, M-bM-^@M-^X^M-bM-^@M-^Y followed by a letter, or none to disable + single character, '^' followed by a letter, or none to disable the escape character entirely (making the connection transparent for binary data). ExitOnForwardFailure Specifies whether ssh(1) should terminate the connection if it cannot set up all requested dynamic, tunnel, local, and remote - port forwardings, (e.g. if either end is unable to bind and - listen on a specified port). Note that ExitOnForwardFailure does + port forwardings, (e.g. if either end is unable to bind and lis- + ten on a specified port). Note that ExitOnForwardFailure does not apply to connections made over port forwardings and will not, - for example, cause ssh(1) to exit if TCP connections to the - ultimate forwarding destination fail. The argument must be yes - or no (the default). + for example, cause ssh(1) to exit if TCP connections to the ulti- + mate forwarding destination fail. The argument must be yes or no + (the default). FingerprintHash - Specifies the hash algorithm used when displaying key - fingerprints. Valid options are: md5 and sha256 (the default). + Specifies the hash algorithm used when displaying key finger- + prints. Valid options are: md5 and sha256 (the default). ForkAfterAuthentication Requests ssh to go to background just before command execution. This is useful if ssh is going to ask for passwords or - passphrases, but the user wants it in the background. This - implies the StdinNull configuration option being set to M-bM-^@M-^\yesM-bM-^@M-^]. - The recommended way to start X11 programs at a remote site is - with something like ssh -f host xterm, which is the same as ssh - host xterm if the ForkAfterAuthentication configuration option is - set to M-bM-^@M-^\yesM-bM-^@M-^]. - - If the ExitOnForwardFailure configuration option is set to M-bM-^@M-^\yesM-bM-^@M-^], - then a client started with the ForkAfterAuthentication - configuration option being set to M-bM-^@M-^\yesM-bM-^@M-^] will wait for all remote - port forwards to be successfully established before placing - itself in the background. The argument to this keyword must be - yes (same as the -f option) or no (the default). + passphrases, but the user wants it in the background. This im- + plies the StdinNull configuration option being set to "yes". The + recommended way to start X11 programs at a remote site is with + something like ssh -f host xterm, which is the same as ssh host + xterm if the ForkAfterAuthentication configuration option is set + to "yes". + + If the ExitOnForwardFailure configuration option is set to "yes", + then a client started with the ForkAfterAuthentication configura- + tion option being set to "yes" will wait for all remote port for- + wards to be successfully established before placing itself in the + background. The argument to this keyword must be yes (same as + the -f option) or no (the default). ForwardAgent Specifies whether the connection to the authentication agent (if any) will be forwarded to the remote machine. The argument may be yes, no (the default), an explicit path to an agent socket or - the name of an environment variable (beginning with M-bM-^@M-^X$M-bM-^@M-^Y) in which - to find the path. + the name of an environment variable (beginning with '$') in which + to find the path. Arguments to ForwardAgent with explicit path + accept the tokens described in the TOKENS section. Agent forwarding should be enabled with caution. Users with the ability to bypass file permissions on the remote host (for the @@ -428,15 +477,15 @@ the agent. ForwardX11 - Specifies whether X11 connections will be automatically - redirected over the secure channel and DISPLAY set. The argument + Specifies whether X11 connections will be automatically redi- + rected over the secure channel and DISPLAY set. The argument must be yes or no (the default). X11 forwarding should be enabled with caution. Users with the ability to bypass file permissions on the remote host (for the - user's X11 authorization database) can access the local X11 - display through the forwarded connection. An attacker may then - be able to perform activities such as keystroke monitoring if the + user's X11 authorization database) can access the local X11 dis- + play through the forwarded connection. An attacker may then be + able to perform activities such as keystroke monitoring if the ForwardX11Trusted option is also enabled. ForwardX11Timeout @@ -444,20 +493,20 @@ described in the TIME FORMATS section of sshd_config(5). X11 connections received by ssh(1) after this time will be refused. Setting ForwardX11Timeout to zero will disable the timeout and - permit X11 forwarding for the life of the connection. The - default is to disable untrusted X11 forwarding after twenty - minutes has elapsed. + permit X11 forwarding for the life of the connection. The de- + fault is to disable untrusted X11 forwarding after twenty minutes + has elapsed. ForwardX11Trusted If this option is set to yes, remote X11 clients will have full access to the original X11 display. If this option is set to no (the default), remote X11 clients - will be considered untrusted and prevented from stealing or - tampering with data belonging to trusted X11 clients. - Furthermore, the xauth(1) token used for the session will be set - to expire after 20 minutes. Remote clients will be refused - access after this time. + will be considered untrusted and prevented from stealing or tam- + pering with data belonging to trusted X11 clients. Furthermore, + the xauth(1) token used for the session will be set to expire af- + ter 20 minutes. Remote clients will be refused access after this + time. See the X11 SECURITY extension specification for full details on the restrictions imposed on untrusted clients. @@ -466,15 +515,16 @@ Specifies whether remote hosts are allowed to connect to local forwarded ports. By default, ssh(1) binds local port forwardings to the loopback address. This prevents other remote hosts from - connecting to forwarded ports. GatewayPorts can be used to - specify that ssh should bind local port forwardings to the - wildcard address, thus allowing remote hosts to connect to - forwarded ports. The argument must be yes or no (the default). + connecting to forwarded ports. GatewayPorts can be used to spec- + ify that ssh should bind local port forwardings to the wildcard + address, thus allowing remote hosts to connect to forwarded + ports. The argument must be yes or no (the default). GlobalKnownHostsFile - Specifies one or more files to use for the global host key - database, separated by whitespace. The default is - /etc/ssh/ssh_known_hosts, /etc/ssh/ssh_known_hosts2. + Specifies one or more files to use for the global host key data- + base, separated by whitespace. The default is + /etc/ssh/ssh_known_hosts, /etc/ssh/ssh_known_hosts2. Setting the + value to none disables the use of global host key database. GSSAPIAuthentication Specifies whether user authentication based on GSSAPI is allowed. @@ -485,117 +535,100 @@ HashKnownHosts Indicates that ssh(1) should hash host names and addresses when - they are added to ~/.ssh/known_hosts. These hashed names may be - used normally by ssh(1) and sshd(8), but they do not visually - reveal identifying information if the file's contents are - disclosed. The default is no. Note that existing names and - addresses in known hosts files will not be converted - automatically, but may be manually hashed using ssh-keygen(1). + they are added to the first user known hosts file. These hashed + names may be used normally by ssh(1) and sshd(8), but they do not + visually reveal identifying information if the file's contents + are disclosed. The default is no. Note that existing names and + addresses in known hosts files will not be converted automati- + cally, but may be manually hashed using ssh-keygen(1). HostbasedAcceptedAlgorithms - Specifies the signature algorithms that will be used for - hostbased authentication as a comma-separated list of patterns. - Alternately if the specified list begins with a M-bM-^@M-^X+M-bM-^@M-^Y character, - then the specified signature algorithms will be appended to the - default set instead of replacing them. If the specified list - begins with a M-bM-^@M-^X-M-bM-^@M-^Y character, then the specified signature - algorithms (including wildcards) will be removed from the default - set instead of replacing them. If the specified list begins with - a M-bM-^@M-^X^M-bM-^@M-^Y character, then the specified signature algorithms will be - placed at the head of the default set. The default for this - option is: + Option compatibility. See HostbasedAlgorithms - ssh-ed25519-cert-v01@openssh.com, - ecdsa-sha2-nistp256-cert-v01@openssh.com, - ecdsa-sha2-nistp384-cert-v01@openssh.com, - ecdsa-sha2-nistp521-cert-v01@openssh.com, - sk-ssh-ed25519-cert-v01@openssh.com, - sk-ecdsa-sha2-nistp256-cert-v01@openssh.com, - rsa-sha2-512-cert-v01@openssh.com, - rsa-sha2-256-cert-v01@openssh.com, - ssh-ed25519, - ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521, - sk-ssh-ed25519@openssh.com, - sk-ecdsa-sha2-nistp256@openssh.com, - rsa-sha2-512,rsa-sha2-256 - - The -Q option of ssh(1) may be used to list supported signature - algorithms. This was formerly named HostbasedKeyTypes. + HostbasedAlgorithms + Specifies the publickey algorithms that will be used in hostbased + authentication as a comma-separated pattern list. See PATTERNS + for more information on patterns. The default * allows all algo- + rithms. Note algorithms that use X.509 certificates depend from + option X509KeyAlgorithm. The list of supported algorithms may + also be obtained using "ssh -Q key". HostbasedAuthentication Specifies whether to try rhosts based authentication with public - key authentication. The argument must be yes or no (the - default). + key authentication. The argument must be yes or no (the de- + fault). + + HostbasedKeyTypes + Option compatibility. See HostbasedAlgorithms HostKeyAlgorithms - Specifies the host key signature algorithms that the client wants - to use in order of preference. Alternately if the specified list - begins with a M-bM-^@M-^X+M-bM-^@M-^Y character, then the specified signature - algorithms will be appended to the default set instead of - replacing them. If the specified list begins with a M-bM-^@M-^X-M-bM-^@M-^Y - character, then the specified signature algorithms (including - wildcards) will be removed from the default set instead of - replacing them. If the specified list begins with a M-bM-^@M-^X^M-bM-^@M-^Y - character, then the specified signature algorithms will be placed - at the head of the default set. The default for this option is: + Specifies the host key algorithms that the client wants to use in + order of preference. Alternately if the specified list begins + with a '+' character, then the specified key algorithms will be + appended to the default set instead of replacing them. If the + specified list begins with a '-' character, then the specified + key algorithms (including wildcards) will be removed from the de- + fault set instead of replacing them. If the specified list be- + gins with a '^' character, then the specified key algorithms will + be placed at the head of the default set. The default for this + option depend from X509KeyAlgorithm. By default it contain + unique list build from names of X509KeyAlgorithm defined for + ECDSA, Ed25519, RSA and DSA keys, followed by ssh-ed25519-cert-v01@openssh.com, ecdsa-sha2-nistp256-cert-v01@openssh.com, ecdsa-sha2-nistp384-cert-v01@openssh.com, ecdsa-sha2-nistp521-cert-v01@openssh.com, - sk-ssh-ed25519-cert-v01@openssh.com, - sk-ecdsa-sha2-nistp256-cert-v01@openssh.com, - rsa-sha2-512-cert-v01@openssh.com, - rsa-sha2-256-cert-v01@openssh.com, + rsa-sha2-256-cert-v01@openssh.com,rsa-sha2-512-cert-v01@openssh.com, + ssh-rsa-cert-v01@openssh.com, ssh-ed25519, ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521, - sk-ecdsa-sha2-nistp256@openssh.com, - sk-ssh-ed25519@openssh.com, - rsa-sha2-512,rsa-sha2-256 + rsa-sha2-256,rsa-sha2-512,ssh-rsa, + ssh-dss - If hostkeys are known for the destination host then this default - is modified to prefer their algorithms. + If hostkeys are known for the destination host and specified list + does not begins a '^' then this default is modified to prefer + their algorithms. - The list of available signature algorithms may also be obtained - using "ssh -Q HostKeyAlgorithms". + The list of available key algorithms may also be obtained using + "ssh -Q key-alg". HostKeyAlias Specifies an alias that should be used instead of the real host - name when looking up or saving the host key in the host key - database files and when validating host certificates. This - option is useful for tunneling SSH connections or for multiple - servers running on a single host. + name when looking up or saving the host key in the host key data- + base files and when validating host certificates. This option is + useful for tunneling SSH connections or for multiple servers run- + ning on a single host. Hostname Specifies the real host name to log into. This can be used to specify nicknames or abbreviations for hosts. Arguments to - Hostname accept the tokens described in the TOKENS section. - Numeric IP addresses are also permitted (both on the command line + Hostname accept the tokens described in the TOKENS section. Nu- + meric IP addresses are also permitted (both on the command line and in Hostname specifications). The default is the name given on the command line. IdentitiesOnly - Specifies that ssh(1) should only use the configured - authentication identity and certificate files (either the default - files, or those explicitly configured in the ssh_config files or - passed on the ssh(1) command-line), even if ssh-agent(1) or a - PKCS11Provider or SecurityKeyProvider offers more identities. - The argument to this keyword must be yes or no (the default). - This option is intended for situations where ssh-agent offers - many different identities. + Specifies that ssh(1) should only use the configured authentica- + tion identity and certificate files (either the default files, or + those explicitly configured in the ssh_config files or passed on + the ssh(1) command-line), even if ssh-agent(1) or a + PKCS11Provider offers more identities. The argument to this key- + word must be yes or no (the default). This option is intended + for situations where ssh-agent offers many different identities. IdentityAgent - Specifies the UNIX-domain socket used to communicate with the - authentication agent. + Specifies the UNIX-domain socket used to communicate with the au- + thentication agent. This option overrides the SSH_AUTH_SOCK environment variable and can be used to select a specific agent. Setting the socket name to none disables the use of an authentication agent. If the string "SSH_AUTH_SOCK" is specified, the location of the socket - will be read from the SSH_AUTH_SOCK environment variable. - Otherwise if the specified value begins with a M-bM-^@M-^X$M-bM-^@M-^Y character, - then it will be treated as an environment variable containing the - location of the socket. + will be read from the SSH_AUTH_SOCK environment variable. Other- + wise if the specified value begins with a '$' character, then it + will be treated as an environment variable containing the loca- + tion of the socket. Arguments to IdentityAgent may use the tilde syntax to refer to a user's home directory, the tokens described in the TOKENS section @@ -603,48 +636,70 @@ VARIABLES section. IdentityFile - Specifies a file from which the user's DSA, ECDSA, authenticator- - hosted ECDSA, Ed25519, authenticator-hosted Ed25519 or RSA - authentication identity is read. You can also specify a public - key file to use the corresponding private key that is loaded in - ssh-agent(1) when the private key file is not present locally. - The default is ~/.ssh/id_rsa, ~/.ssh/id_ecdsa, - ~/.ssh/id_ecdsa_sk, ~/.ssh/id_ed25519, ~/.ssh/id_ed25519_sk and - ~/.ssh/id_dsa. Additionally, any identities represented by the - authentication agent will be used for authentication unless - IdentitiesOnly is set. If no certificates have been explicitly - specified by CertificateFile, ssh(1) will try to load certificate - information from the filename obtained by appending -cert.pub to - the path of a specified IdentityFile. + Specifies a file from which the user's RSA, ECDSA, Ed25519 or DSA + authentication identity is read. The default is ~/.ssh/id_rsa, + ~/.ssh/id_ecdsa, ~/.ssh/id_ed25519 and ~/.ssh/id_dsa. + + For RSA, ECDSA, Ed25519 or DSA identity file may contain X.509 + certificate that match key. In addition file may contain extra + X.509 certificates. Extra certificates along with certificates + from X.509 store are used to build chain of certificates leading + to a trusted certificate authority if required by public key al- + gorithm format. + + Additionally, any identities represented by the authentication + agent will be used for authentication unless IdentitiesOnly is + set. You can also specify a public key file to use the corre- + sponding private key that is loaded in authentication agent when + the private key file is not present locally. + + If no OpenSSH custom certificates have been explicitly specified + by CertificateFile, ssh(1) will try to load OpenSSH custom cer- + tificate information from the filename obtained by appending + -cert.pub to the path of a specified IdentityFile. Arguments to IdentityFile may use the tilde syntax to refer to a - user's home directory or the tokens described in the TOKENS - section. + user's home directory or the tokens described in the TOKENS sec- + tion. - It is possible to have multiple identity files specified in - configuration files; all these identities will be tried in - sequence. Multiple IdentityFile directives will add to the list - of identities tried (this behaviour differs from that of other - configuration directives). + If file name starts with prefix 'engine:' instead from file iden- + tity load is redirected to "loadable cryptographic module" (en- + gine). The name of "loadable cryptographic module" has to follow + prefix engine: and is terminated by colon separator. ssh(1) com- + mand line option -G could specify file with extra engine configu- + ration. Next argument has to specify reference to key as is rec- + ognizable by engine. + + Prefix "store:" could be used if cryptographic library supports + ossl_store(7) functionality. In such case after prefix has to be + specified URI referencing to content containing private key and + optionally X.509 certificates. Store content could be displayed + by command storeutl(1). + + It is possible to have multiple identity files specified in con- + figuration files; all these identities will be tried in sequence. + Multiple IdentityFile directives will add to the list of identi- + ties tried (this behaviour differs from that of other configura- + tion directives). IdentityFile may be used in conjunction with IdentitiesOnly to - select which identities in an agent are offered during - authentication. IdentityFile may also be used in conjunction - with CertificateFile in order to provide any certificate also - needed for authentication with the identity. + select which identities in an agent are offered during authenti- + cation. IdentityFile may also be used in conjunction with + CertificateFile in order to provide any OpenSSH custom certifi- + cate also needed for authentication with the identity. IgnoreUnknown Specifies a pattern-list of unknown options to be ignored if they are encountered in configuration parsing. This may be used to - suppress errors if ssh_config contains options that are - unrecognised by ssh(1). It is recommended that IgnoreUnknown be - listed early in the configuration file as it will not be applied - to unknown options that appear before it. + suppress errors if ssh_config contains options that are unrecog- + nised by ssh(1). It is recommended that IgnoreUnknown be listed + early in the configuration file as it will not be applied to un- + known options that appear before it. Include Include the specified configuration file(s). Multiple pathnames may be specified and each pathname may contain glob(7) wildcards - and, for user configurations, shell-like M-bM-^@M-^X~M-bM-^@M-^Y references to user + and, for user configurations, shell-like '~' references to user home directories. Wildcards will be expanded and processed in lexical order. Files without absolute paths are assumed to be in ~/.ssh if included in a user configuration file or /etc/ssh if @@ -657,13 +712,13 @@ af32, af33, af41, af42, af43, cs0, cs1, cs2, cs3, cs4, cs5, cs6, cs7, ef, le, lowdelay, throughput, reliability, a numeric value, or none to use the operating system default. This option may - take one or two arguments, separated by whitespace. If one - argument is specified, it is used as the packet class - unconditionally. If two values are specified, the first is - automatically selected for interactive sessions and the second - for non-interactive sessions. The default is af21 (Low-Latency - Data) for interactive sessions and cs1 (Lower Effort) for non- - interactive sessions. + take one or two arguments, separated by whitespace. If one argu- + ment is specified, it is used as the packet class uncondition- + ally. If two values are specified, the first is automatically + selected for interactive sessions and the second for non-interac- + tive sessions. The default is af21 (Low-Latency Data) for inter- + active sessions and cs1 (Lower Effort) for non-interactive ses- + sions. KbdInteractiveAuthentication Specifies whether to use keyboard-interactive authentication. @@ -671,71 +726,74 @@ ChallengeResponseAuthentication is a deprecated alias for this. KbdInteractiveDevices - Specifies the list of methods to use in keyboard-interactive - authentication. Multiple method names must be comma-separated. + Specifies the list of methods to use in keyboard-interactive au- + thentication. Multiple method names must be comma-separated. The default is to use the server specified list. The methods available vary depending on what the server supports. For an - OpenSSH server, it may be zero or more of: bsdauth and pam. + PKIX-SSH or OpenSSH server, it may be zero or more of: bsdauth + and pam. KexAlgorithms Specifies the available KEX (Key Exchange) algorithms. Multiple algorithms must be comma-separated. If the specified list begins - with a M-bM-^@M-^X+M-bM-^@M-^Y character, then the specified algorithms will be - appended to the default set instead of replacing them. If the - specified list begins with a M-bM-^@M-^X-M-bM-^@M-^Y character, then the specified + with a '+' character, then the specified algorithms will be ap- + pended to the default set instead of replacing them. If the + specified list begins with a '-' character, then the specified algorithms (including wildcards) will be removed from the default set instead of replacing them. If the specified list begins with - a M-bM-^@M-^X^M-bM-^@M-^Y character, then the specified algorithms will be placed at + a '^' character, then the specified algorithms will be placed at the head of the default set. The default is: - sntrup761x25519-sha512@openssh.com, curve25519-sha256,curve25519-sha256@libssh.org, ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521, diffie-hellman-group-exchange-sha256, diffie-hellman-group16-sha512, diffie-hellman-group18-sha512, - diffie-hellman-group14-sha256 + diffie-hellman-group14-sha256, + sntrup761x25519-sha512@openssh.com, + diffie-hellman-group14-sha1 + Note sntrup761x25519-sha512@openssh.com is used if is build. - The list of available key exchange algorithms may also be - obtained using "ssh -Q kex". + The list of available key exchange algorithms may also be ob- + tained using "ssh -Q kex". KnownHostsCommand - Specifies a command to use to obtain a list of host keys, in - addition to those listed in UserKnownHostsFile and + Specifies a command to use to obtain a list of host keys, in ad- + dition to those listed in UserKnownHostsFile and GlobalKnownHostsFile. This command is executed after the files have been read. It may write host key lines to standard output in identical format to the usual files (described in the VERIFYING HOST KEYS section in ssh(1)). Arguments to - KnownHostsCommand accept the tokens described in the TOKENS - section. The command may be invoked multiple times per - connection: once when preparing the preference list of host key - algorithms to use, again to obtain the host key for the requested - host name and, if CheckHostIP is enabled, one more time to obtain - the host key matching the server's address. If the command exits - abnormally or returns a non-zero exit status then the connection - is terminated. + KnownHostsCommand accept the tokens described in the TOKENS sec- + tion. The command may be invoked multiple times per connection: + once when preparing the preference list of host key algorithms to + use, again to obtain the host key for the requested host name + and, if CheckHostIP is enabled, one more time to obtain the host + key matching the server's address. If the command exits abnor- + mally or returns a non-zero exit status then the connection is + terminated. LocalCommand - Specifies a command to execute on the local machine after - successfully connecting to the server. The command string - extends to the end of the line, and is executed with the user's - shell. Arguments to LocalCommand accept the tokens described in - the TOKENS section. + Specifies a command to execute on the local machine after suc- + cessfully connecting to the server. The command string extends + to the end of the line, and is executed with the user's shell. + Arguments to LocalCommand accept the tokens described in the + TOKENS section. The command is run synchronously and does not have access to the session of the ssh(1) that spawned it. It should not be used for interactive commands. - This directive is ignored unless PermitLocalCommand has been - enabled. + This directive is ignored unless PermitLocalCommand has been en- + abled. LocalForward Specifies that a TCP port on the local machine be forwarded over the secure channel to the specified host and port from the remote machine. The first argument specifies the listener and may be - [bind_address:]port or a Unix domain socket path. The second - argument is the destination and may be host:hostport or a Unix - domain socket path if the remote host supports it. + [bind_address:]port or a Unix domain socket path. The second ar- + gument is the destination and may be host:hostport or a Unix do- + main socket path if the remote host supports it. IPv6 addresses can be specified by enclosing addresses in square brackets. Multiple forwardings may be specified, and additional @@ -745,45 +803,46 @@ explicit bind_address may be used to bind the connection to a specific address. The bind_address of localhost indicates that the listening port be bound for local use only, while an empty - address or M-bM-^@M-^X*M-bM-^@M-^Y indicates that the port should be available from - all interfaces. Unix domain socket paths may use the tokens - described in the TOKENS section and environment variables as - described in the ENVIRONMENT VARIABLES section. + address or '*' indicates that the port should be available from + all interfaces. + + Unix domain socket paths may use the tokens described in the + TOKENS section and environment variables as described in the + ENVIRONMENT VARIABLES section. LogLevel Gives the verbosity level that is used when logging messages from - ssh(1). The possible values are: QUIET, FATAL, ERROR, INFO, - VERBOSE, DEBUG, DEBUG1, DEBUG2, and DEBUG3. The default is INFO. + ssh(1). The possible values are: QUIET, FATAL, ERROR, INFO, VER- + BOSE, DEBUG, DEBUG1, DEBUG2, and DEBUG3. The default is INFO. DEBUG and DEBUG1 are equivalent. DEBUG2 and DEBUG3 each specify higher levels of verbose output. LogVerbose Specify one or more overrides to LogLevel. An override consists of a pattern lists that matches the source file, function and - line number to force detailed logging for. For example, an - override pattern of: + line number to force detailed logging for. For example, an over- + ride pattern of: kex.c:*:1000,*:kex_exchange_identification():*,packet.c:* would enable detailed logging for line 1000 of kex.c, everything in the kex_exchange_identification() function, and all code in the packet.c file. This option is intended for debugging and no - overrides are enabled by default. + overrides are enabled by default, i.e. default value is none. - MACs Specifies the MAC (message authentication code) algorithms in - order of preference. The MAC algorithm is used for data - integrity protection. Multiple algorithms must be comma- - separated. If the specified list begins with a M-bM-^@M-^X+M-bM-^@M-^Y character, - then the specified algorithms will be appended to the default set - instead of replacing them. If the specified list begins with a - M-bM-^@M-^X-M-bM-^@M-^Y character, then the specified algorithms (including - wildcards) will be removed from the default set instead of - replacing them. If the specified list begins with a M-bM-^@M-^X^M-bM-^@M-^Y - character, then the specified algorithms will be placed at the - head of the default set. + MACs Specifies the MAC (message authentication code) algorithms in or- + der of preference. The MAC algorithm is used for data integrity + protection. Multiple algorithms must be comma-separated. If the + specified list begins with a '+' character, then the specified + algorithms will be appended to the default set instead of replac- + ing them. If the specified list begins with a '-' character, + then the specified algorithms (including wildcards) will be re- + moved from the default set instead of replacing them. If the + specified list begins with a '^' character, then the specified + algorithms will be placed at the head of the default set. - The algorithms that contain "-etm" calculate the MAC after - encryption (encrypt-then-mac). These are considered safer and + The algorithms that contain "-etm" calculate the MAC after en- + cryption (encrypt-then-mac). These are considered safer and their use recommended. The default is: @@ -797,6 +856,11 @@ The list of available MAC algorithms may also be obtained using "ssh -Q mac". + MandatoryCRL + "X509 store" option: Specifies whether CRL must present in store + for all certificates in "certificate chain" with attribute + "X509v3 CRL Distribution Points". The default is no. + NoHostAuthenticationForLocalhost Disable host authentication for localhost (loopback addresses). The argument to this keyword must be yes or no (the default). @@ -810,36 +874,36 @@ to this keyword must be yes (the default) or no. PermitLocalCommand - Allow local command execution via the LocalCommand option or - using the !command escape sequence in ssh(1). The argument must - be yes or no (the default). + Allow local command execution via the LocalCommand option or us- + ing the !command escape sequence in ssh(1). The argument must be + yes or no (the default). PermitRemoteOpen Specifies the destinations to which remote TCP port forwarding is - permitted when RemoteForward is used as a SOCKS proxy. The - forwarding specification must be one of the following forms: + permitted when RemoteForward is used as a SOCKS proxy. The for- + warding specification must be one of the following forms: PermitRemoteOpen host:port PermitRemoteOpen IPv4_addr:port PermitRemoteOpen [IPv6_addr]:port - Multiple forwards may be specified by separating them with - whitespace. An argument of any can be used to remove all - restrictions and permit any forwarding requests. An argument of - none can be used to prohibit all forwarding requests. The - wildcard M-bM-^@M-^X*M-bM-^@M-^Y can be used for host or port to allow all hosts or - ports respectively. Otherwise, no pattern matching or address - lookups are performed on supplied names. + Multiple forwards may be specified by separating them with white- + space. An argument of any can be used to remove all restrictions + and permit any forwarding requests. An argument of none can be + used to prohibit all forwarding requests. The wildcard '*' can + be used for host or port to allow all hosts or ports respec- + tively. Otherwise, no pattern matching or address lookups are + performed on supplied names. PKCS11Provider Specifies which PKCS#11 provider to use or none to indicate that no provider should be used (the default). The argument to this keyword is a path to the PKCS#11 shared library ssh(1) should use - to communicate with a PKCS#11 token providing keys for user - authentication. + to communicate with a PKCS#11 token providing X.509 certificates + or keys for user authentication. - Port Specifies the port number to connect on the remote host. The - default is 22. + Port Specifies the port to connect on the remote host. It could be + expresed either by number or by service name. The default is 22. PreferredAuthentications Specifies the order in which the client should try authentication @@ -851,21 +915,25 @@ keyboard-interactive,password ProxyCommand - Specifies the command to use to connect to the server. The - command string extends to the end of the line, and is executed - using the user's shell M-bM-^@M-^XexecM-bM-^@M-^Y directive to avoid a lingering - shell process. + Specifies the command to use to connect to the server. The com- + mand string extends to the end of the line, and is executed using + the user's shell 'exec' directive to avoid a lingering shell + process. Arguments to ProxyCommand accept the tokens described in the TOKENS section. The command can be basically anything, and should read from its standard input and write to its standard output. It should eventually connect an sshd(8) server running - on some machine, or execute sshd -i somewhere. Host key - management will be done using the Hostname of the host being - connected (defaulting to the name typed by the user). Setting - the command to none disables this option entirely. Note that + on some machine, or execute sshd -i somewhere. Host key manage- + ment will be done using the Hostname of the host being connected + (defaulting to the name typed by the user). Note that CheckHostIP is not available for connects with a proxy command. + Setting the command to none disables this option entirely. Note + that this option will compete with the ProxyJump option - which- + ever is specified first will prevent later instances of the other + from taking effect. + This directive is useful in conjunction with nc(1) and its proxy support. For example, the following directive would connect via an HTTP proxy at 192.0.2.0: @@ -874,14 +942,15 @@ ProxyJump Specifies one or more jump proxies as either [user@]host[:port] - or an ssh URI. Multiple proxies may be separated by comma - characters and will be visited sequentially. Setting this option + or an ssh URI. Multiple proxies may be separated by comma char- + acters and will be visited sequentially. Setting this option will cause ssh(1) to connect to the target host by first making a - ssh(1) connection to the specified ProxyJump host and then - establishing a TCP forwarding to the ultimate target from there. - Setting the host to none disables this option entirely. + ssh(1) connection to the specified ProxyJump host and then estab- + lishing a TCP forwarding to the ultimate target from there. Set- + ting the host to none disables this option entirely. - Note that this option will compete with the ProxyCommand option - + Setting the command to none disables this option entirely. Note + that this option will compete with the ProxyCommand option - whichever is specified first will prevent later instances of the other from taking effect. @@ -896,106 +965,94 @@ The default is no. PubkeyAcceptedAlgorithms - Specifies the signature algorithms that will be used for public - key authentication as a comma-separated list of patterns. If the - specified list begins with a M-bM-^@M-^X+M-bM-^@M-^Y character, then the algorithms - after it will be appended to the default instead of replacing it. - If the specified list begins with a M-bM-^@M-^X-M-bM-^@M-^Y character, then the - specified algorithms (including wildcards) will be removed from - the default set instead of replacing them. If the specified list - begins with a M-bM-^@M-^X^M-bM-^@M-^Y character, then the specified algorithms will - be placed at the head of the default set. The default for this - option is: + Option compatibility. See PubkeyAlgorithms - ssh-ed25519-cert-v01@openssh.com, - ecdsa-sha2-nistp256-cert-v01@openssh.com, - ecdsa-sha2-nistp384-cert-v01@openssh.com, - ecdsa-sha2-nistp521-cert-v01@openssh.com, - sk-ssh-ed25519-cert-v01@openssh.com, - sk-ecdsa-sha2-nistp256-cert-v01@openssh.com, - rsa-sha2-512-cert-v01@openssh.com, - rsa-sha2-256-cert-v01@openssh.com, - ssh-ed25519, - ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521, - sk-ssh-ed25519@openssh.com, - sk-ecdsa-sha2-nistp256@openssh.com, - rsa-sha2-512,rsa-sha2-256 + PubkeyAcceptedKeyTypes + Option compatibility. See PubkeyAlgorithms - The list of available signature algorithms may also be obtained - using "ssh -Q PubkeyAcceptedAlgorithms". + PubkeyAlgorithms + Specifies the publickey algorithms used in "publickey" authenti- + cation allowed to sent to the host. See PATTERNS for more infor- + mation on patterns. The default * allows all algorithms and de- + pend from X509KeyAlgorithm, i.e. the option allow all specified + by X509KeyAlgorithm plus "plain" key algorithms like ssh-ed25519, + ecdsa-sha2-nistp256, ecdsa-sha2-nistp384, ecdsa-sha2-nistp521, + ssh-rsa and ssh-dss. If a X.509 certificate is used as identity + but corresponding algorithms are not allowed the client will try + plain key algorithm conforming to certificate public key. Then + if plain key algorithm is not allowed identity is skipped. The + list of supported key algorithms may also be obtained using "ssh + -Q key". PubkeyAuthentication Specifies whether to try public key authentication. The argument - to this keyword must be yes (the default), no, unbound or - host-bound. The final two options enable public key - authentication while respectively disabling or enabling the - OpenSSH host-bound authentication protocol extension required for - restricted ssh-agent(1) forwarding. + to this keyword must be yes (the default) or no. RekeyLimit Specifies the maximum amount of data that may be transmitted or - received before the session key is renegotiated, optionally - followed by a maximum amount of time that may pass before the - session key is renegotiated. The first argument is specified in - bytes and may have a suffix of M-bM-^@M-^XKM-bM-^@M-^Y, M-bM-^@M-^XMM-bM-^@M-^Y, or M-bM-^@M-^XGM-bM-^@M-^Y to indicate - Kilobytes, Megabytes, or Gigabytes, respectively. The default is - between M-bM-^@M-^X1GM-bM-^@M-^Y and M-bM-^@M-^X4GM-bM-^@M-^Y, depending on the cipher. The optional - second value is specified in seconds and may use any of the units + received before the session key is renegotiated, optionally fol- + lowed by a maximum amount of time that may pass before the ses- + sion key is renegotiated. The first argument is specified in + bytes and may have a suffix of 'K', 'M', or 'G' to indicate Kilo- + bytes, Megabytes, or Gigabytes, respectively. The default is be- + tween '1G' and '4G', depending on the cipher. The optional sec- + ond value is specified in seconds and may use any of the units documented in the TIME FORMATS section of sshd_config(5). The default value for RekeyLimit is default none, which means that rekeying is performed after the cipher's default amount of data has been sent or received and no time based rekeying is done. RemoteCommand - Specifies a command to execute on the remote machine after - successfully connecting to the server. The command string - extends to the end of the line, and is executed with the user's - shell. Arguments to RemoteCommand accept the tokens described in - the TOKENS section. + Specifies a command to execute on the remote machine after suc- + cessfully connecting to the server. The command string extends + to the end of the line, and is executed with the user's shell. + Arguments to RemoteCommand accept the tokens described in the + TOKENS section. RemoteForward Specifies that a TCP port on the remote machine be forwarded over the secure channel. The remote port may either be forwarded to a specified host and port from the local machine, or may act as a - SOCKS 4/5 proxy that allows a remote client to connect to - arbitrary destinations from the local machine. The first - argument is the listening specification and may be - [bind_address:]port or, if the remote host supports it, a Unix - domain socket path. If forwarding to a specific destination then - the second argument must be host:hostport or a Unix domain socket - path, otherwise if no destination argument is specified then the - remote forwarding will be established as a SOCKS proxy. When - acting as a SOCKS proxy, the destination of the connection can be - restricted by PermitRemoteOpen. + SOCKS 4/5 proxy that allows a remote client to connect to arbi- + trary destinations from the local machine. The first argument is + the listening specification and may be [bind_address:]port or, if + the remote host supports it, a Unix domain socket path. If for- + warding to a specific destination then the second argument must + be host:hostport or a Unix domain socket path, otherwise if no + destination argument is specified then the remote forwarding will + be established as a SOCKS proxy. When acting as a SOCKS proxy, + the destination of the connection can be restricted by + PermitRemoteOpen. IPv6 addresses can be specified by enclosing addresses in square brackets. Multiple forwardings may be specified, and additional forwardings can be given on the command line. Privileged ports - can be forwarded only when logging in as root on the remote - machine. Unix domain socket paths may use the tokens described - in the TOKENS section and environment variables as described in - the ENVIRONMENT VARIABLES section. + can be forwarded only when logging in as root on the remote ma- + chine. If the port argument is 0, the listen port will be dynamically allocated on the server and reported to the client at run time. If the bind_address is not specified, the default is to only bind - to loopback addresses. If the bind_address is M-bM-^@M-^X*M-bM-^@M-^Y or an empty - string, then the forwarding is requested to listen on all - interfaces. Specifying a remote bind_address will only succeed - if the server's GatewayPorts option is enabled (see - sshd_config(5)). + to loopback addresses. If the bind_address is '*' or an empty + string, then the forwarding is requested to listen on all inter- + faces. Specifying a remote bind_address will only succeed if the + server's GatewayPorts option is enabled (see sshd_config(5)). + + Unix domain socket paths may use the tokens described in the + TOKENS section and environment variables as described in the + ENVIRONMENT VARIABLES section. RequestTTY Specifies whether to request a pseudo-tty for the session. The - argument may be one of: no (never request a TTY), yes (always - request a TTY when standard input is a TTY), force (always - request a TTY) or auto (request a TTY when opening a login - session). This option mirrors the -t and -T flags for ssh(1). + argument may be one of: no (never request a TTY), yes (always re- + quest a TTY when standard input is a TTY), force (always request + a TTY) or auto (request a TTY when opening a login session). + This option mirrors the -t and -T flags for ssh(1). RequiredRSASize - Specifies the minimum RSA key size (in bits) that ssh(1) will - accept. User authentication keys smaller than this limit will be + Specifies the minimum RSA key size (in bits) that ssh(1) will ac- + cept. User authentication keys smaller than this limit will be ignored. Servers that present host keys smaller than this limit will cause the connection to be terminated. The default is 1024 bits. Note that this limit may only be raised from the default. @@ -1005,53 +1062,40 @@ will be refused for host authentication. Note that if this file does not exist or is not readable, then host authentication will be refused for all hosts. Keys may be specified as a text file, - listing one public key per line, or as an OpenSSH Key Revocation - List (KRL) as generated by ssh-keygen(1). For more information - on KRLs, see the KEY REVOCATION LISTS section in ssh-keygen(1). - Arguments to RevokedHostKeys may use the tilde syntax to refer to - a user's home directory, the tokens described in the TOKENS - section and environment variables as described in the ENVIRONMENT - VARIABLES section. - - SecurityKeyProvider - Specifies a path to a library that will be used when loading any - FIDO authenticator-hosted keys, overriding the default of using - the built-in USB HID support. - - If the specified value begins with a M-bM-^@M-^X$M-bM-^@M-^Y character, then it will - be treated as an environment variable containing the path to the - library. + listing one public key per line, or as an custom OpenSSH Key Re- + vocation List (KRL) as generated by ssh-keygen(1). For more in- + formation on KRLs, see the KEY REVOCATION LISTS section in + ssh-keygen(1). Arguments to RevokedHostKeys may use the tilde + syntax to refer to a user's home directory, the tokens described + in the TOKENS section and environment variables as described in + the ENVIRONMENT VARIABLES section. SendEnv Specifies what variables from the local environ(7) should be sent - to the server. The server must also support it, and the server - must be configured to accept these environment variables. Note - that the TERM environment variable is always sent whenever a + to the server. Variables are specified by name as pattern-list. + Lists may be separated by whitespace or spread across multiple + SendEnv directives. The server must also support it, and the + server must be configured to accept these environment variables. + Note that the TERM environment variable is always sent whenever a pseudo-terminal is requested as it is required by the protocol. Refer to AcceptEnv in sshd_config(5) for how to configure the - server. Variables are specified by name, which may contain - wildcard characters. Multiple environment variables may be - separated by whitespace or spread across multiple SendEnv - directives. + server. - See PATTERNS for more information on patterns. - - It is possible to clear previously set SendEnv variable names by - prefixing patterns with -. The default is not to send any - environment variables. + See PATTERNS for more information on pattern-list. The default + is not to send any environment variables. ServerAliveCountMax Sets the number of server alive messages (see below) which may be sent without ssh(1) receiving any messages back from the server. - If this threshold is reached while server alive messages are - being sent, ssh will disconnect from the server, terminating the + If this threshold is reached while server alive messages are be- + ing sent, ssh will disconnect from the server, terminating the session. It is important to note that the use of server alive messages is very different from TCPKeepAlive (below). The server - alive messages are sent through the encrypted channel and - therefore will not be spoofable. The TCP keepalive option - enabled by TCPKeepAlive is spoofable. The server alive mechanism - is valuable when the client or server depend on knowing when a - connection has become unresponsive. + alive messages are sent through the encrypted channel and there- + fore will not be spoofable. The TCP keepalive option enabled by + TCPKeepAlive is spoofable. The server alive mechanism is valu- + able when the client or server depend on knowing when a connec- + tion has become unresponsive. The default value is 3. If, for example, ServerAliveInterval (see below) is set to 15 and ServerAliveCountMax is left at the @@ -1068,15 +1112,18 @@ SessionType May be used to either request invocation of a subsystem on the remote system, or to prevent the execution of a remote command at - all. The latter is useful for just forwarding ports. The - argument to this keyword must be none (same as the -N option), + all. The latter is useful for just forwarding ports. The argu- + ment to this keyword must be none (same as the -N option), subsystem (same as the -s option) or default (shell or command execution). - SetEnv Directly specify one or more environment variables and their - contents to be sent to the server. Similarly to SendEnv, with - the exception of the TERM variable, the server must be prepared - to accept the environment variable. + SetEnv Directly specify one or more environment variables and their con- + tents to be sent to the server. Variables and their contents are + specified as pattern-list. Lists may be separated by whitespace + or spread across multiple SetEnv directives. The environment + value may be quoted (e.g. if it contains whitespace characters). + Similarly to SendEnv, with the exception of the TERM variable, + the server must be prepared to accept the environment variable. StdinNull Redirects stdin from /dev/null (actually, prevents reading from @@ -1107,37 +1154,37 @@ StrictHostKeyChecking If this flag is set to yes, ssh(1) will never automatically add - host keys to the ~/.ssh/known_hosts file, and refuses to connect - to hosts whose host key has changed. This provides maximum - protection against man-in-the-middle (MITM) attacks, though it - can be annoying when the /etc/ssh/ssh_known_hosts file is poorly - maintained or when connections to new hosts are frequently made. + host keys to the first UserKnownHostsFile, and refuses to connect + to hosts whose host key has changed. This provides maximum pro- + tection against man-in-the-middle (MITM) attacks, though it can + be annoying when the GlobalKnownHostsFile files are poorly main- + tained or when connections to new hosts are frequently made. This option forces the user to manually add all new hosts. If this flag is set to accept-new then ssh will automatically add - new host keys to the user's known_hosts file, but will not permit - connections to hosts with changed host keys. If this flag is set - to no or off, ssh will automatically add new host keys to the - user known hosts files and allow connections to hosts with + new host keys to the first user known hosts file, but will not + permit connections to hosts with changed host keys. If this flag + is set to no ssh will automatically add new host keys to the + first user known hosts file and allow connections to hosts with changed hostkeys to proceed, subject to some restrictions. If this flag is set to ask (the default), new host keys will be - added to the user known host files only after the user has + added to the first user known host file only after the user has confirmed that is what they really want to do, and ssh will refuse to connect to hosts whose host key has changed. The host keys of known hosts will be verified automatically in all cases. SyslogFacility Gives the facility code that is used when logging messages from - ssh(1). The possible values are: DAEMON, USER, AUTH, LOCAL0, - LOCAL1, LOCAL2, LOCAL3, LOCAL4, LOCAL5, LOCAL6, LOCAL7. The - default is USER. + ssh(1). The possible values are: DAEMON, USER, AUTH, LOCAL0, LO- + CAL1, LOCAL2, LOCAL3, LOCAL4, LOCAL5, LOCAL6, LOCAL7. The de- + fault is USER. TCPKeepAlive Specifies whether the system should send TCP keepalive messages to the other side. If they are sent, death of the connection or crash of one of the machines will be properly noticed. However, - this means that connections will die if the route is down - temporarily, and some people find it annoying. + this means that connections will die if the route is down tempo- + rarily, and some people find it annoying. The default is yes (to send TCP keepalive messages), and the client will notice if the network goes down or the remote host @@ -1160,82 +1207,150 @@ The argument must be local_tun[:remote_tun]. The devices may be specified by numerical ID or the keyword any, which uses the next - available tunnel device. If remote_tun is not specified, it - defaults to any. The default is any:any. + available tunnel device. If remote_tun is not specified, it de- + faults to any. The default is any:any. UpdateHostKeys - Specifies whether ssh(1) should accept notifications of - additional hostkeys from the server sent after authentication has - completed and add them to UserKnownHostsFile. The argument must - be yes, no or ask. This option allows learning alternate - hostkeys for a server and supports graceful key rotation by - allowing a server to send replacement public keys before old ones - are removed. - - Additional hostkeys are only accepted if the key used to - authenticate the host was already trusted or explicitly accepted - by the user, the host was authenticated via UserKnownHostsFile - (i.e. not GlobalKnownHostsFile) and the host was authenticated - using a plain key and not a certificate. - - UpdateHostKeys is enabled by default if the user has not - overridden the default UserKnownHostsFile setting and has not - enabled VerifyHostKeyDNS, otherwise UpdateHostKeys will be set to - no. - - If UpdateHostKeys is set to ask, then the user is asked to - confirm the modifications to the known_hosts file. Confirmation - is currently incompatible with ControlPersist, and will be - disabled if it is enabled. + Specifies whether ssh(1) should accept notifications of addi- + tional host keys from the server sent after authentication has + completed and add them to first UserKnownHostsFile. The argument + must be yes, no (the default) or ask. Enabling this option al- + lows learning alternate hostkeys for a server and supports grace- + ful key rotation by allowing a server to send replacement public + keys before old ones are removed. + + Hostkeys are only accepted if the key algorithm used to authenti- + cate the host is accepted by the user (see the HostKeyAlgorithms + option for details), the host was authenticated via + UserKnownHostsFile (i.e. not GlobalKnownHostsFile). If + UpdateHostKeys is set to ask, then the user is asked to confirm + the modifications to the known hosts file. Confirmation is cur- + rently incompatible with BatchMode, ControlPersist, if hostkey is + found in GlobalKnownHostsFile, RemoteCommand, and will be dis- + abled if it is enabled. - Presently, only sshd(8) from OpenSSH 6.8 and greater support the + Presently, only some ssh servers support the "hostkeys@openssh.com" protocol extension used to inform the client of all the server's hostkeys. - User Specifies the user to log in as. This can be useful when a - different user name is used on different machines. This saves - the trouble of having to remember to give the user name on the - command line. + Due to all above feature is considered experimental and so de- + fault is no. + + User Specifies the user to log in as. This can be useful when a dif- + ferent user name is used on different machines. This saves the + trouble of having to remember to give the user name on the com- + mand line. + + UserCACertificateFile + "X509 store" option: User CACertificateFile , the default is + ~/.ssh/ca-bundle.crt. + + UserCACertificatePath + "X509 store" option: User CACertificatePath , the default is + ~/.ssh/crt. + + UserCARevocationFile + "X509 store" option: User CARevocationFile , the default is + ~/.ssh/ca-bundle.crl. + + UserCARevocationPath + "X509 store" option: User CARevocationPath , the default is + ~/.ssh/crl. UserKnownHostsFile - Specifies one or more files to use for the user host key - database, separated by whitespace. Each filename may use tilde - notation to refer to the user's home directory, the tokens - described in the TOKENS section and environment variables as - described in the ENVIRONMENT VARIABLES section. A value of none - causes ssh(1) to ignore any user-specific known hosts files. The - default is ~/.ssh/known_hosts, ~/.ssh/known_hosts2. + Specifies one or more files to use for the user host key data- + base, separated by whitespace. Each file may use tilde notation + to refer to the user's home directory, the tokens described in + the Setting the value to none disables the use of user host key + database. TOKENS section and environment variables as described + in the ENVIRONMENT VARIABLES section. The default is + ~/.ssh/known_hosts, ~/.ssh/known_hosts2. + + VACertificateFile + File with X.509 certificates in PEM format concatenated together. + In use when VAType is set to ocspspec. Certificates from that + file explicitly trust 'OCSP Responder' public key. They are used + as trusted certificates in addition to certificates from + CACertificateFile , CACertificatePath , UserCACertificateFile and + UserCACertificatePath to verify responder certificate. The de- + fault is not set. + + VAType Specifies whether 'Online Certificate Status Protocol' (OCSP) is + used to validate X.509 certificates. Accepted values are case + insensitive: + none do not use OCSP to validate certificates; + ocspcert + validate only certificates that specify 'OCSP + Service Locator' URL; + ocspspec + use specified in the configuration 'OCSP Responder' + to validate all certificates. + The default is none. + + VAOCSPResponderURL + 'Access Location' / 'OCSP Service Locator' URL of the OCSP + provider. In use when VAType is set to ocspspec. VerifyHostKeyDNS - Specifies whether to verify the remote key using DNS and SSHFP - resource records. If this option is set to yes, the client will - implicitly trust keys that match a secure fingerprint from DNS. - Insecure fingerprints will be handled as if this option was set - to ask. If this option is set to ask, information on fingerprint - match will be displayed, but the user will still need to confirm - new host keys according to the StrictHostKeyChecking option. The - default is no. + Specifies whether to verify the remote key using DNS and + CERT/SSHFP resource records. If this option is set to yes, the + client will implicitly trust keys that match a secure fingerprint + from DNS. Insecure fingerprints will be handled as if this op- + tion was set to ask. If this option is set to ask, information + on fingerprint match will be displayed, but the user will still + need to confirm new host keys according to the + StrictHostKeyChecking option. The default is no. See also VERIFYING HOST KEYS in ssh(1). VisualHostKey If this flag is set to yes, an ASCII art representation of the - remote host key fingerprint is printed in addition to the - fingerprint string at login and for unknown host keys. If this - flag is set to no (the default), no fingerprint strings are - printed at login and only the fingerprint string will be printed - for unknown host keys. + remote host key fingerprint is printed in addition to the finger- + print string at login and for unknown host keys. If this flag is + set to no (the default), no fingerprint strings are printed at + login and only the fingerprint string will be printed for unknown + host keys. + + X509KeyAlgorithm + Specifies how X.509 certificates and signatures are encoded. It + is possible to have multiple algorithms in form specified in X509 + Key Algorithms Format section of sshd_config(5). Programs use + the first listed for ECDSA, Ed25519, RSA, or DSA key in signing + and accept all listed. + + The default for certificates with ECDSA keys is: + X509KeyAlgorithm + x509v3-ecdsa-sha2-nistp256,ssh-sha256,ecdsa-sha2-nistp256 + X509KeyAlgorithm + x509v3-ecdsa-sha2-nistp384,ssh-sha384,ecdsa-sha2-nistp384 + X509KeyAlgorithm + x509v3-ecdsa-sha2-nistp521,ssh-sha512,ecdsa-sha2-nistp521 + + The default for certificates with Ed25519 keys is: + X509KeyAlgorithm x509v3-ssh-ed25519,none,ssh-ed25519 + + The default for certificates with RSA key is: + X509KeyAlgorithm + x509v3-rsa2048-sha256,rsa2048-sha256,rsa2048-sha256 + X509KeyAlgorithm x509v3-ssh-rsa,rsa-sha1,ssh-rsa + X509KeyAlgorithm x509v3-sign-rsa,rsa-sha1 + X509KeyAlgorithm x509v3-sign-rsa,rsa-md5 + + The default for certificates with DSA key is: + X509KeyAlgorithm x509v3-ssh-dss,dss-raw,ssh-dss + X509KeyAlgorithm x509v3-sign-dss,dss-asn1 + X509KeyAlgorithm x509v3-sign-dss,dss-raw XAuthLocation Specifies the full pathname of the xauth(1) program. The default is /usr/X11R6/bin/xauth. PATTERNS - A pattern consists of zero or more non-whitespace characters, M-bM-^@M-^X*M-bM-^@M-^Y (a - wildcard that matches zero or more characters), or M-bM-^@M-^X?M-bM-^@M-^Y (a wildcard that - matches exactly one character). For example, to specify a set of - declarations for any host in the ".co.uk" set of domains, the following - pattern could be used: + A pattern consists of zero or more non-whitespace characters, '*' (a + wildcard that matches zero or more characters), or '?' (a wildcard that + matches exactly one character). For example, to specify a set of decla- + rations for any host in the ".co.uk" set of domains, the following pat- + tern could be used: Host *.co.uk @@ -1246,9 +1361,9 @@ A pattern-list is a comma-separated list of patterns. Patterns within pattern-lists may be negated by preceding them with an exclamation mark - (M-bM-^@M-^X!M-bM-^@M-^Y). For example, to allow a key to be used from anywhere within an - organization except from the "dialup" pool, the following entry (in - authorized_keys) could be used: + ('!'). For example, to allow a key to be used from anywhere within an + organization except from the "dialup" pool, the following entry (in au- + thorized_keys) could be used: from="!*.dialup.example.com,*.example.com" @@ -1267,33 +1382,33 @@ Arguments to some keywords can make use of tokens, which are expanded at runtime: - %% A literal M-bM-^@M-^X%M-bM-^@M-^Y. + %% A literal '%'. %C Hash of %l%h%p%r. %d Local user's home directory. %f The fingerprint of the server's host key. - %H The known_hosts hostname or address that is being searched + %H The known hosts hostname or address that is being searched for. %h The remote hostname. - %I A string describing the reason for a KnownHostsCommand - execution: either ADDRESS when looking up a host by address - (only when CheckHostIP is enabled), HOSTNAME when searching - by hostname, or ORDER when preparing the host key algorithm + %I A string describing the reason for a KnownHostsCommand execu- + tion: either ADDRESS when looking up a host by address (only + when CheckHostIP is enabled), HOSTNAME when searching by + hostname, or ORDER when preparing the host key algorithm preference list to use for the destination host. %i The local user ID. %K The base64 encoded host key. - %k The host key alias if specified, otherwise the original - remote hostname given on the command line. + %k The host key alias if specified, otherwise the original re- + mote hostname given on the command line. %L The local hostname. %l The local hostname, including the domain name. %n The original remote hostname, as given on the command line. %p The remote port. %r The remote username. - %T The local tun(4) or tap(4) network interface assigned if - tunnel forwarding was requested, or "NONE" otherwise. + %T The local tun(4) or tap(4) network interface assigned if tun- + nel forwarding was requested, or "NONE" otherwise. %t The type of the server host key, e.g. ssh-ed25519. %u The local username. - CertificateFile, ControlPath, IdentityAgent, IdentityFile, + CertificateFile, ControlPath, ForwardAgent, IdentityAgent, IdentityFile, KnownHostsCommand, LocalForward, Match exec, RemoteCommand, RemoteForward, RevokedHostKeys, and UserKnownHostsFile accept the tokens %%, %C, %d, %h, %i, %k, %L, %l, %n, %p, %r, and %u. @@ -1304,7 +1419,7 @@ LocalCommand accepts all tokens. - ProxyCommand and ProxyJump accept the tokens %%, %h, %n, %p, and %r. + ProxyCommand accepts the tokens %%, %h, %n, %p, and %r. ENVIRONMENT VARIABLES Arguments to some keywords can be expanded at runtime from environment @@ -1321,9 +1436,9 @@ FILES ~/.ssh/config This is the per-user configuration file. The format of this file - is described above. This file is used by the SSH client. - Because of the potential for abuse, this file must have strict - permissions: read/write for the user, and not writable by others. + is described above. This file is used by the SSH client. Be- + cause of the potential for abuse, this file must have strict per- + missions: read/write for the user, and not writable by others. /etc/ssh/ssh_config Systemwide configuration file. This file provides defaults for @@ -1335,10 +1450,11 @@ ssh(1) AUTHORS - OpenSSH is a derivative of the original and free ssh 1.2.12 release by + PKIX-SSH is a derivative of the original and free ssh 1.2.12 release by Tatu Ylonen. Aaron Campbell, Bob Beck, Markus Friedl, Niels Provos, Theo - de Raadt and Dug Song removed many bugs, re-added newer features and - created OpenSSH. Markus Friedl contributed the support for SSH protocol - versions 1.5 and 2.0. + de Raadt and Dug Song removed many bugs, re-added newer features and cre- + ated OpenSSH. Markus Friedl contributed the support for SSH protocol + versions 1.5 and 2.0. Roumen Petrov contributed support for X.509 cer- + tificates. -OpenBSD 7.3 July 17, 2023 OpenBSD 7.3 +BSD 17 July 2023 BSD diff -ruN openssh-9.4p1/ssh_config.5 openssh-9.4p1+x509-14.2.1/ssh_config.5 --- openssh-9.4p1/ssh_config.5 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/ssh_config.5 2023-08-20 10:07:00.000000000 +0300 @@ -1,3 +1,11 @@ +.\" Implement .Dd with the Mdocdate RCS keyword +.rn Dd xD +.de Dd +.ie \\$1$Mdocdate: \{\ +. xD \\$3 \\$2 \\$4 +.\} +.el .xD \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 +.. .\" .\" Author: Tatu Ylonen .\" Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -12,6 +20,7 @@ .\" Copyright (c) 1999,2000 Markus Friedl. All rights reserved. .\" Copyright (c) 1999 Aaron Campbell. All rights reserved. .\" Copyright (c) 1999 Theo de Raadt. All rights reserved. +.\" Copyright (c) 2002-2022 Roumen Petrov. All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions @@ -39,7 +48,7 @@ .Os .Sh NAME .Nm ssh_config -.Nd OpenSSH client configuration file +.Nd Secure shell client configuration files .Sh DESCRIPTION .Xr ssh 1 obtains configuration data from the following sources in @@ -254,7 +263,7 @@ .Cm ask , .Xr ssh 1 will require confirmation using the -.Ev SSH_ASKPASS +.Xr ssh-askpass 1 program before adding a key (see .Xr ssh-add 1 for details). @@ -281,7 +290,7 @@ .Cm yes , .Cm confirm (optionally followed by a time interval), -.Cm ask +.Cm ask , or a time interval. .It Cm AddressFamily Specifies which address family to use when connecting. @@ -292,6 +301,20 @@ (use IPv4 only), or .Cm inet6 (use IPv6 only). +.It Cm AllowedCertPurpose +The intended use for the X.509 server certificate. Without this option +no chain verification will be done. Currently accepted uses are case +insensitive: +.Bl -tag -width Ds -compact +.It Cm sslserver | Cm SSL server | Cm SSL_server | Cm server +only SSL-server purpose +.It Cm any | Cm Any Purpose | Cm Any_Purpose | Cm AnyPurpose +allow any purpose +.It Cm skip | Cm '' Li (empty) +do not check purpose +.El +The default is +.Cm sslserver . .It Cm BatchMode If set to .Cm yes , @@ -312,11 +335,68 @@ .It Cm BindInterface Use the address of the specified interface on the local machine as the source address of the connection. +.It Cm CACertificateFile +.Dq X509 store +option: +This file contain multiple certificates of certificate signers in +PEM format concatenated together. The default is +.Pa /etc/ssh/ca/ca-bundle.crt . +.It Cm CACertificatePath +.Dq X509 store +option: +.Dq "Hash dir" +with certificates of certificate signers. Each certificate should be +stored in separate file with name [HASH].[NUMBER], where [HASH] is +certificate hash value and [NUMBER] is an integer starting from zero. +The default is +.Pa /etc/ssh/ca/crt . +.It Cm CAldapVersion +.Dq X509 store +option: +Specifies LDAP protocol version. +The default depend from LDAP library. +.It Cm CAldapURL +.Dq X509 store +option: +Specifies hostport and dn of LDAP URLs (Uniform Resource Locators) +as detailed in RFC 2255. The rest of URL is build internally. +Because of options parser limitation use +.Sq %3D +instead of +.Sq = +! +LDAP initialization method may require URL to be escaped, i.e. use +.Sq %2C +instead of +.Sq \&, +(comma). +Escaped URL don't depend from LDAP initialization method. +.It Cm CARevocationFile +.Dq X509 store +option: +This file contain multiple +.Dq "Certificate Revocation List" +(CRL) of certificate signers in PEM format concatenated together. +The default is +.Pa /etc/ssh/ca/ca-bundle.crl . +.It Cm CARevocationPath +.Dq X509 store +option: +.Dq "Hash dir" +with +.Dq "Certificate Revocation List" +(CRL) of certificate signers. Each CRL should be stored in separate +file with name [HASH].r[NUMBER], where [HASH] is CRL hash value and +[NUMBER] is an integer starting from zero. The default is +.Pa /etc/ssh/ca/crl . .It Cm CanonicalDomains When .Cm CanonicalizeHostname is enabled, this option specifies the list of domain suffixes in which to search for the specified destination host. +The default value of +.Cm none +ignores any domain suffixes. .It Cm CanonicalizeFallbackLocal Specifies whether to fail with an error when hostname canonicalization fails. The default, @@ -400,15 +480,13 @@ causes no CNAMEs to be considered for canonicalization. This is the default behaviour. .It Cm CASignatureAlgorithms -Specifies which algorithms are allowed for signing of certificates -by certificate authorities (CAs). +Specifies which algorithms are allowed for signing of custom certificates +by custom certificate authorities (CAs). The default is: .Bd -literal -offset indent -ssh-ed25519,ecdsa-sha2-nistp256, -ecdsa-sha2-nistp384,ecdsa-sha2-nistp521, -sk-ssh-ed25519@openssh.com, -sk-ecdsa-sha2-nistp256@openssh.com, -rsa-sha2-512,rsa-sha2-256 +ssh-ed25519, +ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521, +rsa-sha2-512,rsa-sha2-256,ssh-rsa .Ed .Pp If the specified list begins with a @@ -421,12 +499,12 @@ from the default set instead of replacing them. .Pp .Xr ssh 1 -will not accept host certificates signed using algorithms other than those +will not accept custom host certificates signed using algorithms other than those specified. .It Cm CertificateFile -Specifies a file from which the user's certificate is read. +Specifies a file from which the user's OpenSSH custom certificate is read. A corresponding private key must be provided separately in order -to use this certificate either +to use this OpenSSH custom certificate either from an .Cm IdentityFile directive or @@ -436,9 +514,7 @@ via .Xr ssh-agent 1 , or via a -.Cm PKCS11Provider -or -.Cm SecurityKeyProvider . +.Cm PKCS11Provider . .Pp Arguments to .Cm CertificateFile @@ -450,21 +526,20 @@ section. .Pp It is possible to have multiple certificate files specified in -configuration files; these certificates will be tried in sequence. +configuration files; these OpenSSH custom certificates will be tried in sequence. Multiple .Cm CertificateFile -directives will add to the list of certificates used for +directives will add to the list of OpenSSH custom certificates used for authentication. .It Cm CheckHostIP If set to .Cm yes , .Xr ssh 1 will additionally check the host IP address in the -.Pa known_hosts -file. +known hosts files. This allows it to detect if a host key changed due to DNS spoofing and will add addresses of destination hosts to -.Pa ~/.ssh/known_hosts +user known hosts files, in the process, regardless of the setting of .Cm StrictHostKeyChecking . If the option is set to @@ -670,7 +745,8 @@ .Cm EscapeChar menu for interactive sessions (default .Ql ~C ) . -By default, the command line is disabled. +By default, the command line is enabled unless system support +.Xr pledge 2 . .It Cm EnableSSHKeysign Setting this option to .Cm yes @@ -775,6 +851,11 @@ (beginning with .Sq $ ) in which to find the path. +Arguments to +.Cm ForwardAgent +with explicit path accept the tokens described in the +.Sx TOKENS +section. .Pp Agent forwarding should be enabled with caution. Users with the ability to bypass file permissions on the remote host @@ -805,7 +886,7 @@ .It Cm ForwardX11Timeout Specify a timeout for untrusted X11 forwarding using the format described in the -.Sx TIME FORMATS +.Em TIME FORMATS section of .Xr sshd_config 5 . X11 connections received by @@ -857,6 +938,9 @@ The default is .Pa /etc/ssh/ssh_known_hosts , .Pa /etc/ssh/ssh_known_hosts2 . +Setting the value to +.Cm none +disables the use of global host key database. .It Cm GSSAPIAuthentication Specifies whether user authentication based on GSSAPI is allowed. The default is @@ -869,7 +953,7 @@ Indicates that .Xr ssh 1 should hash host names and addresses when they are added to -.Pa ~/.ssh/known_hosts . +the first user known hosts file. These hashed names may be used normally by .Xr ssh 1 and @@ -883,43 +967,22 @@ but may be manually hashed using .Xr ssh-keygen 1 . .It Cm HostbasedAcceptedAlgorithms -Specifies the signature algorithms that will be used for hostbased -authentication as a comma-separated list of patterns. -Alternately if the specified list begins with a -.Sq + -character, then the specified signature algorithms will be appended -to the default set instead of replacing them. -If the specified list begins with a -.Sq - -character, then the specified signature algorithms (including wildcards) -will be removed from the default set instead of replacing them. -If the specified list begins with a -.Sq ^ -character, then the specified signature algorithms will be placed -at the head of the default set. -The default for this option is: -.Bd -literal -offset 3n -ssh-ed25519-cert-v01@openssh.com, -ecdsa-sha2-nistp256-cert-v01@openssh.com, -ecdsa-sha2-nistp384-cert-v01@openssh.com, -ecdsa-sha2-nistp521-cert-v01@openssh.com, -sk-ssh-ed25519-cert-v01@openssh.com, -sk-ecdsa-sha2-nistp256-cert-v01@openssh.com, -rsa-sha2-512-cert-v01@openssh.com, -rsa-sha2-256-cert-v01@openssh.com, -ssh-ed25519, -ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521, -sk-ssh-ed25519@openssh.com, -sk-ecdsa-sha2-nistp256@openssh.com, -rsa-sha2-512,rsa-sha2-256 -.Ed -.Pp -The -.Fl Q -option of -.Xr ssh 1 -may be used to list supported signature algorithms. -This was formerly named HostbasedKeyTypes. +Option compatibility. See +.Cm HostbasedAlgorithms +.It Cm HostbasedAlgorithms +Specifies the publickey algorithms that will be used in +.Cm hostbased +authentication as a comma-separated pattern list. +See +.Sx PATTERNS +for more information on patterns. +The default +.Cm * +allows all algorithms. +Note algorithms that use X.509 certificates depend from option +.Cm X509KeyAlgorithm . +The list of supported algorithms may also be obtained using +.Qq ssh -Q key . .It Cm HostbasedAuthentication Specifies whether to try rhosts based authentication with public key authentication. @@ -928,43 +991,48 @@ or .Cm no (the default). +.It Cm HostbasedKeyTypes +Option compatibility. See +.Cm HostbasedAlgorithms .It Cm HostKeyAlgorithms -Specifies the host key signature algorithms +Specifies the host key algorithms that the client wants to use in order of preference. Alternately if the specified list begins with a .Sq + -character, then the specified signature algorithms will be appended to -the default set instead of replacing them. +character, then the specified key algorithms will be appended +to the default set instead of replacing them. If the specified list begins with a .Sq - -character, then the specified signature algorithms (including wildcards) -will be removed from the default set instead of replacing them. +character, then the specified key algorithms (including wildcards) will be removed +from the default set instead of replacing them. If the specified list begins with a .Sq ^ -character, then the specified signature algorithms will be placed -at the head of the default set. -The default for this option is: +character, then the specified key algorithms will be placed at the head of the +default set. +The default for this option depend from +.Cm X509KeyAlgorithm . +By default it contain unique list build from names of X509KeyAlgorithm +defined for ECDSA, Ed25519, RSA and DSA keys, followed by .Bd -literal -offset 3n ssh-ed25519-cert-v01@openssh.com, ecdsa-sha2-nistp256-cert-v01@openssh.com, ecdsa-sha2-nistp384-cert-v01@openssh.com, ecdsa-sha2-nistp521-cert-v01@openssh.com, -sk-ssh-ed25519-cert-v01@openssh.com, -sk-ecdsa-sha2-nistp256-cert-v01@openssh.com, -rsa-sha2-512-cert-v01@openssh.com, -rsa-sha2-256-cert-v01@openssh.com, +rsa-sha2-256-cert-v01@openssh.com,rsa-sha2-512-cert-v01@openssh.com, +ssh-rsa-cert-v01@openssh.com, ssh-ed25519, ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521, -sk-ecdsa-sha2-nistp256@openssh.com, -sk-ssh-ed25519@openssh.com, -rsa-sha2-512,rsa-sha2-256 +rsa-sha2-256,rsa-sha2-512,ssh-rsa, +ssh-dss .Ed .Pp -If hostkeys are known for the destination host then this default is modified -to prefer their algorithms. +If hostkeys are known for the destination host +and specified list does not begins a +.Sq ^ +then this default is modified to prefer their algorithms. .Pp -The list of available signature algorithms may also be obtained using -.Qq ssh -Q HostKeyAlgorithms . +The list of available key algorithms may also be obtained using +.Qq ssh -Q key-alg . .It Cm HostKeyAlias Specifies an alias that should be used instead of the real host name when looking up or saving the host key @@ -997,8 +1065,6 @@ .Xr ssh-agent 1 or a .Cm PKCS11Provider -or -.Cm SecurityKeyProvider offers more identities. The argument to this keyword must be .Cm yes @@ -1037,28 +1103,33 @@ .Sx ENVIRONMENT VARIABLES section. .It Cm IdentityFile -Specifies a file from which the user's DSA, ECDSA, authenticator-hosted ECDSA, -Ed25519, authenticator-hosted Ed25519 or RSA authentication identity is read. -You can also specify a public key file to use the corresponding -private key that is loaded in -.Xr ssh-agent 1 -when the private key file is not present locally. +Specifies a file from which the user's RSA, ECDSA, Ed25519 or DSA authentication +identity is read. The default is .Pa ~/.ssh/id_rsa , .Pa ~/.ssh/id_ecdsa , -.Pa ~/.ssh/id_ecdsa_sk , -.Pa ~/.ssh/id_ed25519 , -.Pa ~/.ssh/id_ed25519_sk +.Pa ~/.ssh/id_ed25519 and .Pa ~/.ssh/id_dsa . +.Pp +For RSA, ECDSA, Ed25519 or DSA identity file may contain X.509 certificate that +match key. In addition file may contain extra X.509 certificates. +Extra certificates along with certificates from X.509 store are used +to build chain of certificates leading to a trusted certificate +authority if required by public key algorithm format. +.Pp Additionally, any identities represented by the authentication agent will be used for authentication unless .Cm IdentitiesOnly is set. -If no certificates have been explicitly specified by +You can also specify a public key file to use the corresponding +private key that is loaded in authentication agent +when the private key file is not present locally. +.Pp +If no OpenSSH custom certificates have been explicitly specified by .Cm CertificateFile , .Xr ssh 1 -will try to load certificate information from the filename obtained by +will try to load OpenSSH custom certificate information from the filename obtained by appending .Pa -cert.pub to the path of a specified @@ -1071,6 +1142,28 @@ .Sx TOKENS section. .Pp +If file name starts with prefix +.Sq engine: +instead from file identity load is redirected to +.Dq loadable cryptographic module +(engine). +The name of +.Dq loadable cryptographic module +has to follow prefix engine: and is terminated by colon separator. +.Xr ssh 1 +command line option -G could specify file with extra engine configuration. +Next argument has to specify reference to key as is recognizable by engine. +.Pp +Prefix +.Dq store: +could be used if cryptographic library supports +.Xr ossl_store 7 +functionality. +In such case after prefix has to be specified URI referencing +to content containing private key and optionally X.509 certificates. +Store content could be displayed by command +.Xr storeutl 1 . +.Pp It is possible to have multiple identity files specified in configuration files; all these identities will be tried in sequence. @@ -1086,7 +1179,7 @@ .Cm IdentityFile may also be used in conjunction with .Cm CertificateFile -in order to provide any certificate also needed for authentication with +in order to provide any OpenSSH custom certificate also needed for authentication with the identity. .It Cm IgnoreUnknown Specifies a pattern-list of unknown options to be ignored if they are @@ -1175,7 +1268,7 @@ Multiple method names must be comma-separated. The default is to use the server specified list. The methods available vary depending on what the server supports. -For an OpenSSH server, +For an PKIX-SSH or OpenSSH server, it may be zero or more of: .Cm bsdauth and @@ -1197,14 +1290,16 @@ default set. The default is: .Bd -literal -offset indent -sntrup761x25519-sha512@openssh.com, curve25519-sha256,curve25519-sha256@libssh.org, ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521, diffie-hellman-group-exchange-sha256, diffie-hellman-group16-sha512, diffie-hellman-group18-sha512, -diffie-hellman-group14-sha256 +diffie-hellman-group14-sha256, +sntrup761x25519-sha512@openssh.com, +diffie-hellman-group14-sha1 .Ed +Note sntrup761x25519-sha512@openssh.com is used if is build. .Pp The list of available key exchange algorithms may also be obtained using .Qq ssh -Q kex . @@ -1217,7 +1312,7 @@ This command is executed after the files have been read. It may write host key lines to standard output in identical format to the usual files (described in the -.Sx VERIFYING HOST KEYS +.Em VERIFYING HOST KEYS section in .Xr ssh 1 ) . Arguments to @@ -1283,6 +1378,7 @@ empty address or .Sq * indicates that the port should be available from all interfaces. +.Pp Unix domain socket paths may use the tokens described in the .Sx TOKENS section and environment variables as described in the @@ -1312,7 +1408,9 @@ function, and all code in the .Pa packet.c file. -This option is intended for debugging and no overrides are enabled by default. +This option is intended for debugging and no overrides are enabled by default, +i.e. default value is +.Cm none . .It Cm MACs Specifies the MAC (message authentication code) algorithms in order of preference. @@ -1347,6 +1445,15 @@ .Pp The list of available MAC algorithms may also be obtained using .Qq ssh -Q mac . +.It Cm MandatoryCRL +.Dq X509 store +option: +Specifies whether CRL must present in store for all certificates in +.Dq certificate chain +with attribute +.Dq X509v3 CRL Distribution Points . +The default is +.Cm no . .It Cm NoHostAuthenticationForLocalhost Disable host authentication for localhost (loopback addresses). The argument to this keyword must be @@ -1419,10 +1526,11 @@ to indicate that no provider should be used (the default). The argument to this keyword is a path to the PKCS#11 shared library .Xr ssh 1 -should use to communicate with a PKCS#11 token providing keys for user -authentication. +should use to communicate with a PKCS#11 token providing +X.509 certificates or keys for user authentication. .It Cm Port -Specifies the port number to connect on the remote host. +Specifies the port to connect on the remote host. +It could be expresed either by number or by service name. The default is 22. .It Cm PreferredAuthentications Specifies the order in which the client should try authentication methods. @@ -1458,13 +1566,18 @@ Host key management will be done using the .Cm Hostname of the host being connected (defaulting to the name typed by the user). -Setting the command to -.Cm none -disables this option entirely. Note that .Cm CheckHostIP is not available for connects with a proxy command. .Pp +Setting the command to +.Cm none +disables this option entirely. +Note that this option will compete with the +.Cm ProxyJump +option - whichever is specified first will prevent later instances of the +other from taking effect. +.Pp This directive is useful in conjunction with .Xr nc 1 and its proxy support. @@ -1497,6 +1610,9 @@ .Cm none disables this option entirely. .Pp +Setting the command to +.Cm none +disables this option entirely. Note that this option will compete with the .Cm ProxyCommand option - whichever is specified first will prevent later instances of the @@ -1516,53 +1632,44 @@ The default is .Cm no . .It Cm PubkeyAcceptedAlgorithms -Specifies the signature algorithms that will be used for public key -authentication as a comma-separated list of patterns. -If the specified list begins with a -.Sq + -character, then the algorithms after it will be appended to the default -instead of replacing it. -If the specified list begins with a -.Sq - -character, then the specified algorithms (including wildcards) will be removed -from the default set instead of replacing them. -If the specified list begins with a -.Sq ^ -character, then the specified algorithms will be placed at the head of the -default set. -The default for this option is: -.Bd -literal -offset 3n -ssh-ed25519-cert-v01@openssh.com, -ecdsa-sha2-nistp256-cert-v01@openssh.com, -ecdsa-sha2-nistp384-cert-v01@openssh.com, -ecdsa-sha2-nistp521-cert-v01@openssh.com, -sk-ssh-ed25519-cert-v01@openssh.com, -sk-ecdsa-sha2-nistp256-cert-v01@openssh.com, -rsa-sha2-512-cert-v01@openssh.com, -rsa-sha2-256-cert-v01@openssh.com, +Option compatibility. See +.Cm PubkeyAlgorithms +.It Cm PubkeyAcceptedKeyTypes +Option compatibility. See +.Cm PubkeyAlgorithms +.It Cm PubkeyAlgorithms +Specifies the publickey algorithms used in +.Dq publickey +authentication allowed to sent to the host. +See +.Sx PATTERNS +for more information on patterns. +The default +.Cm * +allows all algorithms and depend from +.Cm X509KeyAlgorithm , +i.e. the option allow all specified by +.Cm X509KeyAlgorithm +plus +.Dq plain +key algorithms like ssh-ed25519, -ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521, -sk-ssh-ed25519@openssh.com, -sk-ecdsa-sha2-nistp256@openssh.com, -rsa-sha2-512,rsa-sha2-256 -.Ed -.Pp -The list of available signature algorithms may also be obtained using -.Qq ssh -Q PubkeyAcceptedAlgorithms . +ecdsa-sha2-nistp256, ecdsa-sha2-nistp384, ecdsa-sha2-nistp521, +ssh-rsa and ssh-dss. +If a X.509 certificate is used as identity +but corresponding algorithms are not allowed +the client will try plain key algorithm +conforming to certificate public key. +Then if plain key algorithm is not allowed identity is skipped. +The list of supported key algorithms may also be obtained using +.Qq ssh -Q key . .It Cm PubkeyAuthentication Specifies whether to try public key authentication. The argument to this keyword must be .Cm yes -(the default), -.Cm no , -.Cm unbound +(the default) or -.Cm host-bound . -The final two options enable public key authentication while respectively -disabling or enabling the OpenSSH host-bound authentication protocol -extension required for restricted -.Xr ssh-agent 1 -forwarding. +.Cm no . .It Cm RekeyLimit Specifies the maximum amount of data that may be transmitted or received before the session key is renegotiated, optionally followed by a maximum @@ -1579,7 +1686,9 @@ .Sq 4G , depending on the cipher. The optional second value is specified in seconds and may use any of the -units documented in the TIME FORMATS section of +units documented in the +.Em TIME FORMATS +section of .Xr sshd_config 5 . The default value for .Cm RekeyLimit @@ -1622,11 +1731,6 @@ forwardings can be given on the command line. Privileged ports can be forwarded only when logging in as root on the remote machine. -Unix domain socket paths may use the tokens described in the -.Sx TOKENS -section and environment variables as described in the -.Sx ENVIRONMENT VARIABLES -section. .Pp If the .Ar port @@ -1649,6 +1753,12 @@ .Cm GatewayPorts option is enabled (see .Xr sshd_config 5 ) . +.Pp +Unix domain socket paths may use the tokens described in the +.Sx TOKENS +section and environment variables as described in the +.Sx ENVIRONMENT VARIABLES +section. .It Cm RequestTTY Specifies whether to request a pseudo-tty for the session. The argument may be one of: @@ -1683,7 +1793,7 @@ Note that if this file does not exist or is not readable, then host authentication will be refused for all hosts. Keys may be specified as a text file, listing one public key per line, or as -an OpenSSH Key Revocation List (KRL) as generated by +an custom OpenSSH Key Revocation List (KRL) as generated by .Xr ssh-keygen 1 . For more information on KRLs, see the KEY REVOCATION LISTS section in .Xr ssh-keygen 1 . @@ -1695,19 +1805,14 @@ section and environment variables as described in the .Sx ENVIRONMENT VARIABLES section. -.It Cm SecurityKeyProvider -Specifies a path to a library that will be used when loading any -FIDO authenticator-hosted keys, overriding the default of using -the built-in USB HID support. -.Pp -If the specified value begins with a -.Sq $ -character, then it will be treated as an environment variable containing -the path to the library. .It Cm SendEnv Specifies what variables from the local .Xr environ 7 should be sent to the server. +Variables are specified by name as pattern-list. +Lists may be separated by whitespace or spread across multiple +.Cm SendEnv +directives. The server must also support it, and the server must be configured to accept these environment variables. Note that the @@ -1719,20 +1824,10 @@ in .Xr sshd_config 5 for how to configure the server. -Variables are specified by name, which may contain wildcard characters. -Multiple environment variables may be separated by whitespace or spread -across multiple -.Cm SendEnv -directives. .Pp See .Sx PATTERNS -for more information on patterns. -.Pp -It is possible to clear previously set -.Cm SendEnv -variable names by prefixing patterns with -.Pa - . +for more information on pattern-list. The default is not to send any environment variables. .It Cm ServerAliveCountMax Sets the number of server alive messages (see below) which may be @@ -1786,6 +1881,12 @@ .It Cm SetEnv Directly specify one or more environment variables and their contents to be sent to the server. +Variables and their contents are specified as pattern-list. +Lists may be separated by whitespace or spread across multiple +.Cm SetEnv +directives. +The environment value may be quoted (e.g. if it contains whitespace +characters). Similarly to .Cm SendEnv , with the exception of the @@ -1837,35 +1938,32 @@ If this flag is set to .Cm yes , .Xr ssh 1 -will never automatically add host keys to the -.Pa ~/.ssh/known_hosts -file, and refuses to connect to hosts whose host key has changed. +will never automatically add host keys to the first +.Cm UserKnownHostsFile , +and refuses to connect to hosts whose host key has changed. This provides maximum protection against man-in-the-middle (MITM) attacks, though it can be annoying when the -.Pa /etc/ssh/ssh_known_hosts -file is poorly maintained or when connections to new hosts are +.Cm GlobalKnownHostsFile +files are poorly maintained or when connections to new hosts are frequently made. This option forces the user to manually add all new hosts. .Pp If this flag is set to .Cm accept-new -then ssh will automatically add new host keys to the user's -.Pa known_hosts -file, but will not permit connections to hosts with +then ssh will automatically add new host keys to the first user +known hosts file, but will not permit connections to hosts with changed host keys. If this flag is set to .Cm no -or -.Cm off , -ssh will automatically add new host keys to the user known hosts files +ssh will automatically add new host keys to the first user known hosts file and allow connections to hosts with changed hostkeys to proceed, subject to some restrictions. If this flag is set to .Cm ask (the default), new host keys -will be added to the user known host files only after the user +will be added to the first user known host file only after the user has confirmed that is what they really want to do, and ssh will refuse to connect to hosts whose host key has changed. The host keys of @@ -1941,74 +2039,142 @@ .It Cm UpdateHostKeys Specifies whether .Xr ssh 1 -should accept notifications of additional hostkeys from the server sent -after authentication has completed and add them to +should accept notifications of additional host keys from the server sent +after authentication has completed and add them to first .Cm UserKnownHostsFile . The argument must be .Cm yes , .Cm no -or +(the default) or .Cm ask . -This option allows learning alternate hostkeys for a server +Enabling this option allows learning alternate hostkeys for a server and supports graceful key rotation by allowing a server to send replacement public keys before old ones are removed. .Pp -Additional hostkeys are only accepted if the key used to authenticate the -host was already trusted or explicitly accepted by the user, the host was +Hostkeys are only accepted if the key algorithm used to authenticate the +host is accepted by the user (see the +.Cm HostKeyAlgorithms +option for details), the host was authenticated via .Cm UserKnownHostsFile (i.e. not -.Cm GlobalKnownHostsFile ) -and the host was authenticated using a plain key and not a certificate. -.Pp -.Cm UpdateHostKeys -is enabled by default if the user has not overridden the default -.Cm UserKnownHostsFile -setting and has not enabled -.Cm VerifyHostKeyDNS , -otherwise -.Cm UpdateHostKeys -will be set to -.Cm no . -.Pp +.Cm GlobalKnownHostsFile). If .Cm UpdateHostKeys is set to .Cm ask , -then the user is asked to confirm the modifications to the known_hosts file. +then the user is asked to confirm the modifications to the known hosts file. Confirmation is currently incompatible with +.Cm BatchMode , .Cm ControlPersist , +if hostkey is found in +.Cm GlobalKnownHostsFile , +.Cm RemoteCommand , and will be disabled if it is enabled. .Pp Presently, only -.Xr sshd 8 -from OpenSSH 6.8 and greater support the +some ssh servers support the .Qq hostkeys@openssh.com protocol extension used to inform the client of all the server's hostkeys. +.Pp +Due to all above feature is considered experimental and so default is +.Cm no . .It Cm User Specifies the user to log in as. This can be useful when a different user name is used on different machines. This saves the trouble of having to remember to give the user name on the command line. +.It Cm UserCACertificateFile +.Dq X509 store +option: +User +.Cm CACertificateFile +, the default is +.Pa ~/.ssh/ca-bundle.crt . +.It Cm UserCACertificatePath +.Dq X509 store +option: +User +.Cm CACertificatePath +, the default is +.Pa ~/.ssh/crt . +.It Cm UserCARevocationFile +.Dq X509 store +option: +User +.Cm CARevocationFile +, the default is +.Pa ~/.ssh/ca-bundle.crl . +.It Cm UserCARevocationPath +.Dq X509 store +option: +User +.Cm CARevocationPath +, the default is +.Pa ~/.ssh/crl . .It Cm UserKnownHostsFile Specifies one or more files to use for the user host key database, separated by whitespace. -Each filename may use tilde notation to refer to the user's home directory, +Each file may use tilde notation to refer to the user's home directory, the tokens described in the +Setting the value to +.Cm none +disables the use of user host key database. .Sx TOKENS section and environment variables as described in the .Sx ENVIRONMENT VARIABLES section. -A value of -.Cm none -causes -.Xr ssh 1 -to ignore any user-specific known hosts files. The default is .Pa ~/.ssh/known_hosts , .Pa ~/.ssh/known_hosts2 . +.It Cm VACertificateFile +File with X.509 certificates in PEM format concatenated together. +In use when +.Cm VAType +is set to +.Cm ocspspec . +Certificates from that file explicitly trust +.Sq "OCSP Responder" +public key. +They are used as trusted certificates in addition to certificates from +.Cm CACertificateFile +, +.Cm CACertificatePath +, +.Cm UserCACertificateFile +and +.Cm UserCACertificatePath +to verify responder certificate. +The default is not set. +.It Cm VAType +Specifies whether +.Sq "Online Certificate Status Protocol" +(OCSP) is used to validate X.509 certificates. +Accepted values are case insensitive: +.Bl -tag -offset indent -compact +.It none +do not use OCSP to validate certificates; +.It ocspcert +validate only certificates that specify +.Sq "OCSP Service Locator" +URL; +.It ocspspec +use specified in the configuration +.Sq "OCSP Responder" +to validate all certificates. +.El +The default is +.Cm none . +.It Cm VAOCSPResponderURL +.Sq "Access Location" +/ +.Sq "OCSP Service Locator" +URL of the OCSP provider. In use when +.Cm VAType +is set to +.Cm ocspspec . .It Cm VerifyHostKeyDNS -Specifies whether to verify the remote key using DNS and SSHFP resource +Specifies whether to verify the remote key using DNS and CERT/SSHFP resource records. If this option is set to .Cm yes , @@ -2026,7 +2192,7 @@ .Cm no . .Pp See also -.Sx VERIFYING HOST KEYS +.Em VERIFYING HOST KEYS in .Xr ssh 1 . .It Cm VisualHostKey @@ -2040,6 +2206,91 @@ (the default), no fingerprint strings are printed at login and only the fingerprint string will be printed for unknown host keys. +.It Cm X509KeyAlgorithm +Specifies how X.509 certificates and signatures are encoded. +It is possible to have multiple algorithms +in form specified in +.Em X509 Key Algorithms Format +section of +.Xr sshd_config 5 . +Programs use the first listed for +.Cm ECDSA , +.Cm Ed25519 , +.Cm RSA , +or +.Cm DSA +key in signing and accept all listed. +.Pp +The default for certificates with ECDSA keys is: +.Bl -item -offset indent -compact +.It +.Cm X509KeyAlgorithm +.Sm off +.Ar x509v3-ecdsa-sha2-nistp256 , Ar ssh-sha256 , Ar ecdsa-sha2-nistp256 +.Sm on +.It +.Cm X509KeyAlgorithm +.Sm off +.Ar x509v3-ecdsa-sha2-nistp384 , Ar ssh-sha384 , Ar ecdsa-sha2-nistp384 +.Sm on +.It +.Cm X509KeyAlgorithm +.Sm off +.Ar x509v3-ecdsa-sha2-nistp521 , Ar ssh-sha512 , Ar ecdsa-sha2-nistp521 +.Sm on +.El +.Pp +The default for certificates with Ed25519 keys is: +.Bl -item -offset indent -compact +.Cm X509KeyAlgorithm +.Sm off +.Ar x509v3-ssh-ed25519 , Ar none , Ar ssh-ed25519 +.Sm on +.El +.Pp +The default for certificates with RSA key is: +.Bl -item -offset indent -compact +.It +.Cm X509KeyAlgorithm +.Sm off +.Ar x509v3-rsa2048-sha256 , Ar rsa2048-sha256 , Ar rsa2048-sha256 +.Sm on +.It +.Cm X509KeyAlgorithm +.Sm off +.Ar x509v3-ssh-rsa , Ar rsa-sha1 , Ar ssh-rsa +.Sm on +.It +.Cm X509KeyAlgorithm +.Sm off +.Ar x509v3-sign-rsa , Ar rsa-sha1 +.Sm on +.It +.Cm X509KeyAlgorithm +.Sm off +.Ar x509v3-sign-rsa , Ar rsa-md5 +.Sm on +.El +.Pp +The default for certificates with DSA key is: +.Bl -item -offset indent -compact +.It +.Cm X509KeyAlgorithm +.Sm off +.Ar x509v3-ssh-dss , Ar dss-raw , Ar ssh-dss +.Sm on +.It +.Cm X509KeyAlgorithm +.Sm off +.Ar x509v3-sign-dss , Ar dss-asn1 +.Sm on +.It +.Cm X509KeyAlgorithm +.Sm off +.Ar x509v3-sign-dss , Ar dss-raw +.Sm on +.El +.Pp .It Cm XAuthLocation Specifies the full pathname of the .Xr xauth 1 @@ -2109,9 +2360,7 @@ .It %f The fingerprint of the server's host key. .It %H -The -.Pa known_hosts -hostname or address that is being searched for. +The known hosts hostname or address that is being searched for. .It %h The remote hostname. .It \%%I @@ -2162,6 +2411,7 @@ .Pp .Cm CertificateFile , .Cm ControlPath , +.Cm ForwardAgent , .Cm IdentityAgent , .Cm IdentityFile , .Cm KnownHostsCommand , @@ -2184,9 +2434,7 @@ accepts all tokens. .Pp .Cm ProxyCommand -and -.Cm ProxyJump -accept the tokens %%, %h, %n, %p, and %r. +accepts the tokens %%, %h, %n, %p, and %r. .Sh ENVIRONMENT VARIABLES Arguments to some keywords can be expanded at runtime from environment variables on the client by enclosing them in @@ -2230,7 +2478,7 @@ .Xr ssh 1 .Sh AUTHORS .An -nosplit -OpenSSH is a derivative of the original and free +PKIX-SSH is a derivative of the original and free ssh 1.2.12 release by .An Tatu Ylonen . .An Aaron Campbell , Bob Beck , Markus Friedl , @@ -2241,3 +2489,5 @@ created OpenSSH. .An Markus Friedl contributed the support for SSH protocol versions 1.5 and 2.0. +.An Roumen Petrov +contributed support for X.509 certificates. diff -ruN openssh-9.4p1/sshconnect2.c openssh-9.4p1+x509-14.2.1/sshconnect2.c --- openssh-9.4p1/sshconnect2.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/sshconnect2.c 2023-08-20 10:07:01.000000000 +0300 @@ -1,7 +1,8 @@ -/* $OpenBSD: sshconnect2.c,v 1.367 2023/08/01 08:15:04 dtucker Exp $ */ +/* $OpenBSD: sshconnect2.c,v 1.366 2023/03/09 07:11:05 dtucker Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * Copyright (c) 2008 Damien Miller. All rights reserved. + * Copyright (c) 2006-2022 Roumen Petrov. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -50,12 +51,13 @@ #include "xmalloc.h" #include "ssh.h" #include "ssh2.h" -#include "sshbuf.h" #include "packet.h" #include "compat.h" #include "cipher.h" -#include "sshkey.h" +#include "ssh-x509.h" +#include "ssh-xkalg.h" #include "kex.h" +#include "myproposal.h" #include "sshconnect.h" #include "authfile.h" #include "dh.h" @@ -68,20 +70,15 @@ #include "canohost.h" #include "msg.h" #include "pathnames.h" -#include "uidswap.h" #include "hostfile.h" #include "ssherr.h" #include "utf8.h" -#include "ssh-sk.h" -#include "sk-api.h" #ifdef GSSAPI #include "ssh-gss.h" #endif /* import */ -extern char *client_version_string; -extern char *server_version_string; extern Options options; /* @@ -95,74 +92,41 @@ static int verify_host_key_callback(struct sshkey *hostkey, struct ssh *ssh) { - int r; + struct kex *kex = ssh->kex; - if ((r = sshkey_check_rsa_length(hostkey, - options.required_rsa_size)) != 0) +#if 0 + /* NOTE: key size is validated on read, sign and verify */ + if (sshkey_check_length(host_key) != 0) fatal_r(r, "Bad server host key"); - if (verify_host_key(xxx_host, xxx_hostaddr, hostkey, +#endif + if (verify_host_key(xxx_host, xxx_hostaddr, kex->hostkey_alg, hostkey, xxx_conn_info) == -1) fatal("Host key verification failed."); return 0; } -/* Returns the first item from a comma-separated algorithm list */ -static char * -first_alg(const char *algs) -{ - char *ret, *cp; - - ret = xstrdup(algs); - if ((cp = strchr(ret, ',')) != NULL) - *cp = '\0'; - return ret; -} - static char * order_hostkeyalgs(char *host, struct sockaddr *hostaddr, u_short port, const struct ssh_conn_info *cinfo) { - char *oavail = NULL, *avail = NULL, *first = NULL, *last = NULL; - char *alg = NULL, *hostname = NULL, *ret = NULL, *best = NULL; + char *oavail, *avail, *first, *last, *alg, *hostname, *ret; size_t maxlen; - struct hostkeys *hostkeys = NULL; + struct hostkeys *hostkeys; int ktype; u_int i; + UNUSED(cinfo); /* Find all hostkeys for this hostname */ get_hostfile_hostname_ipaddr(host, hostaddr, port, &hostname, NULL); hostkeys = init_hostkeys(); for (i = 0; i < options.num_user_hostfiles; i++) load_hostkeys(hostkeys, hostname, options.user_hostfiles[i], 0); - for (i = 0; i < options.num_system_hostfiles; i++) { - load_hostkeys(hostkeys, hostname, - options.system_hostfiles[i], 0); - } - if (options.known_hosts_command != NULL) { + for (i = 0; i < options.num_system_hostfiles; i++) + load_hostkeys(hostkeys, hostname, options.system_hostfiles[i], 0); + if (options.known_hosts_command != NULL) load_hostkeys_command(hostkeys, options.known_hosts_command, "ORDER", cinfo, NULL, host); - } - /* - * If a plain public key exists that matches the type of the best - * preference HostkeyAlgorithms, then use the whole list as is. - * Note that we ignore whether the best preference algorithm is a - * certificate type, as sshconnect.c will downgrade certs to - * plain keys if necessary. - */ - best = first_alg(options.hostkeyalgorithms); - if (lookup_key_in_hostkeys_by_type(hostkeys, - sshkey_type_plain(sshkey_type_from_name(best)), - sshkey_ecdsa_nid_from_name(best), NULL)) { - debug3_f("have matching best-preference key type %s, " - "using HostkeyAlgorithms verbatim", best); - ret = xstrdup(options.hostkeyalgorithms); - goto out; - } - /* - * Otherwise, prefer the host key algorithms that match known keys - * while keeping the ordering of HostkeyAlgorithms as much as possible. - */ oavail = avail = xstrdup(options.hostkeyalgorithms); maxlen = strlen(avail) + 1; first = xmalloc(maxlen); @@ -176,37 +140,36 @@ strlcat(to, from, maxlen); \ } while (0) +{ int has_ca_mark = lookup_marker_in_hostkeys(hostkeys, MRK_CA); while ((alg = strsep(&avail, ",")) && *alg != '\0') { - if ((ktype = sshkey_type_from_name(alg)) == KEY_UNSPEC) + int subtype; + sshkey_types_from_name(alg, &ktype, &subtype); + if (ktype == KEY_UNSPEC) fatal_f("unknown alg %s", alg); /* * If we have a @cert-authority marker in known_hosts then * prefer all certificate algorithms. */ - if (sshkey_type_is_cert(ktype) && - lookup_marker_in_hostkeys(hostkeys, MRK_CA)) { + if (has_ca_mark && sshkey_type_is_cert(ktype)) { ALG_APPEND(first, alg); continue; } /* If the key appears in known_hosts then prefer it */ - if (lookup_key_in_hostkeys_by_type(hostkeys, - sshkey_type_plain(ktype), - sshkey_ecdsa_nid_from_name(alg), NULL)) { + if (lookup_key_in_hostkeys_by_types(hostkeys, + sshkey_type_plain(ktype), subtype, NULL)) { ALG_APPEND(first, alg); continue; } /* Otherwise, put it last */ ALG_APPEND(last, alg); } +} #undef ALG_APPEND xasprintf(&ret, "%s%s%s", first, (*first == '\0' || *last == '\0') ? "" : ",", last); if (*first != '\0') debug3_f("prefer hostkeyalgs: %s", first); - else - debug3_f("no algorithms matched; accept original"); - out: - free(best); + free(first); free(last); free(hostname); @@ -220,9 +183,10 @@ ssh_kex2(struct ssh *ssh, char *host, struct sockaddr *hostaddr, u_short port, const struct ssh_conn_info *cinfo) { - char *myproposal[PROPOSAL_MAX]; - char *s, *all_key, *hkalgs = NULL; - int r, use_known_hosts_order = 0; + char *myproposal[PROPOSAL_MAX] = { KEX_CLIENT }; + char *s, *prop_kex = NULL, *prop_enc = NULL, *prop_hostkey = NULL; + struct kex *kex; + int r; xxx_host = host; xxx_hostaddr = hostaddr; @@ -232,72 +196,77 @@ ssh_packet_set_rekey_limits(ssh, options.rekey_limit, options.rekey_interval); - /* - * If the user has not specified HostkeyAlgorithms, or has only - * appended or removed algorithms from that list then prefer algorithms - * that are in the list that are supported by known_hosts keys. - */ - if (options.hostkeyalgorithms == NULL || - options.hostkeyalgorithms[0] == '-' || - options.hostkeyalgorithms[0] == '+') - use_known_hosts_order = 1; - - /* Expand or fill in HostkeyAlgorithms */ - all_key = sshkey_alg_list(0, 0, 1, ','); - if ((r = kex_assemble_names(&options.hostkeyalgorithms, - kex_default_pk_alg(), all_key)) != 0) - fatal_fr(r, "kex_assemble_namelist"); - free(all_key); - if ((s = kex_names_cat(options.kex_algorithms, "ext-info-c")) == NULL) fatal_f("kex_names_cat"); - if (use_known_hosts_order) - hkalgs = order_hostkeyalgs(host, hostaddr, port, cinfo); - - kex_proposal_populate_entries(ssh, myproposal, s, options.ciphers, - options.macs, compression_alg_list(options.compression), - hkalgs ? hkalgs : options.hostkeyalgorithms); - - free(hkalgs); + myproposal[PROPOSAL_KEX_ALGS] = prop_kex = + compat_kex_proposal(ssh, s); + myproposal[PROPOSAL_ENC_ALGS_CTOS] = + myproposal[PROPOSAL_ENC_ALGS_STOC] = prop_enc = + xstrdup(options.ciphers); + myproposal[PROPOSAL_COMP_ALGS_CTOS] = + myproposal[PROPOSAL_COMP_ALGS_STOC] = + (char *)compression_alg_list(options.compression); + myproposal[PROPOSAL_MAC_ALGS_CTOS] = + myproposal[PROPOSAL_MAC_ALGS_STOC] = options.macs; + +{ /* finalize set of client option HostKeyAlgorithms */ + int user_prefered; + char *defalgs = default_hostkey_algorithms(); + + user_prefered = + options.hostkeyalgorithms != NULL && + options.hostkeyalgorithms[0] == '^'; + + if (options.hostkeyalgorithms != NULL) { + /* Assemble */ + char *allalgs = sshkey_alg_list(0, 0, 1, ','); + if (kex_assemble_names(&options.hostkeyalgorithms, + defalgs, allalgs) != 0) + fatal_f("kex_assemble_names failed"); + free(allalgs); + free(defalgs); + } else { + /* Enforce default */ + options.hostkeyalgorithms = defalgs; + } + if (user_prefered) + myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = prop_hostkey = + xstrdup(options.hostkeyalgorithms); + else + /* Prefer algorithms that we already have keys for */ + myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = prop_hostkey = + order_hostkeyalgs(host, hostaddr, port, cinfo); +} /* start key exchange */ if ((r = kex_setup(ssh, myproposal)) != 0) - fatal_r(r, "kex_setup"); -#ifdef WITH_OPENSSL - ssh->kex->kex[KEX_DH_GRP1_SHA1] = kex_gen_client; - ssh->kex->kex[KEX_DH_GRP14_SHA1] = kex_gen_client; - ssh->kex->kex[KEX_DH_GRP14_SHA256] = kex_gen_client; - ssh->kex->kex[KEX_DH_GRP16_SHA512] = kex_gen_client; - ssh->kex->kex[KEX_DH_GRP18_SHA512] = kex_gen_client; - ssh->kex->kex[KEX_DH_GEX_SHA1] = kexgex_client; - ssh->kex->kex[KEX_DH_GEX_SHA256] = kexgex_client; -# ifdef OPENSSL_HAS_ECC - ssh->kex->kex[KEX_ECDH_SHA2] = kex_gen_client; -# endif -#endif - ssh->kex->kex[KEX_C25519_SHA256] = kex_gen_client; - ssh->kex->kex[KEX_KEM_SNTRUP761X25519_SHA512] = kex_gen_client; - ssh->kex->verify_host_key=&verify_host_key_callback; + fatal_fr(r, "kex_setup"); + kex = ssh->kex; + kex_set_callbacks_client(kex); + kex->verify_host_key=&verify_host_key_callback; - ssh_dispatch_run_fatal(ssh, DISPATCH_BLOCK, &ssh->kex->done); + ssh_dispatch_run_fatal(ssh, DISPATCH_BLOCK, &kex->done); /* remove ext-info from the KEX proposals for rekeying */ - free(myproposal[PROPOSAL_KEX_ALGS]); myproposal[PROPOSAL_KEX_ALGS] = compat_kex_proposal(ssh, options.kex_algorithms); - if ((r = kex_prop2buf(ssh->kex->my, myproposal)) != 0) - fatal_r(r, "kex_prop2buf"); + if ((r = kex_prop2buf(kex->my, myproposal)) != 0) + fatal_fr(r, "kex_prop2buf"); -#ifdef DEBUG_KEXDH +#ifdef DEBUG_KEX /* send 1st encrypted/maced/compressed message */ if ((r = sshpkt_start(ssh, SSH2_MSG_IGNORE)) != 0 || - (r = sshpkt_put_cstring(ssh, "markus")) != 0 || + (r = sshpkt_put_cstring(ssh, "roumen")) != 0 || (r = sshpkt_send(ssh)) != 0 || (r = ssh_packet_write_wait(ssh)) != 0) fatal_fr(r, "send packet"); #endif - kex_proposal_free_entries(myproposal); + /* Free only parts of proposal that were dynamically allocated here. */ + free(s); + free(prop_kex); + free(prop_enc); + free(prop_hostkey); } /* @@ -313,6 +282,7 @@ TAILQ_ENTRY(identity) next; int agent_fd; /* >=0 if agent supports key */ struct sshkey *key; /* public/private key */ + const char *pkalg; /* public key algorithm (static) */ char *filename; /* comment for agent-only keys */ int tried; int isprivate; /* key points to the private key */ @@ -330,6 +300,7 @@ char *authlist; #ifdef GSSAPI /* gssapi */ + OM_uint32 gss_minor_status; gss_OID_set gss_supported_mechs; u_int mech_tried; #endif @@ -338,8 +309,8 @@ int agent_fd; /* hostbased */ Sensitive *sensitive; - char *oktypes, *ktypes; - const char *active_ktype; + char *pkalg_list; + const char *active_pkalg; /* kbd-interactive */ int info_req_seen; int attempt_kbdint; @@ -451,11 +422,12 @@ authctxt.authlist = NULL; authctxt.methoddata = NULL; authctxt.sensitive = sensitive; - authctxt.active_ktype = authctxt.oktypes = authctxt.ktypes = NULL; + authctxt.pkalg_list = NULL; + authctxt.active_pkalg = NULL; authctxt.info_req_seen = 0; authctxt.attempt_kbdint = 0; authctxt.attempt_passwd = 0; -#if GSSAPI +#ifdef GSSAPI authctxt.gss_supported_mechs = NULL; authctxt.mech_tried = 0; #endif @@ -497,6 +469,8 @@ { int r; + UNUSED(type); + UNUSED(seq); if (ssh_packet_remaining(ssh) > 0) { char *reply; @@ -524,9 +498,9 @@ } static int -input_userauth_ext_info(int type, u_int32_t seqnr, struct ssh *ssh) +input_userauth_ext_info(int type, u_int32_t seq, struct ssh *ssh) { - return kex_input_ext_info(type, seqnr, ssh); + return kex_input_ext_info(type, seq, ssh); } void @@ -570,6 +544,8 @@ static int input_userauth_error(int type, u_int32_t seq, struct ssh *ssh) { + UNUSED(seq); + UNUSED(ssh); fatal_f("bad message during authentication: type %d", type); return 0; } @@ -581,9 +557,11 @@ size_t len; int r; + UNUSED(type); + UNUSED(seq); debug3_f("entering"); if ((r = sshpkt_get_cstring(ssh, &msg, &len)) != 0 || - (r = sshpkt_get_cstring(ssh, NULL, NULL)) != 0) + (r = sshpkt_get_cstring(ssh, NULL/*language*/, NULL)) != 0) goto out; if (len > 0 && options.log_level >= SYSLOG_LEVEL_INFO) fmprintf(stderr, "%s", msg); @@ -598,6 +576,8 @@ { Authctxt *authctxt = ssh->authctxt; + UNUSED(type); + UNUSED(seq); if (authctxt == NULL) fatal_f("no authentication context"); free(authctxt->authlist); @@ -610,21 +590,6 @@ return 0; } -#if 0 -static int -input_userauth_success_unexpected(int type, u_int32_t seq, struct ssh *ssh) -{ - Authctxt *authctxt = ssh->authctxt; - - if (authctxt == NULL) - fatal_f("no authentication context"); - - fatal("Unexpected authentication success during %s.", - authctxt->method->name); - return 0; -} -#endif - static int input_userauth_failure(int type, u_int32_t seq, struct ssh *ssh) { @@ -632,8 +597,10 @@ char *authlist = NULL; u_char partial; + UNUSED(type); + UNUSED(seq); if (authctxt == NULL) - fatal("input_userauth_failure: no authentication context"); + fatal_f("no authentication context"); if (sshpkt_get_cstring(ssh, &authlist, NULL) != 0 || sshpkt_get_u8(ssh, &partial) != 0 || @@ -659,27 +626,22 @@ * Format an identity for logging including filename, key type, fingerprint * and location (agent, etc.). Caller must free. */ -static char * +static const char * format_identity(Identity *id) { char *fp = NULL, *ret = NULL; - const char *note = ""; if (id->key != NULL) { fp = sshkey_fingerprint(id->key, options.fingerprint_hash, SSH_FP_DEFAULT); } - if (id->key) { - if ((id->key->flags & SSHKEY_FLAG_EXT) != 0) - note = " token"; - else if (sshkey_is_sk(id->key)) - note = " authenticator"; - } - xasprintf(&ret, "%s %s%s%s%s%s%s", + xasprintf(&ret, "'%s' %s %s%s%s%s%s%s", + id->pkalg ? id->pkalg : "*", id->filename, id->key ? sshkey_type(id->key) : "", id->key ? " " : "", fp ? fp : "", - id->userprovided ? " explicit" : "", note, + id->userprovided ? " explicit" : "", + (id->key && (id->key->flags & SSHKEY_FLAG_EXT)) ? " token" : "", id->agent_fd != -1 ? " agent" : ""); free(fp); return ret; @@ -693,12 +655,14 @@ Identity *id = NULL; int pktype, found = 0, sent = 0; size_t blen; - char *pkalg = NULL, *fp = NULL, *ident = NULL; + char *pkalg = NULL; u_char *pkblob = NULL; int r; + UNUSED(type); + UNUSED(seq); if (authctxt == NULL) - fatal("input_userauth_pk_ok: no authentication context"); + fatal_f("no authentication context"); if ((r = sshpkt_get_cstring(ssh, &pkalg, NULL)) != 0 || (r = sshpkt_get_string(ssh, &pkblob, &blen)) != 0 || @@ -709,12 +673,12 @@ debug_f("server sent unknown pkalg %s", pkalg); goto done; } - if ((r = sshkey_from_blob(pkblob, blen, &key)) != 0) { + if ((r = Xkey_from_blob(pkalg, pkblob, blen, &key)) != 0) { debug_r(r, "no key from blob. pkalg %s", pkalg); goto done; } if (key->type != pktype) { - error("input_userauth_pk_ok: type mismatch " + error_f("type mismatch " "for decoded key (received %d, expected %d)", key->type, pktype); goto done; @@ -732,20 +696,21 @@ } } if (!found || id == NULL) { - fp = sshkey_fingerprint(key, options.fingerprint_hash, + char *fp = sshkey_fingerprint(key, options.fingerprint_hash, SSH_FP_DEFAULT); error_f("server replied with unknown key: %s %s", sshkey_type(key), fp == NULL ? "" : fp); + free(fp); goto done; } - ident = format_identity(id); +{ const char *ident = format_identity(id); debug("Server accepts key: %s", ident); + free((void*)ident); +} sent = sign_and_send_pubkey(ssh, id); r = 0; done: sshkey_free(key); - free(ident); - free(fp); free(pkalg); free(pkblob); @@ -761,7 +726,6 @@ { Authctxt *authctxt = (Authctxt *)ssh->authctxt; Gssctxt *gssctxt = NULL; - OM_uint32 min; int r, ok = 0; gss_OID mech = NULL; @@ -769,7 +733,7 @@ * once. */ if (authctxt->gss_supported_mechs == NULL) - gss_indicate_mechs(&min, &authctxt->gss_supported_mechs); + gss_indicate_mechs(&authctxt->gss_minor_status, &authctxt->gss_supported_mechs); /* Check to see whether the mechanism is usable before we offer it */ while (authctxt->mech_tried < authctxt->gss_supported_mechs->count && @@ -816,13 +780,15 @@ userauth_gssapi_cleanup(struct ssh *ssh) { Authctxt *authctxt = (Authctxt *)ssh->authctxt; - Gssctxt *gssctxt = (Gssctxt *)authctxt->methoddata; - ssh_gssapi_delete_ctx(&gssctxt); - authctxt->methoddata = NULL; - - free(authctxt->gss_supported_mechs); + gss_release_oid_set(&authctxt->gss_minor_status, &authctxt->gss_supported_mechs); authctxt->gss_supported_mechs = NULL; + +{ + Gssctxt *gssctxt = (Gssctxt *)authctxt->methoddata; + authctxt->methoddata = NULL; + ssh_gssapi_delete_ctx(&gssctxt); +} } static OM_uint32 @@ -901,8 +867,10 @@ u_char *oidv = NULL; int r; + UNUSED(type); + UNUSED(plen); if (authctxt == NULL) - fatal("input_gssapi_response: no authentication context"); + fatal_f("no authentication context"); gssctxt = authctxt->methoddata; /* Setup our OID */ @@ -946,8 +914,10 @@ OM_uint32 status; int r; + UNUSED(type); + UNUSED(plen); if (authctxt == NULL) - fatal("input_gssapi_response: no authentication context"); + fatal_f("no authentication context"); if ((r = sshpkt_get_string(ssh, &p, &len)) != 0 || (r = sshpkt_get_end(ssh)) != 0) @@ -980,8 +950,10 @@ size_t len; int r; + UNUSED(type); + UNUSED(plen); if (authctxt == NULL) - fatal("input_gssapi_response: no authentication context"); + fatal_f("no authentication context"); gssctxt = authctxt->methoddata; if ((r = sshpkt_get_string(ssh, &p, &len)) != 0 || @@ -1006,19 +978,19 @@ input_gssapi_error(int type, u_int32_t plen, struct ssh *ssh) { char *msg = NULL; - char *lang = NULL; int r; + UNUSED(type); + UNUSED(plen); if ((r = sshpkt_get_u32(ssh, NULL)) != 0 || /* maj */ (r = sshpkt_get_u32(ssh, NULL)) != 0 || /* min */ (r = sshpkt_get_cstring(ssh, &msg, NULL)) != 0 || - (r = sshpkt_get_cstring(ssh, &lang, NULL)) != 0) + (r = sshpkt_get_cstring(ssh, NULL/*language*/, NULL)) != 0) goto out; r = sshpkt_get_end(ssh); debug("Server GSSAPI Error:\n%s", msg); out: free(msg); - free(lang); return r; } #endif /* GSSAPI */ @@ -1080,7 +1052,7 @@ * parse PASSWD_CHANGEREQ, prompt user and send SSH2_MSG_USERAUTH_REQUEST */ static int -input_userauth_passwd_changereq(int type, u_int32_t seqnr, struct ssh *ssh) +input_userauth_passwd_changereq(int type, u_int32_t seq, struct ssh *ssh) { Authctxt *authctxt = ssh->authctxt; char *info = NULL, *lang = NULL, *password = NULL, *retype = NULL; @@ -1088,11 +1060,12 @@ const char *host; int r; - debug2("input_userauth_passwd_changereq"); + UNUSED(type); + UNUSED(seq); + debug2_f("entering"); if (authctxt == NULL) - fatal("input_userauth_passwd_changereq: " - "no authentication context"); + fatal_f("no authentication context"); host = options.host_key_alias ? options.host_key_alias : authctxt->host; if ((r = sshpkt_get_cstring(ssh, &info, NULL)) != 0 || @@ -1153,79 +1126,18 @@ return r; } -/* - * Select an algorithm for publickey signatures. - * Returns algorithm (caller must free) or NULL if no mutual algorithm found. - * - * Call with ssh==NULL to ignore server-sig-algs extension list and - * only attempt with the key's base signature type. - */ -static char * -key_sig_algorithm(struct ssh *ssh, const struct sshkey *key) -{ - char *allowed, *oallowed, *cp, *tmp, *alg = NULL; - const char *server_sig_algs; - - /* - * The signature algorithm will only differ from the key algorithm - * for RSA keys/certs and when the server advertises support for - * newer (SHA2) algorithms. - */ - if (ssh == NULL || ssh->kex->server_sig_algs == NULL || - (key->type != KEY_RSA && key->type != KEY_RSA_CERT) || - (key->type == KEY_RSA_CERT && (ssh->compat & SSH_BUG_SIGTYPE))) { - /* Filter base key signature alg against our configuration */ - return match_list(sshkey_ssh_name(key), - options.pubkey_accepted_algos, NULL); - } - - /* - * Workaround OpenSSH 7.4 bug: this version supports RSA/SHA-2 but - * fails to advertise it via SSH2_MSG_EXT_INFO. - */ - server_sig_algs = ssh->kex->server_sig_algs; - if (key->type == KEY_RSA && (ssh->compat & SSH_BUG_SIGTYPE74)) - server_sig_algs = "rsa-sha2-256,rsa-sha2-512"; - - /* - * For RSA keys/certs, since these might have a different sig type: - * find the first entry in PubkeyAcceptedAlgorithms of the right type - * that also appears in the supported signature algorithms list from - * the server. - */ - oallowed = allowed = xstrdup(options.pubkey_accepted_algos); - while ((cp = strsep(&allowed, ",")) != NULL) { - if (sshkey_type_from_name(cp) != key->type) - continue; - tmp = match_list(sshkey_sigalg_by_name(cp), - server_sig_algs, NULL); - if (tmp != NULL) - alg = xstrdup(cp); - free(tmp); - if (alg != NULL) - break; - } - free(oallowed); - return alg; -} - static int -identity_sign(struct identity *id, u_char **sigp, size_t *lenp, - const u_char *data, size_t datalen, u_int compat, const char *alg) +identity_sign(struct identity *id, ssh_sign_ctx *id_ctx, + u_char **sigp, size_t *lenp, const u_char *data, size_t datalen) { - struct sshkey *sign_key = NULL, *prv = NULL; - int is_agent = 0, retried = 0, r = SSH_ERR_INTERNAL_ERROR; - struct notifier_ctx *notifier = NULL; - char *fp = NULL, *pin = NULL, *prompt = NULL; - - *sigp = NULL; - *lenp = 0; + struct sshkey *prv = NULL; + int r; + ssh_sign_ctx ctx = { id_ctx->alg, id->key, id_ctx->compat, NULL, NULL }; /* The agent supports this key. */ - if (id->key != NULL && id->agent_fd != -1) { - return ssh_agent_sign(id->agent_fd, id->key, sigp, lenp, - data, datalen, alg, compat); - } + if (id->key != NULL && id->agent_fd != -1) + return Xssh_agent_sign(id->agent_fd, &ctx, + sigp, lenp, data, datalen); /* * We have already loaded the private key or the private key is @@ -1233,8 +1145,7 @@ */ if (id->key != NULL && (id->isprivate || (id->key->flags & SSHKEY_FLAG_EXT))) { - sign_key = id->key; - is_agent = 1; + /* use passed identity */ } else { /* Load the private key from the file. */ if ((prv = load_identity_file(id)) == NULL) @@ -1245,53 +1156,16 @@ r = SSH_ERR_KEY_NOT_FOUND; goto out; } - sign_key = prv; - } - retry_pin: - /* Prompt for touch for non-agent FIDO keys that request UP */ - if (!is_agent && sshkey_is_sk(sign_key) && - (sign_key->sk_flags & SSH_SK_USER_PRESENCE_REQD)) { - /* XXX should batch mode just skip these? */ - if ((fp = sshkey_fingerprint(sign_key, - options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL) - fatal_f("fingerprint failed"); - notifier = notify_start(options.batch_mode, - "Confirm user presence for key %s %s", - sshkey_type(sign_key), fp); - free(fp); - } - if ((r = sshkey_sign(sign_key, sigp, lenp, data, datalen, - alg, options.sk_provider, pin, compat)) != 0) { - debug_fr(r, "sshkey_sign"); - if (!retried && pin == NULL && !is_agent && - sshkey_is_sk(sign_key) && - r == SSH_ERR_KEY_WRONG_PASSPHRASE) { - notify_complete(notifier, NULL); - notifier = NULL; - xasprintf(&prompt, "Enter PIN for %s key %s: ", - sshkey_type(sign_key), id->filename); - pin = read_passphrase(prompt, 0); - retried = 1; - goto retry_pin; - } - goto out; + if (id->key != NULL) + prv->type = id->key->type; + ctx.key = prv; } - /* - * PKCS#11 tokens may not support all signature algorithms, - * so check what we get back. - */ - if ((r = sshkey_check_sigtype(*sigp, *lenp, alg)) != 0) { - debug_fr(r, "sshkey_check_sigtype"); - goto out; - } - /* success */ - r = 0; - out: - free(prompt); - if (pin != NULL) - freezero(pin, strlen(pin)); - notify_complete(notifier, r == 0 ? "User presence confirmed" : NULL); + r = Xkey_sign(&ctx, sigp, lenp, data, datalen); + if (r == 0) + r = Xkey_check_sigalg(&ctx, *sigp, *lenp); + +out: sshkey_free(prv); return r; } @@ -1319,27 +1193,19 @@ sign_and_send_pubkey(struct ssh *ssh, Identity *id) { Authctxt *authctxt = (Authctxt *)ssh->authctxt; + const char *pkalg = id->pkalg; struct sshbuf *b = NULL; Identity *private_id, *sign_id = NULL; u_char *signature = NULL; size_t slen = 0, skip = 0; - int r, fallback_sigtype, sent = 0; - char *alg = NULL, *fp = NULL; - const char *loc = "", *method = "publickey"; - int hostbound = 0; - - /* prefer host-bound pubkey signatures if supported by server */ - if ((ssh->kex->flags & KEX_HAS_PUBKEY_HOSTBOUND) != 0 && - (options.pubkey_authentication & SSH_PUBKEY_AUTH_HBOUND) != 0) { - hostbound = 1; - method = "publickey-hostbound-v00@openssh.com"; - } + int r, sent = 0; + char *fp = NULL; if ((fp = sshkey_fingerprint(id->key, options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL) return 0; - debug3_f("using %s with %s %s", method, sshkey_type(id->key), fp); + debug3_f("%s %s", pkalg, fp); /* * If the key is an certificate, try to find a matching private key @@ -1392,22 +1258,10 @@ if (sign_id == NULL) sign_id = id; - /* assemble and sign data */ - for (fallback_sigtype = 0; fallback_sigtype <= 1; fallback_sigtype++) { - free(alg); - slen = 0; - signature = NULL; - if ((alg = key_sig_algorithm(fallback_sigtype ? NULL : ssh, - id->key)) == NULL) { - error_f("no mutual signature supported"); - goto out; - } - debug3_f("signing using %s %s", alg, fp); - - sshbuf_free(b); + while (1) { /*synchronize indent*/ if ((b = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); - if (ssh->compat & SSH_OLD_SESSIONID) { + if (ssh_compat_fellows(ssh, SSH_OLD_SESSIONID)) { if ((r = sshbuf_putb(b, ssh->kex->session_id)) != 0) fatal_fr(r, "sshbuf_putb"); } else { @@ -1419,40 +1273,25 @@ if ((r = sshbuf_put_u8(b, SSH2_MSG_USERAUTH_REQUEST)) != 0 || (r = sshbuf_put_cstring(b, authctxt->server_user)) != 0 || (r = sshbuf_put_cstring(b, authctxt->service)) != 0 || - (r = sshbuf_put_cstring(b, method)) != 0 || + (r = sshbuf_put_cstring(b, authctxt->method->name)) != 0 || (r = sshbuf_put_u8(b, 1)) != 0 || - (r = sshbuf_put_cstring(b, alg)) != 0 || - (r = sshkey_puts(id->key, b)) != 0) { + (r = sshbuf_put_cstring(b, pkalg)) != 0 || + (r = Xkey_puts(pkalg, id->key, b)) != 0) { fatal_fr(r, "assemble signed data"); } - if (hostbound) { - if (ssh->kex->initial_hostkey == NULL) { - fatal_f("internal error: initial hostkey " - "not recorded"); - } - if ((r = sshkey_puts(ssh->kex->initial_hostkey, b)) != 0) - fatal_fr(r, "assemble %s hostkey", method); - } + /* generate signature */ - r = identity_sign(sign_id, &signature, &slen, - sshbuf_ptr(b), sshbuf_len(b), ssh->compat, alg); + { ssh_sign_ctx ctx = { pkalg, NULL, &ssh->compat, NULL, NULL }; + + r = identity_sign(sign_id, &ctx, &signature, &slen, sshbuf_ptr(b), sshbuf_len(b)); + } if (r == 0) break; - else if (r == SSH_ERR_KEY_NOT_FOUND) + if (r == SSH_ERR_KEY_NOT_FOUND) goto out; /* soft failure */ - else if (r == SSH_ERR_SIGN_ALG_UNSUPPORTED && - !fallback_sigtype) { - if (sign_id->agent_fd != -1) - loc = "agent "; - else if ((sign_id->key->flags & SSHKEY_FLAG_EXT) != 0) - loc = "token "; - logit("%skey %s %s returned incorrect signature type", - loc, sshkey_type(id->key), fp); - continue; - } error_fr(r, "signing failed for %s \"%s\"%s", - sshkey_type(sign_id->key), sign_id->filename, - id->agent_fd != -1 ? " from agent" : ""); + pkalg, sign_id->filename, + id->agent_fd != -1 ? " from agent" : ""); goto out; } if (slen == 0 || signature == NULL) /* shouldn't happen */ @@ -1480,7 +1319,6 @@ out: free(fp); - free(alg); sshbuf_free(b); freezero(signature, slen); return sent; @@ -1490,18 +1328,22 @@ send_pubkey_test(struct ssh *ssh, Identity *id) { Authctxt *authctxt = (Authctxt *)ssh->authctxt; + const char *pkalg = id->pkalg; u_char *blob = NULL; - char *alg = NULL; size_t bloblen; u_int have_sig = 0; int sent = 0, r; - if ((alg = key_sig_algorithm(ssh, id->key)) == NULL) { - debug_f("no mutual signature algorithm"); - goto out; - } + debug3_f("%s", pkalg); + + /* Keys stored in secure token does not have chain if is used + * configuration with IdentityFile pointing to public part. + * Usually such configuration is used with IdentitiesOnly set + * to yes to restrict list of keys that client will try. + */ + x509key_prepare_chain(pkalg, id->key); - if ((r = sshkey_to_blob(id->key, &blob, &bloblen)) != 0) { + if ((r = Xkey_to_blob(pkalg, id->key, &blob, &bloblen)) != 0) { /* we cannot handle this key */ debug3_f("cannot handle key"); goto out; @@ -1514,14 +1356,13 @@ (r = sshpkt_put_cstring(ssh, authctxt->service)) != 0 || (r = sshpkt_put_cstring(ssh, authctxt->method->name)) != 0 || (r = sshpkt_put_u8(ssh, have_sig)) != 0 || - (r = sshpkt_put_cstring(ssh, alg)) != 0 || + (r = sshpkt_put_cstring(ssh, pkalg)) != 0 || (r = sshpkt_put_string(ssh, blob, bloblen)) != 0 || (r = sshpkt_send(ssh)) != 0) fatal_fr(r, "send packet"); sent = 1; out: - free(alg); free(blob); return sent; } @@ -1534,14 +1375,25 @@ int r, quit = 0, i; struct stat st; - if (stat(id->filename, &st) == -1) { +{ int external = ( +#ifdef USE_OPENSSL_ENGINE + (strncmp(id->filename, "engine:", 7) == 0) || +#endif +#ifdef USE_OPENSSL_STORE2 + (strncmp(id->filename, "store:", 6) == 0) || +#endif + 0 + ); + if (!external && + stat(id->filename, &st) == -1) { do_log2(id->userprovided ? SYSLOG_LEVEL_INFO : SYSLOG_LEVEL_DEBUG3, "no such identity: %s: %s", id->filename, strerror(errno)); return NULL; } +} snprintf(prompt, sizeof prompt, - "Enter passphrase for key '%.100s': ", id->filename); + "Enter passphrase for key '%.400s': ", id->filename); for (i = 0; i <= options.number_of_password_prompts; i++) { if (i == 0) passphrase = ""; @@ -1553,7 +1405,7 @@ break; } } - switch ((r = sshkey_load_private_type(KEY_UNSPEC, id->filename, + switch ((r = sshkey_load_private(id->filename, passphrase, &private, &comment))) { case 0: break; @@ -1577,21 +1429,15 @@ quit = 1; break; } - if (private != NULL && sshkey_is_sk(private) && - options.sk_provider == NULL) { - debug("key \"%s\" is an authenticator-hosted key, " - "but no provider specified", id->filename); - sshkey_free(private); - private = NULL; - quit = 1; - } - if (!quit && (r = sshkey_check_rsa_length(private, - options.required_rsa_size)) != 0) { - debug_fr(r, "Skipping key %s", id->filename); + #if 0 + /* NOTE: key size is validated on read, sign and verify */ + if (!quit && (r = sshkey_check_length(private)) != 0) { + debug_r(r, "skipping key %s", id->filename); sshkey_free(private); private = NULL; quit = 1; } + #endif if (!quit && private != NULL && id->agent_fd == -1 && !(id->key && id->isprivate)) maybe_add_key_to_agent(id->filename, private, comment, @@ -1605,66 +1451,6 @@ return private; } -static int -key_type_allowed_by_config(struct sshkey *key) -{ - if (match_pattern_list(sshkey_ssh_name(key), - options.pubkey_accepted_algos, 0) == 1) - return 1; - - /* RSA keys/certs might be allowed by alternate signature types */ - switch (key->type) { - case KEY_RSA: - if (match_pattern_list("rsa-sha2-512", - options.pubkey_accepted_algos, 0) == 1) - return 1; - if (match_pattern_list("rsa-sha2-256", - options.pubkey_accepted_algos, 0) == 1) - return 1; - break; - case KEY_RSA_CERT: - if (match_pattern_list("rsa-sha2-512-cert-v01@openssh.com", - options.pubkey_accepted_algos, 0) == 1) - return 1; - if (match_pattern_list("rsa-sha2-256-cert-v01@openssh.com", - options.pubkey_accepted_algos, 0) == 1) - return 1; - break; - } - return 0; -} - -/* obtain a list of keys from the agent */ -static int -get_agent_identities(struct ssh *ssh, int *agent_fdp, - struct ssh_identitylist **idlistp) -{ - int r, agent_fd; - struct ssh_identitylist *idlist; - - if ((r = ssh_get_authentication_socket(&agent_fd)) != 0) { - if (r != SSH_ERR_AGENT_NOT_PRESENT) - debug_fr(r, "ssh_get_authentication_socket"); - return r; - } - if ((r = ssh_agent_bind_hostkey(agent_fd, ssh->kex->initial_hostkey, - ssh->kex->session_id, ssh->kex->initial_sig, 0)) == 0) - debug_f("bound agent to hostkey"); - else - debug2_fr(r, "ssh_agent_bind_hostkey"); - - if ((r = ssh_fetch_identitylist(agent_fd, &idlist)) != 0) { - debug_fr(r, "ssh_fetch_identitylist"); - close(agent_fd); - return r; - } - /* success */ - *agent_fdp = agent_fd; - *idlistp = idlist; - debug_f("agent returned %zu keys", idlist->nkeys); - return 0; -} - /* * try keys in the following order: * 1. certificates listed in the config file @@ -1682,8 +1468,9 @@ int agent_fd = -1, i, r, found; size_t j; struct ssh_identitylist *idlist; - char *ident; + UNUSED(ssh); + debug2("preparing keys"); TAILQ_INIT(&agent); /* keys from the agent */ TAILQ_INIT(&files); /* keys from the config file */ preferred = &authctxt->keys; @@ -1692,18 +1479,8 @@ /* list of keys stored in the filesystem and PKCS#11 */ for (i = 0; i < options.num_identity_files; i++) { key = options.identity_keys[i]; - if (key && key->cert && - key->cert->type != SSH2_CERT_TYPE_USER) { - debug_f("ignoring certificate %s: not a user " - "certificate", options.identity_files[i]); - continue; - } - if (key && sshkey_is_sk(key) && options.sk_provider == NULL) { - debug_f("ignoring authenticator-hosted key %s as no " - "SecurityKeyProvider has been specified", - options.identity_files[i]); + if (key && key->cert && key->cert->type != SSH2_CERT_TYPE_USER) continue; - } options.identity_keys[i] = NULL; id = xcalloc(1, sizeof(*id)); id->agent_fd = -1; @@ -1716,18 +1493,8 @@ for (i = 0; i < options.num_certificate_files; i++) { key = options.certificates[i]; if (!sshkey_is_cert(key) || key->cert == NULL || - key->cert->type != SSH2_CERT_TYPE_USER) { - debug_f("ignoring certificate %s: not a user " - "certificate", options.identity_files[i]); - continue; - } - if (key && sshkey_is_sk(key) && options.sk_provider == NULL) { - debug_f("ignoring authenticator-hosted key " - "certificate %s as no " - "SecurityKeyProvider has been specified", - options.identity_files[i]); + key->cert->type != SSH2_CERT_TYPE_USER) continue; - } id = xcalloc(1, sizeof(*id)); id->agent_fd = -1; id->key = key; @@ -1736,14 +1503,23 @@ TAILQ_INSERT_TAIL(preferred, id, next); } /* list of keys supported by the agent */ - if ((r = get_agent_identities(ssh, &agent_fd, &idlist)) == 0) { + if ((r = ssh_get_authentication_socket(&agent_fd)) != 0) { + if (r != SSH_ERR_AGENT_NOT_PRESENT) + error_fr(r, "ssh_get_authentication_socket"); + } else if ((r = ssh_fetch_identitylist(agent_fd, &idlist)) != 0) { + if (r != SSH_ERR_AGENT_NO_IDENTITIES) + error_fr(r, "ssh_fetch_identitylist"); + close(agent_fd); + } else { for (j = 0; j < idlist->nkeys; j++) { - if ((r = sshkey_check_rsa_length(idlist->keys[j], - options.required_rsa_size)) != 0) { - debug_fr(r, "ignoring %s agent key", + #if 0 + /* NOTE: key size is validated on read, sign and verify */ + if ((r = sshkey_check_length(idlist->keys[j])) != 0) { + debug_r(r, "ignoring %s agent key", sshkey_ssh_name(idlist->keys[j])); continue; } + #endif found = 0; TAILQ_FOREACH(id, &files, next) { /* @@ -1798,24 +1574,10 @@ } /* append remaining keys from the config file */ TAILQ_CONCAT(preferred, &files, next); - /* finally, filter by PubkeyAcceptedAlgorithms */ - TAILQ_FOREACH_SAFE(id, preferred, next, id2) { - if (id->key != NULL && !key_type_allowed_by_config(id->key)) { - debug("Skipping %s key %s - " - "corresponding algo not in PubkeyAcceptedAlgorithms", - sshkey_ssh_name(id->key), id->filename); - TAILQ_REMOVE(preferred, id, next); - sshkey_free(id->key); - free(id->filename); - memset(id, 0, sizeof(*id)); - continue; - } - } - /* List the keys we plan on using */ - TAILQ_FOREACH_SAFE(id, preferred, next, id2) { - ident = format_identity(id); + TAILQ_FOREACH(id, preferred, next) { + const char *ident = format_identity(id); debug("Will attempt key: %s", ident); - free(ident); + free((void*)ident); } debug2_f("done"); } @@ -1848,13 +1610,165 @@ id->tried = 0; } +static void +set_keytype(struct sshkey *k, int kt) { + const char *n1, *n2; + + if (k->type == kt) return; + + /* sshkey_ssh_name returns pointer to static */ + n1 = sshkey_ssh_name(k); + k->type = kt; + n2 = sshkey_ssh_name(k); + verbose("Offering key-type '%s', original was '%s'", n2, n1); +} + +static inline int +pkalg_match(const char *pkalg, const char *pattern) { + if (pattern == NULL) return 1; /* NULL match all, i.e. like '*' */ + return match_pattern_list(pkalg, pattern, 0) == 1; +} + +static int +try_identity(struct ssh *ssh, Identity *id) +{ + struct sshkey *key; + struct kex *kex; + int kt; + const char *pkalg; + + if (ssh == NULL) return 0; + if (id == NULL) return 0; + key = id->key; + if (key == NULL) return 0; + + kex = ssh->kex; + kt = key->type; + + if (!sshkey_is_cert(key)) goto x509_cert; + +{ /* custom certificates: + * Follow broken OpenBSD implementation - extension that list + * supported public key algorithms is not correct. In + * consequence we cannot search into list offered by server + * as custom certificate algorithms are not listed at all! + * As work around we will check for respective 'plain' + * algorithms. + * On top on this version 7.8 is first that implements + * RSA-SHA2 algorithms for custom certificates, i.e. + * this requires specific processing. + */ + const char *pkalg0; + + if ((key->type == KEY_RSA_CERT) && + !ssh_compat_fellows(ssh, SSH_BUG_SIGTYPE)) { + pkalg = "rsa-sha2-256-cert-v01@openssh.com"; + pkalg0 = "rsa-sha2-256"; + if (pkalg_match(pkalg, options.pubkey_algorithms) && + pkalg_match(pkalg0, kex->pkalgs)) + goto cust_cert_done; + + pkalg = "rsa-sha2-512-cert-v01@openssh.com"; + pkalg0 = "rsa-sha2-512"; + if (pkalg_match(pkalg, options.pubkey_algorithms) && + pkalg_match(pkalg0, kex->pkalgs)) + goto cust_cert_done; + } + + pkalg = sshkey_ssh_name(key); + pkalg0 = sshkey_ssh_name_plain(key); + if (pkalg_match(pkalg, options.pubkey_algorithms) && + pkalg_match(pkalg0, kex->pkalgs)) + goto cust_cert_done; + + return 0; + +cust_cert_done: + id->pkalg = pkalg; + return 1; +} + +x509_cert: + if (!sshkey_is_x509(key)) goto plain; + +{ /* try "X.509" algorithms only */ + const SSHX509KeyAlgs *xkalg; + int loc; + int k = 0, frms[3]; + + if (kex->pkalgs != NULL) { + /* prefer RFC6187 algorithms if algorithm extension is available */ + frms[0] = X509FORMAT_RFC6187; + frms[1] = X509FORMAT_LEGACY; + frms[2] = -1; + } else { + frms[0] = X509FORMAT_FIRSTMATCH; + frms[1] = -1; + } + while (frms[k] != -1) { + for ( + loc = ssh_xkalg_keyfrmind(key, frms[k], &xkalg, -1); + loc >= 0; + loc = ssh_xkalg_keyfrmind(key, frms[k], &xkalg, loc) + ) { + pkalg = xkalg->name; + + if (!pkalg_match(pkalg, options.pubkey_algorithms)) + continue; + + if (!pkalg_match(pkalg, kex->pkalgs)) + continue; + + id->pkalg = pkalg; + return 1; + } + k++; + } +} + +plain: /* try "plain" key algorithm */ + kt = sshkey_type_plain(kt); +#ifdef HAVE_EVP_SHA256 + if (kt == KEY_RSA && (kex->pkalgs != NULL)) { + /* server must announce support for following algorithms */ + pkalg = "rsa-sha2-256"; + if ((match_pattern_list(pkalg, kex->pkalgs, 0) == 1) && + pkalg_match(pkalg, options.pubkey_algorithms)) + goto done; + + pkalg = "rsa-sha2-512"; + if ((match_pattern_list(pkalg, kex->pkalgs, 0) == 1) && + pkalg_match(pkalg, options.pubkey_algorithms)) + goto done; + } +#endif /*def HAVE_EVP_SHA256*/ + + pkalg = sshkey_ssh_name_plain(key); + if (!pkalg_match(pkalg, options.pubkey_algorithms)) { + debug("Skipped %s key %s as algorithm %s is not allowed by configuration", + sshkey_type(key), id->filename, pkalg); + return 0; + } + + if (!pkalg_match(pkalg, kex->pkalgs)) { + debug("Skipped %s key %s as algorithm %s is not accepted by peer", + sshkey_type(key), id->filename, pkalg); + return 0; + } + +done: + set_keytype(id->key, kt); + + id->pkalg = pkalg; + return 1; +} + static int userauth_pubkey(struct ssh *ssh) { Authctxt *authctxt = (Authctxt *)ssh->authctxt; Identity *id; int sent = 0; - char *ident; while ((id = TAILQ_FIRST(&authctxt->keys))) { if (id->tried++) @@ -1868,15 +1782,17 @@ * private key instead */ if (id->key != NULL) { - ident = format_identity(id); - debug("Offering public key: %s", ident); - free(ident); - sent = send_pubkey_test(ssh, id); + if (try_identity(ssh, id)) { + const char *ident = format_identity(id); + verbose("Offering public key: %s", ident); + free((void*)ident); + sent = send_pubkey_test(ssh, id); + } } else { - debug("Trying private key: %s", id->filename); + verbose("Trying private key: %s", id->filename); id->key = load_identity_file(id); if (id->key != NULL) { - if (id->key != NULL) { + if (try_identity(ssh, id)) { id->isprivate = 1; sent = sign_and_send_pubkey(ssh, id); } @@ -1904,12 +1820,12 @@ return 0; /* disable if no SSH2_MSG_USERAUTH_INFO_REQUEST has been seen */ if (authctxt->attempt_kbdint > 1 && !authctxt->info_req_seen) { - debug3("userauth_kbdint: disable: no info_req_seen"); + debug3_f("disable: no info_req_seen"); ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_INFO_REQUEST, NULL); return 0; } - debug2("userauth_kbdint"); + debug2_f("entering"); if ((r = sshpkt_start(ssh, SSH2_MSG_USERAUTH_REQUEST)) != 0 || (r = sshpkt_put_cstring(ssh, authctxt->server_user)) != 0 || (r = sshpkt_put_cstring(ssh, authctxt->service)) != 0 || @@ -1924,25 +1840,55 @@ return 1; } +static char* +get_response(Authctxt *authctxt, const char *prompt, u_char echo) +{ + char *ret, *display_prompt; + const char *host = options.host_key_alias + ? options.host_key_alias : authctxt->host; + + if (asnmprintf(&display_prompt, INT_MAX, NULL, "(%s@%s) %s", + authctxt->server_user, host, prompt) == -1) + fatal_f("asnmprintf failed"); + ret = read_passphrase(display_prompt, echo ? RP_ECHO : 0); + free(display_prompt); + + return ret; +} + +static int +put_response(struct ssh *ssh, const char *prompt, u_char echo) +{ + int r; + Authctxt *authctxt = ssh->authctxt; + char *response; + + response = get_response(authctxt, prompt, echo); + r = sshpkt_put_cstring(ssh, response); + freezero(response, strlen(response)); + + return r; +} + /* * parse INFO_REQUEST, prompt user and send INFO_RESPONSE */ static int input_userauth_info_req(int type, u_int32_t seq, struct ssh *ssh) { - Authctxt *authctxt = ssh->authctxt; char *name = NULL, *inst = NULL, *lang = NULL, *prompt = NULL; - char *display_prompt = NULL, *response = NULL; - u_char echo = 0; u_int num_prompts, i; int r; + UNUSED(type); + UNUSED(seq); debug2_f("entering"); +{ Authctxt *authctxt = ssh->authctxt; if (authctxt == NULL) fatal_f("no authentication context"); - authctxt->info_req_seen = 1; +} if ((r = sshpkt_get_cstring(ssh, &name, NULL)) != 0 || (r = sshpkt_get_cstring(ssh, &inst, NULL)) != 0 || @@ -1967,20 +1913,13 @@ debug2_f("num_prompts %d", num_prompts); for (i = 0; i < num_prompts; i++) { + u_char echo; if ((r = sshpkt_get_cstring(ssh, &prompt, NULL)) != 0 || (r = sshpkt_get_u8(ssh, &echo)) != 0) goto out; - if (asmprintf(&display_prompt, INT_MAX, NULL, "(%s@%s) %s", - authctxt->server_user, options.host_key_alias ? - options.host_key_alias : authctxt->host, prompt) == -1) - fatal_f("asmprintf failed"); - response = read_passphrase(display_prompt, echo ? RP_ECHO : 0); - if ((r = sshpkt_put_cstring(ssh, response)) != 0) - goto out; - freezero(response, strlen(response)); - free(prompt); - free(display_prompt); - display_prompt = response = prompt = NULL; + r = put_response(ssh, prompt, echo); + if (r != 0) goto out; + free(prompt); prompt = NULL; } /* done with parsing incoming message. */ if ((r = sshpkt_get_end(ssh)) != 0 || @@ -1988,10 +1927,7 @@ goto out; r = sshpkt_send(ssh); out: - if (response) - freezero(response, strlen(response)); free(prompt); - free(display_prompt); free(name); free(inst); free(lang); @@ -2010,6 +1946,7 @@ u_char rversion = 0, version = 2; void (*osigchld)(int); + UNUSED(key); *sigp = NULL; *lenp = 0; @@ -2120,27 +2057,44 @@ Authctxt *authctxt = (Authctxt *)ssh->authctxt; struct sshkey *private = NULL; struct sshbuf *b = NULL; + const char *pkalg; u_char *sig = NULL, *keyblob = NULL; char *fp = NULL, *chost = NULL, *lname = NULL; size_t siglen = 0, keylen = 0; int i, r, success = 0; - if (authctxt->ktypes == NULL) { - authctxt->oktypes = xstrdup(options.hostbased_accepted_algos); - authctxt->ktypes = authctxt->oktypes; +{ /* finalize set of client option HostbasedAlgorithms */ + char *defalgs = default_hostkey_algorithms(); + + if ((options.hostbased_algorithms != NULL) && + (strcmp(options.hostbased_algorithms, "*") != 0) + ) { + /* Assemble */ + char *allalgs = sshkey_alg_list(0, 0, 1, ','); + if (kex_assemble_names(&options.hostbased_algorithms, + defalgs, allalgs) != 0) + fatal_f("kex_assemble_names failed"); + free(allalgs); + free(defalgs); + } else { + /* Enforce default */ + free(options.hostbased_algorithms); + options.hostbased_algorithms = defalgs; } +} + if (authctxt->pkalg_list == NULL) + authctxt->pkalg_list = xstrdup(options.hostbased_algorithms); /* - * Work through each listed type pattern in HostbasedAcceptedAlgorithms, - * trying each hostkey that matches the type in turn. + * Work through each listed algorithm pattern in HostbasedAlgorithms, + * trying each hostkey that matches the algorithm in turn. */ for (;;) { - if (authctxt->active_ktype == NULL) - authctxt->active_ktype = strsep(&authctxt->ktypes, ","); - if (authctxt->active_ktype == NULL || - *authctxt->active_ktype == '\0') + authctxt->active_pkalg = strsep(&authctxt->pkalg_list, ","); + if (authctxt->active_pkalg == NULL || + *authctxt->active_pkalg == '\0') break; - debug3_f("trying key type %s", authctxt->active_ktype); + debug3_f("trying algorithm %s", authctxt->active_pkalg); /* check for a useful key */ private = NULL; @@ -2148,25 +2102,35 @@ if (authctxt->sensitive->keys[i] == NULL || authctxt->sensitive->keys[i]->type == KEY_UNSPEC) continue; - if (!sshkey_match_keyname_to_sigalgs( - sshkey_ssh_name(authctxt->sensitive->keys[i]), - authctxt->active_ktype)) - continue; - /* we take and free the key */ + + pkalg = NULL; + { const char **key_algs = Xkey_algoriths(authctxt->sensitive->keys[i]); + const char **p; + for (p = key_algs; *p != NULL; p++) { + if (strcmp(*p, authctxt->active_pkalg) == 0) { + pkalg = *p; + break; + } + } + free(key_algs); + } + if (pkalg == NULL) continue; + if (!pkalg_match(pkalg, ssh->kex->pkalgs)) continue; + private = authctxt->sensitive->keys[i]; - authctxt->sensitive->keys[i] = NULL; break; } /* Found one */ if (private != NULL) break; /* No more keys of this type; advance */ - authctxt->active_ktype = NULL; + authctxt->active_pkalg = NULL; } if (private == NULL) { - free(authctxt->oktypes); - authctxt->oktypes = authctxt->ktypes = NULL; - authctxt->active_ktype = NULL; + free(authctxt->pkalg_list); + authctxt->pkalg_list = NULL; + free((void*)authctxt->active_pkalg); + authctxt->active_pkalg = NULL; debug("No more client hostkeys for hostbased authentication."); goto out; } @@ -2176,8 +2140,7 @@ error_f("sshkey_fingerprint failed"); goto out; } - debug_f("trying hostkey %s %s using sigalg %s", - sshkey_ssh_name(private), fp, authctxt->active_ktype); + debug_f("trying hostkey %s %s", pkalg, fp); /* figure out a name for the client host */ lname = get_local_name(ssh_packet_get_connection_in(ssh)); @@ -2195,8 +2158,8 @@ error_f("sshbuf_new failed"); goto out; } - if ((r = sshkey_to_blob(private, &keyblob, &keylen)) != 0) { - error_fr(r, "sshkey_to_blob"); + if ((r = Xkey_to_blob(pkalg, private, &keyblob, &keylen)) != 0) { + error_fr(r, "Xkey_to_blob"); goto out; } if ((r = sshbuf_put_stringb(b, ssh->kex->session_id)) != 0 || @@ -2204,7 +2167,7 @@ (r = sshbuf_put_cstring(b, authctxt->server_user)) != 0 || (r = sshbuf_put_cstring(b, authctxt->service)) != 0 || (r = sshbuf_put_cstring(b, authctxt->method->name)) != 0 || - (r = sshbuf_put_cstring(b, authctxt->active_ktype)) != 0 || + (r = sshbuf_put_cstring(b, pkalg)) != 0 || (r = sshbuf_put_string(b, keyblob, keylen)) != 0 || (r = sshbuf_put_cstring(b, chost)) != 0 || (r = sshbuf_put_cstring(b, authctxt->local_user)) != 0) { @@ -2218,14 +2181,14 @@ if ((r = ssh_keysign(ssh, private, &sig, &siglen, sshbuf_ptr(b), sshbuf_len(b))) != 0) { error("sign using hostkey %s %s failed", - sshkey_ssh_name(private), fp); + pkalg, fp); goto out; } if ((r = sshpkt_start(ssh, SSH2_MSG_USERAUTH_REQUEST)) != 0 || (r = sshpkt_put_cstring(ssh, authctxt->server_user)) != 0 || (r = sshpkt_put_cstring(ssh, authctxt->service)) != 0 || (r = sshpkt_put_cstring(ssh, authctxt->method->name)) != 0 || - (r = sshpkt_put_cstring(ssh, authctxt->active_ktype)) != 0 || + (r = sshpkt_put_cstring(ssh, pkalg)) != 0 || (r = sshpkt_put_string(ssh, keyblob, keylen)) != 0 || (r = sshpkt_put_cstring(ssh, chost)) != 0 || (r = sshpkt_put_cstring(ssh, authctxt->local_user)) != 0 || @@ -2243,7 +2206,6 @@ free(lname); free(fp); free(chost); - sshkey_free(private); sshbuf_free(b); return success; diff -ruN openssh-9.4p1/sshconnect.c openssh-9.4p1+x509-14.2.1/sshconnect.c --- openssh-9.4p1/sshconnect.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/sshconnect.c 2023-08-20 10:07:01.000000000 +0300 @@ -1,4 +1,4 @@ -/* $OpenBSD: sshconnect.c,v 1.363 2023/03/10 07:17:08 dtucker Exp $ */ +/* $OpenBSD: sshconnect.c,v 1.362 2023/03/05 05:34:09 dtucker Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -11,6 +11,28 @@ * software must be clearly marked as such, and if the derived work is * incompatible with the protocol description in the RFC file, it must be * called by a name other than "ssh" or "Secure Shell". + * + * Copyright (c) 2002-2023 Roumen Petrov. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "includes.h" @@ -36,9 +58,6 @@ #include #endif #include -#ifdef HAVE_POLL_H -#include -#endif #include #include #include @@ -54,12 +73,11 @@ #include "ssh.h" #include "sshbuf.h" #include "packet.h" -#include "sshkey.h" +#include "ssh-x509.h" #include "sshconnect.h" #include "log.h" #include "misc.h" #include "readconf.h" -#include "atomicio.h" #include "dns.h" #include "monitor_fdpass.h" #include "ssh2.h" @@ -99,7 +117,7 @@ "k", keyalias, "n", host_arg, "p", strport, - "r", options.user, + "r", user, (char *)NULL); free(tmp); return ret; @@ -135,12 +153,12 @@ close(sp[1]); /* Redirect stdin and stdout. */ - if (sp[0] != 0) { - if (dup2(sp[0], 0) == -1) + if (sp[0] != STDIN_FILENO) { + if (dup2(sp[0], STDIN_FILENO) == -1) perror("dup2 stdin"); } - if (sp[0] != 1) { - if (dup2(sp[0], 1) == -1) + if (sp[0] != STDOUT_FILENO) { + if (dup2(sp[0], STDOUT_FILENO) == -1) perror("dup2 stdout"); } if (sp[0] >= 2) @@ -150,9 +168,12 @@ * Stderr is left for non-ControlPersist connections is so * error messages may be printed on the user's terminal. */ - if (!debug_flag && options.control_path != NULL && - options.control_persist && stdfd_devnull(0, 0, 1) == -1) +{ int null_stderr = !debug_flag && + options.control_persist && + options.control_path != NULL; + if (stdfd_devnull(0, 0, null_stderr) == -1) error_f("stdfd_devnull failed"); +} argv[0] = shell; argv[1] = "-c"; @@ -218,24 +239,28 @@ /* Redirect stdin and stdout. */ close(pin[1]); - if (pin[0] != 0) { - if (dup2(pin[0], 0) == -1) + if (pin[0] != STDIN_FILENO) { + if (dup2(pin[0], STDIN_FILENO) == -1) perror("dup2 stdin"); close(pin[0]); } close(pout[0]); - if (dup2(pout[1], 1) == -1) + /* Cannot be 1(STDOUT_FILENO) because pipe() allocates + two descriptors for pin. */ + if (dup2(pout[1], STDOUT_FILENO) == -1) perror("dup2 stdout"); - /* Cannot be 1 because pin allocated two descriptors. */ close(pout[1]); /* * Stderr is left for non-ControlPersist connections is so * error messages may be printed on the user's terminal. */ - if (!debug_flag && options.control_path != NULL && - options.control_persist && stdfd_devnull(0, 0, 1) == -1) +{ int null_stderr = !debug_flag && + options.control_persist && + options.control_path != NULL; + if (stdfd_devnull(0, 0, null_stderr) == -1) error_f("stdfd_devnull failed"); +} argv[0] = shell; argv[1] = "-c"; @@ -282,7 +307,7 @@ kill(proxy_command_pid, SIGHUP); } -#ifdef HAVE_IFADDRS_H +#ifdef HAVE_GETIFADDRS /* * Search a interface address list (returned from getifaddrs(3)) for an * address that matches the desired address family on the specified interface. @@ -292,12 +317,10 @@ check_ifaddrs(const char *ifname, int af, const struct ifaddrs *ifaddrs, struct sockaddr_storage *resultp, socklen_t *rlenp) { - struct sockaddr_in6 *sa6; - struct sockaddr_in *sa; - struct in6_addr *v6addr; const struct ifaddrs *ifa; int allow_local; + UNUSED(ifname); /* * Prefer addresses that are not loopback or linklocal, but use them * if nothing else matches. @@ -311,25 +334,33 @@ continue; switch (ifa->ifa_addr->sa_family) { case AF_INET: + { struct sockaddr_in *sa; + struct in_addr *addr; + sa = (struct sockaddr_in *)ifa->ifa_addr; - if (!allow_local && sa->sin_addr.s_addr == - htonl(INADDR_LOOPBACK)) + addr = &sa->sin_addr; + if (!allow_local && + IN_LOOPBACK(ntohl(addr->s_addr))) continue; - if (*rlenp < sizeof(struct sockaddr_in)) { + if (*rlenp < (socklen_t)sizeof(struct sockaddr_in)) { error_f("v4 addr doesn't fit"); return -1; } *rlenp = sizeof(struct sockaddr_in); memcpy(resultp, sa, *rlenp); return 0; + } case AF_INET6: + { struct sockaddr_in6 *sa6; + struct in6_addr *v6addr; + sa6 = (struct sockaddr_in6 *)ifa->ifa_addr; v6addr = &sa6->sin6_addr; if (!allow_local && (IN6_IS_ADDR_LINKLOCAL(v6addr) || IN6_IS_ADDR_LOOPBACK(v6addr))) continue; - if (*rlenp < sizeof(struct sockaddr_in6)) { + if (*rlenp < (socklen_t)sizeof(struct sockaddr_in6)) { error_f("v6 addr doesn't fit"); return -1; } @@ -337,11 +368,12 @@ memcpy(resultp, sa6, *rlenp); return 0; } + } } } return -1; } -#endif +#endif /*def HAVE_GETIFADDRS*/ /* * Creates a socket for use as the ssh connection. @@ -353,7 +385,7 @@ struct sockaddr_storage bindaddr; socklen_t bindaddrlen = 0; struct addrinfo hints, *res = NULL; -#ifdef HAVE_IFADDRS_H +#ifdef HAVE_GETIFADDRS struct ifaddrs *ifaddrs = NULL; #endif char ntop[NI_MAXHOST]; @@ -392,7 +424,7 @@ memcpy(&bindaddr, res->ai_addr, res->ai_addrlen); bindaddrlen = res->ai_addrlen; } else if (options.bind_interface != NULL) { -#ifdef HAVE_IFADDRS_H +#ifdef HAVE_GETIFADDRS if ((r = getifaddrs(&ifaddrs)) != 0) { error("getifaddrs: %s: %s", options.bind_interface, strerror(errno)); @@ -414,8 +446,8 @@ error_f("getnameinfo failed: %s", ssh_gai_strerror(r)); goto fail; } - if (bind(sock, (struct sockaddr *)&bindaddr, bindaddrlen) != 0) { - error("bind %s: %s", ntop, strerror(errno)); + if (bind(sock, (struct sockaddr *)&bindaddr, bindaddrlen) == -1) { + error_f("bind %s: %s", ntop, strerror(errno)); goto fail; } debug_f("bound to %s", ntop); @@ -427,7 +459,7 @@ out: if (res != NULL) freeaddrinfo(res); -#ifdef HAVE_IFADDRS_H +#ifdef HAVE_GETIFADDRS if (ifaddrs != NULL) freeifaddrs(ifaddrs); #endif @@ -453,6 +485,7 @@ char ntop[NI_MAXHOST], strport[NI_MAXSERV]; struct addrinfo *ai; + UNUSED(port); debug3_f("entering"); memset(ntop, 0, sizeof(ntop)); memset(strport, 0, sizeof(strport)); @@ -486,7 +519,7 @@ /* Create a socket for connecting. */ sock = ssh_create_socket(ai); - if (sock < 0) { + if (sock == -1) { /* Any error is already output */ errno = 0; continue; @@ -538,15 +571,15 @@ struct addrinfo *addrs, struct sockaddr_storage *hostaddr, u_short port, int connection_attempts, int *timeout_ms, int want_keepalive) { - int in, out; - if (options.proxy_command == NULL) { return ssh_connect_direct(ssh, host, addrs, hostaddr, port, connection_attempts, timeout_ms, want_keepalive); } else if (strcmp(options.proxy_command, "-") == 0) { + int in, out; + if ((in = dup(STDIN_FILENO)) == -1 || (out = dup(STDOUT_FILENO)) == -1) { - if (in >= 0) + if (in != -1) close(in); error_f("dup() in/out failed"); return -1; /* ssh_packet_set_connection logs error */ @@ -562,6 +595,21 @@ options.proxy_command); } +static int +prepare_client_banner(struct ssh *ssh) +{ + int r; + + /* NOTE: Version string is prepared and sent with at end. + * After identification exchange trailing is removed for + * further use in key exchange messages. + */ + r = sshbuf_putf(ssh->kex->client_version, + "SSH-%d.%d-%s PKIX["PACKAGE_VERSION"]\r\n", + PROTOCOL_MAJOR_2, PROTOCOL_MINOR_2, SSH_VERSION); + return r; +} + /* defaults to 'no' */ static int confirm(const char *prompt, const char *fingerprint) @@ -573,7 +621,7 @@ if (options.batch_mode) return 0; - for (msg = prompt;;msg = fingerprint ? again_fp : again) { + for (msg = prompt;;msg = (fingerprint != NULL) ? again_fp : again) { cp = p = read_passphrase(msg, RP_ECHO); if (p == NULL) return 0; @@ -595,8 +643,8 @@ { switch (hostaddr->sa_family) { case AF_INET: - return (ntohl(((struct sockaddr_in *)hostaddr)-> - sin_addr.s_addr) >> 24) == IN_LOOPBACKNET; + return IN_LOOPBACK(ntohl(((struct sockaddr_in *)hostaddr)-> + sin_addr.s_addr)); case AF_INET6: return IN6_IS_ADDR_LOOPBACK( &(((struct sockaddr_in6 *)hostaddr)->sin6_addr)); @@ -722,7 +770,7 @@ if (l->marker != MRK_NONE) return 0; /* we are only interested in exact key matches */ - if (l->key == NULL || !sshkey_equal(ctx->key, l->key)) + if (l->key == NULL || !hostkey_match(ctx->key, l->key)) return 0; path = try_tilde_unexpand(l->path); debug_f("found matching key in %s:%lu", path, l->linenum); @@ -743,16 +791,18 @@ int r; debug3_f("trying %s hostfile \"%s\"", which, file); - if ((r = hostkeys_foreach(file, hostkeys_find_by_key_cb, ctx, - ctx->host, ctx->ip, HKF_WANT_PARSE_KEY, 0)) != 0) { - if (r == SSH_ERR_SYSTEM_ERROR && errno == ENOENT) { - debug_f("hostkeys file %s does not exist", file); - return 0; - } - error_fr(r, "hostkeys_foreach failed for %s", file); - return r; + + r = hostkeys_foreach(file, hostkeys_find_by_key_cb, + ctx, ctx->host, ctx->ip, + HKF_WANT_PARSE_KEY, 0); + if (r == 0) return 0; + + if (r == SSH_ERR_SYSTEM_ERROR && errno == ENOENT) { + debug3_f("hostkeys file %s does not exist", file); + return 0; } - return 0; + error_fr(r, "hostkeys_foreach failed for \"%s\"", file); + return r; } /* @@ -891,10 +941,13 @@ /* Prepare a printable command for logs, etc. */ command = argv_assemble(ac, av); - if ((pid = subprocess(tag, command, ac, av, &f, + pid = subprocess(tag, command, ac, av, &f, SSH_SUBPROCESS_STDOUT_CAPTURE|SSH_SUBPROCESS_UNSAFE_PATH| - SSH_SUBPROCESS_PRESERVE_ENV, NULL, NULL, NULL)) == 0) + SSH_SUBPROCESS_PRESERVE_ENV, NULL, NULL, NULL); + if (pid == 0) goto out; + if (pid < 0) + fatal("fail to execute KnownHostsCommand"); load_hostkeys_file(hostkeys, hostfile_hostname, tag, f, 1); @@ -905,9 +958,7 @@ if (f != NULL) fclose(f); ssh_signal(SIGCHLD, osigchld); - for (i = 0; i < ac; i++) - free(av[i]); - free(av); + argv_free(av, ac); free(tag); free(command); free(key_fp); @@ -924,7 +975,7 @@ static int check_host_key(char *hostname, const struct ssh_conn_info *cinfo, struct sockaddr *hostaddr, u_short port, - struct sshkey *host_key, int readonly, int clobber_port, + struct sshkey *host_key, int readonly, char **user_hostfiles, u_int num_user_hostfiles, char **system_hostfiles, u_int num_system_hostfiles, const char *hostfile_command) @@ -934,9 +985,9 @@ char *ip = NULL, *host = NULL; char hostline[1000], *hostp, *fp, *ra; char msg[1024]; - const char *type, *fail_reason = NULL; + const char *type; const struct hostkey_entry *host_found = NULL, *ip_found = NULL; - int len, cancelled_forwarding = 0, confirmed; + int len, cancelled_forwarding = 0; int local = sockaddr_is_local(hostaddr); int r, want_cert = sshkey_is_cert(host_key), host_ip_differ = 0; int hostkey_trusted = 0; /* Known or explicitly accepted by user */ @@ -965,8 +1016,8 @@ * '[' or ']' in the name before they are added. */ if (strcspn(hostname, "@?*#[]|'\'\"\\") != strlen(hostname)) { - debug_f("invalid hostname \"%s\"; will not record: %s", - hostname, fail_reason); + debug_f("invalid hostname \"%s\"; will not record", + hostname); readonly = RDONLY; } @@ -974,8 +1025,7 @@ * Prepare the hostname and address strings used for hostkey lookup. * In some cases, these will have a port number appended. */ - get_hostfile_hostname_ipaddr(hostname, hostaddr, - clobber_port ? 0 : port, &host, &ip); + get_hostfile_hostname_ipaddr(hostname, hostaddr, port, &host, &ip); /* * Turn off check_host_ip if the connection is to localhost, via proxy @@ -990,10 +1040,9 @@ load_hostkeys(host_hostkeys, host, user_hostfiles[i], 0); for (i = 0; i < num_system_hostfiles; i++) load_hostkeys(host_hostkeys, host, system_hostfiles[i], 0); - if (hostfile_command != NULL && !clobber_port) { + if (hostfile_command != NULL && port != 0) load_hostkeys_command(host_hostkeys, hostfile_command, "HOSTNAME", cinfo, host_key, host); - } ip_hostkeys = NULL; if (!want_cert && options.check_host_ip) { @@ -1002,10 +1051,9 @@ load_hostkeys(ip_hostkeys, ip, user_hostfiles[i], 0); for (i = 0; i < num_system_hostfiles; i++) load_hostkeys(ip_hostkeys, ip, system_hostfiles[i], 0); - if (hostfile_command != NULL && !clobber_port) { + if (hostfile_command != NULL && port != 0) load_hostkeys_command(ip_hostkeys, hostfile_command, "ADDRESS", cinfo, host_key, ip); - } } retry: @@ -1052,9 +1100,11 @@ debug("Found %s in %s:%lu", want_cert ? "CA key" : "key", host_found->file, host_found->line); if (want_cert) { - if (sshkey_cert_check_host(host_key, - options.host_key_alias == NULL ? - hostname : options.host_key_alias, 0, + const char *fail_reason; + const char *host_alias = options.host_key_alias == NULL + ? hostname : options.host_key_alias; + + if (sshkey_cert_check_host(host_key, host_alias, 0, options.ca_sign_algorithms, &fail_reason) != 0) { error("%s", fail_reason); goto fail; @@ -1115,10 +1165,10 @@ break; case HOST_NEW: if (options.host_key_alias == NULL && port != 0 && - port != SSH_DEFAULT_PORT && !clobber_port) { + port != SSH_DEFAULT_PORT) { debug("checking without port identifier"); if (check_host_key(hostname, cinfo, hostaddr, 0, - host_key, ROQUIET, 1, + host_key, ROQUIET, user_hostfiles, num_user_hostfiles, system_hostfiles, num_system_hostfiles, hostfile_command) == 0) { @@ -1141,15 +1191,16 @@ goto fail; } else if (options.strict_host_key_checking == SSH_STRICT_HOSTKEY_ASK) { - char *msg1 = NULL, *msg2 = NULL; + char *msg1 = NULL; + int confirmed; xasprintf(&msg1, "The authenticity of host " "'%.200s (%s)' can't be established", host, ip); - if (show_other_keys(host_hostkeys, host_key)) { + if (show_other_keys(host_hostkeys, host_key)) xextendf(&msg1, "\n", "but keys of different " "type are already known for this host."); - } else + else xextendf(&msg1, "", "."); fp = sshkey_fingerprint(host_key, @@ -1160,19 +1211,28 @@ fatal_f("sshkey_fingerprint failed"); xextendf(&msg1, "\n", "%s key fingerprint is %s.", type, fp); + if (sshkey_is_x509(host_key)) { + char *subject = x509key_subject(host_key); + xextendf(&msg1, "\n", + "Distinguished name is '%s'.", + subject); + free(subject); + } if (options.visual_host_key) xextendf(&msg1, "\n", "%s", ra); - if (options.verify_host_key_dns) { + if (options.verify_host_key_dns) xextendf(&msg1, "\n", - "%s host key fingerprint found in DNS.", - matching_host_key_dns ? - "Matching" : "No matching"); - } + "%s host key RR found in DNS.", + matching_host_key_dns + ? "Matching" : "No matching"); + { char *msg2 = NULL; /* msg2 informs for other names matching this key */ if ((msg2 = other_hostkeys_message(host, ip, host_key, user_hostfiles, num_user_hostfiles, system_hostfiles, num_system_hostfiles)) != NULL) xextendf(&msg1, "\n", "%s", msg2); + free(msg2); + } xextendf(&msg1, "\n", "Are you sure you want to continue connecting " @@ -1182,7 +1242,6 @@ free(ra); free(fp); free(msg1); - free(msg2); if (!confirmed) goto fail; hostkey_trusted = 1; /* user explicitly confirmed */ @@ -1254,7 +1313,7 @@ if (readonly == ROQUIET) goto fail; if (options.check_host_ip && host_ip_differ) { - char *key_msg; + const char *key_msg; if (ip_status == HOST_NEW) key_msg = "is unknown"; else if (ip_status == HOST_OK) @@ -1430,7 +1489,8 @@ /* returns 0 if key verifies or -1 if key does NOT verify */ int -verify_host_key(char *host, struct sockaddr *hostaddr, struct sshkey *host_key, +verify_host_key(char *host, struct sockaddr *hostaddr, + char *hostkey_alg, struct sshkey *host_key, const struct ssh_conn_info *cinfo) { u_int i; @@ -1438,6 +1498,13 @@ char valid[64], *fp = NULL, *cafp = NULL; struct sshkey *plain = NULL; + if (sshkey_is_x509(host_key)) { + if (xkey_validate_cert(host_key) != 0) { + r = -1; + goto out; + } + } + if ((fp = sshkey_fingerprint(host_key, options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL) { error_fr(r, "fingerprint host key"); @@ -1456,7 +1523,7 @@ valid, sizeof(valid)); debug("Server host certificate: %s %s, serial %llu " "ID \"%s\" CA %s %s valid %s", - sshkey_ssh_name(host_key), fp, + hostkey_alg, fp, (unsigned long long)host_key->cert->serial, host_key->cert->key_id, sshkey_ssh_name(host_key->cert->signature_key), cafp, @@ -1466,7 +1533,7 @@ host_key->cert->principals[i]); } } else { - debug("Server host key: %s %s", sshkey_ssh_name(host_key), fp); + debug("Server host key: %s %s", hostkey_alg, fp); } if (sshkey_equal(previous_host_key, host_key)) { @@ -1506,7 +1573,7 @@ goto out; if (sshkey_is_cert(plain)) sshkey_drop_cert(plain); - if (verify_host_key_dns(host, hostaddr, plain, &flags) == 0) { + if (verify_host_key_dns(host, hostaddr, cinfo, plain, &flags) == 0) { if (flags & DNS_VERIFY_FOUND) { if (options.verify_host_key_dns == 1 && flags & DNS_VERIFY_MATCH && @@ -1517,16 +1584,18 @@ if (flags & DNS_VERIFY_MATCH) { matching_host_key_dns = 1; } else { + const char *rr = sshkey_is_x509(host_key) + ? "CERT" : "SSHFP"; warn_changed_key(plain); - error("Update the SSHFP RR in DNS " + error("Update the %s RR in DNS " "with the new host key to get rid " - "of this message."); + "of this message.", rr); } } } } r = check_host_key(host, cinfo, hostaddr, options.port, host_key, - RDRW, 0, options.user_hostfiles, options.num_user_hostfiles, + RDRW, options.user_hostfiles, options.num_user_hostfiles, options.system_hostfiles, options.num_system_hostfiles, options.known_hosts_command); @@ -1565,8 +1634,11 @@ host = xstrdup(orighost); lowercase(host); + if ((r = prepare_client_banner(ssh)) != 0) + sshpkt_fatal(ssh, r, "prepare client banner"); + /* Exchange protocol version identification strings with the server. */ - if ((r = kex_exchange_identification(ssh, timeout_ms, NULL)) != 0) + if ((r = kex_exchange_identification(ssh, timeout_ms)) != 0) sshpkt_fatal(ssh, r, "banner exchange"); /* Put the connection into non-blocking mode. */ @@ -1578,7 +1650,10 @@ ssh_kex2(ssh, host, hostaddr, port, cinfo); ssh_userauth2(ssh, local_user, server_user, host, sensitive); free(local_user); + /* do not free "host" as in ssh_kex2() (from sshconnect2.c) + * it is assigned to global variable "xxx_host"! free(host); + */ } /* print all known host keys for a given host, but skip keys of given type */ @@ -1593,16 +1668,29 @@ KEY_XMSS, -1 }; + int subtype[] = { +#ifdef OPENSSL_HAS_ECC + NID_X9_62_prime256v1, + NID_secp384r1, +# ifdef OPENSSL_HAS_NISTP521 + NID_secp521r1, +# endif +#endif /* OPENSSL_HAS_ECC */ + -1 /* non-ECC keys has to be processed once */, + -1 + }; int i, ret = 0; char *fp, *ra; const struct hostkey_entry *found; for (i = 0; type[i] != -1; i++) { - if (type[i] == key->type) - continue; - if (!lookup_key_in_hostkeys_by_type(hostkeys, type[i], - -1, &found)) - continue; + int k; + k = (type[i] == KEY_ECDSA) ? 0 : (sizeof(subtype) / sizeof(*subtype) - 2); + do { + if (type[i] == key->type && subtype[k] == key->ecdsa_nid) + goto nextsubtype; + if (!lookup_key_in_hostkeys_by_types(hostkeys, type[i], subtype[k], &found)) + goto nextsubtype; fp = sshkey_fingerprint(found->key, options.fingerprint_hash, SSH_FP_DEFAULT); ra = sshkey_fingerprint(found->key, @@ -1615,11 +1703,19 @@ sshkey_type(found->key), found->host, found->file, found->line, sshkey_type(found->key), fp); + if (sshkey_is_x509(found->key)) { + char *subject = x509key_subject(found->key); + logit("Distinguished name found is '%s'.", subject); + free(subject); + } if (options.visual_host_key) logit("%s", ra); free(ra); free(fp); ret = 1; +nextsubtype: + k++; + } while(subtype[k] != -1); } return ret; } @@ -1642,6 +1738,11 @@ error("It is also possible that a host key has just been changed."); error("The fingerprint for the %s key sent by the remote host is\n%s.", sshkey_type(host_key), fp); + if (sshkey_is_x509(host_key)) { + char *subject = x509key_subject(host_key); + error("Distinguished name sent by remote host is '%s'.", subject); + free(subject); + } error("Please contact your system administrator."); free(fp); @@ -1694,6 +1795,7 @@ int auth_sock = -1, r; const char *skprovider = NULL; + UNUSED(passphrase); if (options.add_keys_to_agent == 0) return; @@ -1708,12 +1810,11 @@ close(auth_sock); return; } - if (sshkey_is_sk(private)) - skprovider = options.sk_provider; + if ((r = ssh_add_identity_constrained(auth_sock, private, comment == NULL ? authfile : comment, options.add_keys_to_agent_lifespan, - (options.add_keys_to_agent == 3), 0, skprovider, NULL, 0)) == 0) + (options.add_keys_to_agent == 3), 0, skprovider)) == 0) debug("identity added to agent: %s", authfile); else debug("could not add identity to agent: %s (%d)", authfile, r); diff -ruN openssh-9.4p1/sshconnect.h openssh-9.4p1+x509-14.2.1/sshconnect.h --- openssh-9.4p1/sshconnect.h 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/sshconnect.h 2023-08-20 10:07:00.000000000 +0300 @@ -44,12 +44,8 @@ char *locuser; }; -struct addrinfo; -struct ssh; -struct hostkeys; -struct ssh_conn_info; - /* default argument for client percent expansions */ +/* keep synchronised with match exec (readconf.c) */ #define DEFAULT_CLIENT_PERCENT_EXPAND_ARGS(conn_info) \ "C", conn_info->conn_hash_hex, \ "L", conn_info->shorthost, \ @@ -58,11 +54,16 @@ "l", conn_info->thishost, \ "n", conn_info->host_arg, \ "p", conn_info->portstr, \ - "d", conn_info->homedir, \ "h", conn_info->remhost, \ "r", conn_info->remuser, \ + "d", conn_info->homedir, \ "u", conn_info->locuser + +struct addrinfo; +struct ssh; +struct hostkeys; + int ssh_connect(struct ssh *, const char *, const char *, struct addrinfo *, struct sockaddr_storage *, u_short, int, int *, int); @@ -72,8 +73,9 @@ struct sockaddr *, u_short, struct passwd *, int, const struct ssh_conn_info *); -int verify_host_key(char *, struct sockaddr *, struct sshkey *, - const struct ssh_conn_info *); +int verify_host_key(char *host, struct sockaddr *hostaddr, + char *hostkey_alg, struct sshkey *host_key, + const struct ssh_conn_info *cinfo); void get_hostfile_hostname_ipaddr(char *, struct sockaddr *, u_short, char **, char **); diff -ruN openssh-9.4p1/sshd.0 openssh-9.4p1+x509-14.2.1/sshd.0 --- openssh-9.4p1/sshd.0 2023-08-10 04:11:18.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/sshd.0 2023-08-20 10:07:00.000000000 +0300 @@ -1,7 +1,7 @@ -SSHD(8) System Manager's Manual SSHD(8) +SSHD(8) BSD System Manager's Manual SSHD(8) NAME - sshd M-bM-^@M-^S OpenSSH daemon + sshd -- Secure shell daemon SYNOPSIS sshd [-46DdeGiqTtV] [-C connection_spec] [-c host_certificate_file] @@ -9,20 +9,20 @@ [-h host_key_file] [-o option] [-p port] [-u len] DESCRIPTION - sshd (OpenSSH Daemon) is the daemon program for ssh(1). It provides - secure encrypted communications between two untrusted hosts over an - insecure network. + sshd (SecSH Daemon) is the daemon program for ssh(1). It provides secure + encrypted communications between two untrusted hosts over an insecure + network. sshd listens for connections from clients. It is normally started at boot from /etc/rc. It forks a new daemon for each incoming connection. - The forked daemons handle key exchange, encryption, authentication, - command execution, and data exchange. + The forked daemons handle key exchange, encryption, authentication, com- + mand execution, and data exchange. sshd can be configured using command-line options or a configuration file - (by default sshd_config(5)); command-line options override values - specified in the configuration file. sshd rereads its configuration file - when it receives a hangup signal, SIGHUP, by executing itself with the - name and options it was started with, e.g. /usr/sbin/sshd. + (by default sshd_config(5)); command-line options override values speci- + fied in the configuration file. sshd rereads its configuration file when + it receives a hangup signal, SIGHUP, by executing itself with the name + and options it was started with, e.g. /usr/sbin/sshd. The options are as follows: @@ -34,26 +34,26 @@ Specify the connection parameters to use for the -T extended test mode. If provided, any Match directives in the configuration file that would apply are applied before the configuration is - written to standard output. The connection parameters are - supplied as keyword=value pairs and may be supplied in any order, + written to standard output. The connection parameters are sup- + plied as keyword=value pairs and may be supplied in any order, either with multiple -C options or as a comma-separated list. - The keywords are M-bM-^@M-^\addrM-bM-^@M-^], M-bM-^@M-^\userM-bM-^@M-^], M-bM-^@M-^\hostM-bM-^@M-^], M-bM-^@M-^\laddrM-bM-^@M-^], M-bM-^@M-^\lportM-bM-^@M-^], and - M-bM-^@M-^\rdomainM-bM-^@M-^] and correspond to source address, user, resolved source + The keywords are "addr", "user", "host", "laddr", "lport", and + "rdomain" and correspond to source address, user, resolved source host name, local address, local port number and routing domain respectively. -c host_certificate_file Specifies a path to a certificate file to identify sshd during key exchange. The certificate file must match a host key file - specified using the -h option or the HostKey configuration - directive. + specified using the -h option or the HostKey configuration direc- + tive. -D When this option is specified, sshd will not detach and does not become a daemon. This allows easy monitoring of sshd. -d Debug mode. The server sends verbose debug output to standard error, and does not put itself in the background. The server - also will not fork(2) and will only process one connection. This + also will not fork and will only process one connection. This option is only intended for debugging for the server. Multiple -d options increase the debugging level. Maximum is 3. @@ -64,20 +64,19 @@ -f config_file Specifies the name of the configuration file. The default is - /etc/ssh/sshd_config. sshd refuses to start if there is no - configuration file. + /etc/ssh/sshd_config. sshd refuses to start if there is no con- + figuration file. -G Parse and print configuration file. Check the validity of the configuration file, output the effective configuration to stdout - and then exit. Optionally, Match rules may be applied by - specifying the connection parameters using one or more -C - options. + and then exit. Optionally, Match rules may be applied by speci- + fying the connection parameters using one or more -C options. -g login_grace_time - Gives the grace time for clients to authenticate themselves - (default 120 seconds). If the client fails to authenticate the - user within this many seconds, the server disconnects and exits. - A value of zero indicates no limit. + Gives the grace time for clients to authenticate themselves (de- + fault 120 seconds). If the client fails to authenticate the user + within this many seconds, the server disconnects and exits. A + value of zero indicates no limit. -h host_key_file Specifies a file from which a host key is read. This option must @@ -87,31 +86,38 @@ /etc/ssh/ssh_host_rsa_key. It is possible to have multiple host key files for the different host key algorithms. + For RSA, ECDSA, Ed25519 or DSA host key may contain X.509 cer- + tificate that match it. In addition file may contain extra X.509 + certificates. Extra certificates along with certificates from + X.509 store are used to build chain of certificates leading to a + trusted certificate authority if required by public key algorithm + format. + -i Specifies that sshd is being run from inetd(8). -o option - Can be used to give options in the format used in the - configuration file. This is useful for specifying options for - which there is no separate command-line flag. For full details - of the options, and their values, see sshd_config(5). + Can be used to give options in the format used in the configura- + tion file. This is useful for specifying options for which there + is no separate command-line flag. For full details of the op- + tions, and their values, see sshd_config(5). -p port Specifies the port on which the server listens for connections - (default 22). Multiple port options are permitted. Ports - specified in the configuration file with the Port option are - ignored when a command-line port is specified. Ports specified - using the ListenAddress option override command-line ports. + (default 22). Multiple port options are permitted. Ports speci- + fied in the configuration file with the Port option are ignored + when a command-line port is specified. Ports specified using the + ListenAddress option override command-line ports. - -q Quiet mode. Nothing is sent to the system log. Normally the - beginning, authentication, and termination of each connection is + -q Quiet mode. Nothing is sent to the system log. Normally the be- + ginning, authentication, and termination of each connection is logged. -T Extended test mode. Check the validity of the configuration file, output the effective configuration to stdout and then exit. - Optionally, Match rules may be applied by specifying the - connection parameters using one or more -C options. This is - similar to the -G flag, but it includes the additional testing - performed by the -t flag. + Optionally, Match rules may be applied by specifying the connec- + tion parameters using one or more -C options. This is similar to + the -G flag, but it includes the additional testing performed by + the -t flag. -t Test mode. Only check the validity of the configuration file and sanity of the keys. This is useful for updating sshd reliably as @@ -120,52 +126,51 @@ -u len This option is used to specify the size of the field in the utmp structure that holds the remote host name. If the resolved host name is longer than len, the dotted decimal value will be used - instead. This allows hosts with very long host names that - overflow this field to still be uniquely identified. Specifying - -u0 indicates that only dotted decimal addresses should be put - into the utmp file. -u0 may also be used to prevent sshd from - making DNS requests unless the authentication mechanism or - configuration requires it. Authentication mechanisms that may - require DNS include HostbasedAuthentication and using a - from="pattern-list" option in a key file. Configuration options - that require DNS include using a USER@HOST pattern in AllowUsers - or DenyUsers. + instead. This allows hosts with very long host names that over- + flow this field to still be uniquely identified. Specifying -u0 + indicates that only dotted decimal addresses should be put into + the utmp file. -u0 may also be used to prevent sshd from making + DNS requests unless the authentication mechanism or configuration + requires it. Authentication mechanisms that may require DNS in- + clude HostbasedAuthentication and using a from="pattern-list" op- + tion in a key file. Configuration options that require DNS in- + clude using a USER@HOST pattern in AllowUsers or DenyUsers. -V Display the version number and exit. AUTHENTICATION - The OpenSSH SSH daemon supports SSH protocol 2 only. Each host has a - host-specific key, used to identify the host. Whenever a client - connects, the daemon responds with its public host key. The client - compares the host key against its own database to verify that it has not - changed. Forward secrecy is provided through a Diffie-Hellman key - agreement. This key agreement results in a shared session key. The rest - of the session is encrypted using a symmetric cipher. The client selects - the encryption algorithm to use from those offered by the server. - Additionally, session integrity is provided through a cryptographic - message authentication code (MAC). + The SecSH daemon supports SSH protocol 2 only. Each host has a host-spe- + cific key, used to identify the host. Whenever a client connects, the + daemon responds with its public host key. The client compares the host + key against its own database to verify that it has not changed. Forward + secrecy is provided through a Diffie-Hellman key agreement. This key + agreement results in a shared session key. The rest of the session is + encrypted using a symmetric cipher. The client selects the encryption + algorithm to use from those offered by the server. Additionally, session + integrity is provided through a cryptographic message authentication code + (MAC). Finally, the server and the client enter an authentication dialog. The - client tries to authenticate itself using host-based authentication, - public key authentication, challenge-response authentication, or password + client tries to authenticate itself using host-based authentication, pub- + lic key authentication, keyboard-interactive authentication, or password authentication. Regardless of the authentication type, the account is checked to ensure that it is accessible. An account is not accessible if it is locked, - listed in DenyUsers or its group is listed in DenyGroups . The - definition of a locked account is system dependent. Some platforms have - their own account database (eg AIX) and some modify the passwd field ( - M-bM-^@M-^X*LK*M-bM-^@M-^Y on Solaris and UnixWare, M-bM-^@M-^X*M-bM-^@M-^Y on HP-UX, containing M-bM-^@M-^XNologinM-bM-^@M-^Y on - Tru64, a leading M-bM-^@M-^X*LOCKED*M-bM-^@M-^Y on FreeBSD and a leading M-bM-^@M-^X!M-bM-^@M-^Y on most - Linuxes). If there is a requirement to disable password authentication - for the account while allowing still public-key, then the passwd field - should be set to something other than these values (eg M-bM-^@M-^XNPM-bM-^@M-^Y or M-bM-^@M-^X*NP*M-bM-^@M-^Y ). + listed in DenyUsers or its group is listed in DenyGroups . The defini- + tion of a locked account is system dependent. Some platforms have their + own account database (eg AIX) and some modify the passwd field ( '*LK*' + on Solaris and UnixWare, '*' on HP-UX, containing 'Nologin' on Tru64, a + leading '*LOCKED*' on FreeBSD and a leading '!' on most Linuxes). If + there is a requirement to disable password authentication for the account + while allowing still public-key, then the passwd field should be set to + something other than these values (eg 'NP' or '*NP*' ). If the client successfully authenticates itself, a dialog for preparing the session is entered. At this time the client may request things like - allocating a pseudo-tty, forwarding X11 connections, forwarding TCP - connections, or forwarding the authentication agent connection over the - secure channel. + allocating a pseudo-tty, forwarding X11 connections, forwarding TCP con- + nections, or forwarding the authentication agent connection over the se- + cure channel. After this, the client either requests an interactive shell or execution or a non-interactive command, which sshd will execute via the user's @@ -174,8 +179,8 @@ to/from the shell or command on the server side, and the user terminal in the client side. - When the user program terminates and all forwarded X11 and other - connections have been closed, the server sends command exit status to the + When the user program terminates and all forwarded X11 and other connec- + tions have been closed, the server sends command exit status to the client, and both sides exit. LOGIN PROCESS @@ -201,23 +206,22 @@ 7. Changes to user's home directory. 8. If ~/.ssh/rc exists and the sshd_config(5) PermitUserRC option - is set, runs it; else if /etc/ssh/sshrc exists, runs it; - otherwise runs xauth(1). The M-bM-^@M-^\rcM-bM-^@M-^] files are given the X11 - authentication protocol and cookie in standard input. See + is set, runs it; else if /etc/ssh/sshrc exists, runs it; oth- + erwise runs xauth(1). The "rc" files are given the X11 au- + thentication protocol and cookie in standard input. See SSHRC, below. 9. Runs user's shell or command. All commands are run under the - user's login shell as specified in the system password - database. + user's login shell as specified in the system password data- + base. SSHRC If the file ~/.ssh/rc exists, sh(1) runs it after reading the environment - files but before starting the user's shell or command. It must not - produce any output on stdout; stderr must be used instead. If X11 - forwarding is in use, it will receive the "proto cookie" pair in its - standard input (and DISPLAY in its environment). The script must call - xauth(1) because sshd will not run xauth automatically to add X11 - cookies. + files but before starting the user's shell or command. It must not pro- + duce any output on stdout; stderr must be used instead. If X11 forward- + ing is in use, it will receive the "proto cookie" pair in its standard + input (and DISPLAY in its environment). The script must call xauth(1) + because sshd will not run xauth automatically to add X11 cookies. The primary purpose of this file is to run any initialization routines which may be needed before the user's home directory becomes accessible; @@ -243,36 +247,55 @@ AUTHORIZED_KEYS FILE FORMAT AuthorizedKeysFile specifies the files containing public keys for public key authentication; if this option is not specified, the default is - ~/.ssh/authorized_keys and ~/.ssh/authorized_keys2. Each line of the - file contains one key (empty lines and lines starting with a M-bM-^@M-^X#M-bM-^@M-^Y are - ignored as comments). Public keys consist of the following space- - separated fields: options, keytype, base64-encoded key, comment. The - options field is optional. The supported key types are: + ~/.ssh/authorized_keys and ~/.ssh/authorized_keys2. Key file may contain + X.509 certificates or X.509 certificate "Distinguished Name". Each line + of the file contains one key (empty lines and lines starting with a '#' + are ignored as comments). Public keys consist of the following space- + separated fields: options, keytype, base64-encoded key, comment. The op- + tions field is optional. The supported key types are: - sk-ecdsa-sha2-nistp256@openssh.com ecdsa-sha2-nistp256 ecdsa-sha2-nistp384 ecdsa-sha2-nistp521 - sk-ssh-ed25519@openssh.com ssh-ed25519 ssh-dss ssh-rsa The comment field is not used for anything (but may be convenient for the - user to identify the key). + user to identify the key). "ssh-rsa". In addition, user can use X.509 + certificates. In such case keytype is one of: + + x509v3-rsa2048-sha256 + x509v3-ssh-rsa + x509v3-sign-rsa + x509v3-ecdsa-sha2-nistp256 + x509v3-ecdsa-sha2-nistp384 + x509v3-ecdsa-sha2-nistp521 + x509v3-ssh-dss + x509v3-sign-dss + x509v3-ssh-ed25519 + + Instead of "base64 encoded key" line must contain base64 encoded X.509 + certificate (old style) or a keyword (new style), optionally followed by + symbol '=' (equal) or ':' (colon), zero or more spaces and X.509 certifi- + cate "Distinguished Name" (Subject). Keyword is case insensitive and can + be one of 'Subject' , 'Distinguished Name' , 'Distinguished-Name' , + 'Distinguished_Name' , 'DistinguishedName' or 'DN'. Separator of Subject + items can be '/' (slash), ',' (comma) or mixed and order is not impor- + tant. Note that lines in this file can be several hundred bytes long (because of the size of the public key encoding) up to a limit of 8 kilobytes, - which permits RSA keys up to 16 kilobits. You don't want to type them - in; instead, copy the id_dsa.pub, id_ecdsa.pub, id_ecdsa_sk.pub, - id_ed25519.pub, id_ed25519_sk.pub, or the id_rsa.pub file and edit it. + which permits DSA keys up to 8 kilobits and RSA keys up to 16 kilobits. + You don't want to type them in; instead, copy the id_dsa.pub, + id_ecdsa.pub, id_ed25519.pub, or the id_rsa.pub file and edit it. sshd enforces a minimum RSA key modulus size of 1024 bits. - The options (if present) consist of comma-separated option - specifications. No spaces are permitted, except within double quotes. - The following option specifications are supported (note that option - keywords are case-insensitive): + The options (if present) consist of comma-separated option specifica- + tions. No spaces are permitted, except within double quotes. The fol- + lowing option specifications are supported (note that option keywords are + case-insensitive): agent-forwarding Enable authentication agent forwarding previously disabled by the @@ -280,8 +303,8 @@ cert-authority Specifies that the listed key is a certification authority (CA) - that is trusted to validate signed certificates for user - authentication. + that is trusted to validate signed certificates for user authen- + tication. Certificates may encode access restrictions similar to these key options. If both certificate restrictions and key options are @@ -291,16 +314,16 @@ Specifies that the command is executed whenever this key is used for authentication. The command supplied by the user (if any) is ignored. The command is run on a pty if the client requests a - pty; otherwise it is run without a tty. If an 8-bit clean - channel is required, one must not request a pty or should specify + pty; otherwise it is run without a tty. If an 8-bit clean chan- + nel is required, one must not request a pty or should specify no-pty. A quote may be included in the command by quoting it with a backslash. This option might be useful to restrict certain public keys to perform just a specific operation. An example might be a key that permits remote backups but nothing else. Note that the - client may specify TCP and/or X11 forwarding unless they are - explicitly prohibited, e.g. using the restrict key option. + client may specify TCP and/or X11 forwarding unless they are ex- + plicitly prohibited, e.g. using the restrict key option. The command originally supplied by the client is available in the SSH_ORIGINAL_COMMAND environment variable. Note that this option @@ -321,10 +344,10 @@ expiry-time="timespec" Specifies a time after which the key will not be accepted. The - time may be specified as a YYYYMMDD[Z] date or a - YYYYMMDDHHMM[SS][Z] time. Dates and times will be interpreted in - the system time zone unless suffixed by a Z character, in which - case they will be interpreted in the UTC time zone. + time may be specified as a YYYYMMDD[Z] date or a YYYYMMD- + DHHMM[SS][Z] time. Dates and times will be interpreted in the + system time zone unless suffixed by a Z character, in which case + they will be interpreted in the UTC time zone. from="pattern-list" Specifies that in addition to public key authentication, either @@ -332,9 +355,9 @@ present in the comma-separated list of patterns. See PATTERNS in ssh_config(5) for more information on patterns. - In addition to the wildcard matching that may be applied to - hostnames or addresses, a from stanza may match IP addresses - using CIDR address/masklen notation. + In addition to the wildcard matching that may be applied to host- + names or addresses, a from stanza may match IP addresses using + CIDR address/masklen notation. The purpose of this option is to optionally increase security: public key authentication by itself does not trust the network or @@ -363,79 +386,72 @@ Any X11 forward requests by the client will return an error. permitlisten="[host:]port" - Limit remote port forwarding with the ssh(1) -R option such that - it may only listen on the specified host (optional) and port. - IPv6 addresses can be specified by enclosing the address in - square brackets. Multiple permitlisten options may be applied - separated by commas. Hostnames may include wildcards as - described in the PATTERNS section in ssh_config(5). A port - specification of * matches any port. Note that the setting of + Limit remote port forwarding requested with the ssh(1) -R option + such that it may only listen on the specified host (optional) and + port. IPv6 addresses can be specified by enclosing the address + in square brackets. Multiple permitlisten options may be applied + separated by commas. Hostnames may include wildcards as de- + scribed in the PATTERNS section in ssh_config(5). A port speci- + fication of * matches any port. Note that the setting of GatewayPorts may further restrict listen addresses. Note that - ssh(1) will send a hostname of M-bM-^@M-^\localhostM-bM-^@M-^] if a listen host was + ssh(1) will send a hostname of "localhost" if a listen host was not specified when the forwarding was requested, and that this name is treated differently to the explicit localhost addresses - M-bM-^@M-^\127.0.0.1M-bM-^@M-^] and M-bM-^@M-^\::1M-bM-^@M-^]. + "127.0.0.1" and "::1". permitopen="host:port" - Limit local port forwarding with the ssh(1) -L option such that - it may only connect to the specified host and port. IPv6 - addresses can be specified by enclosing the address in square - brackets. Multiple permitopen options may be applied separated - by commas. No pattern matching or name lookup is performed on - the specified hostnames, they must be literal host names and/or - addresses. A port specification of * matches any port. + Limit local port forwarding requested with the ssh(1) -L option + such that it may only connect to the specified host and port. + IPv6 addresses can be specified by enclosing the address in + square brackets. Multiple permitopen options may be applied sep- + arated by commas. No pattern matching or name lookup is per- + formed on the specified hostnames, they must be literal host + names and/or addresses. A port specification of * matches any + port. port-forwarding - Enable port forwarding previously disabled by the restrict - option. + Enable port forwarding previously disabled by the restrict op- + tion. principals="principals" - On a cert-authority line, specifies allowed principals for - certificate authentication as a comma-separated list. At least - one name from the list must appear in the certificate's list of - principals for the certificate to be accepted. This option is - ignored for keys that are not marked as trusted certificate - signers using the cert-authority option. - - pty Permits tty allocation previously disabled by the restrict - option. - - no-touch-required - Do not require demonstration of user presence for signatures made - using this key. This option only makes sense for the FIDO - authenticator algorithms ecdsa-sk and ed25519-sk. - - verify-required - Require that signatures made using this key attest that they - verified the user, e.g. via a PIN. This option only makes sense - for the FIDO authenticator algorithms ecdsa-sk and ed25519-sk. + On a cert-authority line, specifies allowed principals for cer- + tificate authentication as a comma-separated list. At least one + name from the list must appear in the certificate's list of prin- + cipals for the certificate to be accepted. This option is ig- + nored for keys that are not marked as trusted certificate signers + using the cert-authority option. + + pty Permits tty allocation previously disabled by the restrict op- + tion. restrict - Enable all restrictions, i.e. disable port, agent and X11 - forwarding, as well as disabling PTY allocation and execution of + Enable all restrictions, i.e. disable port, agent and X11 for- + warding, as well as disabling PTY allocation and execution of ~/.ssh/rc. If any future restriction capabilities are added to authorized_keys files, they will be included in this set. tunnel="n" Force a tun(4) device on the server. Without this option, the - next available device will be used if the client requests a - tunnel. + next available device will be used if the client requests a tun- + nel. user-rc Enables execution of ~/.ssh/rc previously disabled by the restrict option. X11-forwarding - Permits X11 forwarding previously disabled by the restrict - option. + Permits X11 forwarding previously disabled by the restrict op- + tion. An example authorized_keys file: # Comments are allowed at start of line. Blank lines are allowed. # Plain key, no restrictions ssh-rsa ... - # Forced command, disable PTY and all forwarding - restrict,command="dump /home" ssh-rsa ... + # X.509 certificate, no restrictions + x509v3-rsa2048-sha256 subject=/C=XX/ST=World/O=SecSH Test Team... + # Forced command, disable all forwarding, PTY and etc. + restrict,command="uptime" ssh-rsa ... # Restriction of ssh -L forwarding destinations permitopen="192.0.2.1:80",permitopen="192.0.2.2:25" ssh-rsa ... # Restriction of ssh -R forwarding listeners @@ -444,91 +460,85 @@ tunnel="0",command="sh /etc/netstart tun0" ssh-rsa ... # Override of restriction to allow PTY allocation restrict,pty,command="nethack" ssh-rsa ... - # Allow FIDO key without requiring touch - no-touch-required sk-ecdsa-sha2-nistp256@openssh.com ... - # Require user-verification (e.g. PIN or biometric) for FIDO key - verify-required sk-ecdsa-sha2-nistp256@openssh.com ... - # Trust CA key, allow touch-less FIDO if requested in certificate - cert-authority,no-touch-required,principals="user_a" ssh-rsa ... SSH_KNOWN_HOSTS FILE FORMAT The /etc/ssh/ssh_known_hosts and ~/.ssh/known_hosts files contain host - public keys for all known hosts. The global file should be prepared by - the administrator (optional), and the per-user file is maintained - automatically: whenever the user connects to an unknown host, its key is - added to the per-user file. - - Each line in these files contains the following fields: marker - (optional), hostnames, keytype, base64-encoded key, comment. The fields - are separated by spaces. + public keys, X.509 certificates (old style) or X.509 certificate + "Distinguished Name" for all known hosts. The global file should be pre- + pared by the administrator (optional), and the per-user file is main- + tained automatically: whenever the user connects to an unknown host, its + key is added to the per-user file. + + Each line in these files contains the following fields: marker (op- + tional), hostnames, keytype, base64-encoded key, comment. The fields are + separated by spaces. The marker is optional, but if it is present then it must be one of - M-bM-^@M-^\@cert-authorityM-bM-^@M-^], to indicate that the line contains a certification - authority (CA) key, or M-bM-^@M-^\@revokedM-bM-^@M-^], to indicate that the key contained on + "@cert-authority", to indicate that the line contains a certification au- + thority (CA) key, or "@revoked", to indicate that the key contained on the line is revoked and must not ever be accepted. Only one marker should be used on a key line. - Hostnames is a comma-separated list of patterns (M-bM-^@M-^X*M-bM-^@M-^Y and M-bM-^@M-^X?M-bM-^@M-^Y act as - wildcards); each pattern in turn is matched against the host name. When - sshd is authenticating a client, such as when using - HostbasedAuthentication, this will be the canonical client host name. - When ssh(1) is authenticating a server, this will be the host name given - by the user, the value of the ssh(1) HostkeyAlias if it was specified, or - the canonical server hostname if the ssh(1) CanonicalizeHostname option - was used. + Hostnames is a comma-separated list of patterns ('*' and '?' act as wild- + cards); each pattern in turn is matched against the host name. When sshd + is authenticating a client, such as when using HostbasedAuthentication, + this will be the canonical client host name. When ssh(1) is authenticat- + ing a server, this will be the host name given by the user, the value of + the ssh(1) HostkeyAlias if it was specified, or the canonical server + hostname if the ssh(1) CanonicalizeHostname option was used. - A pattern may also be preceded by M-bM-^@M-^X!M-bM-^@M-^Y to indicate negation: if the host + A pattern may also be preceded by '!' to indicate negation: if the host name matches a negated pattern, it is not accepted (by that line) even if - it matched another pattern on the line. A hostname or address may - optionally be enclosed within M-bM-^@M-^X[M-bM-^@M-^Y and M-bM-^@M-^X]M-bM-^@M-^Y brackets then followed by M-bM-^@M-^X:M-bM-^@M-^Y - and a non-standard port number. + it matched another pattern on the line. A hostname or address may op- + tionally be enclosed within '[' and ']' brackets then followed by ':' and + a non-standard port number. Alternately, hostnames may be stored in a hashed form which hides host names and addresses should the file's contents be disclosed. Hashed - hostnames start with a M-bM-^@M-^X|M-bM-^@M-^Y character. Only one hashed hostname may - appear on a single line and none of the above negation or wildcard - operators may be applied. + hostnames start with a '|' character. Only one hashed hostname may ap- + pear on a single line and none of the above negation or wildcard opera- + tors may be applied. The keytype and base64-encoded key are taken directly from the host key; they can be obtained, for example, from /etc/ssh/ssh_host_rsa_key.pub. The optional comment field continues to the end of the line, and is not used. - Lines starting with M-bM-^@M-^X#M-bM-^@M-^Y and empty lines are ignored as comments. + Lines starting with '#' and empty lines are ignored as comments. When performing host authentication, authentication is accepted if any matching line has the proper key; either one that matches exactly or, if the server has presented a certificate for authentication, the key of the certification authority that signed the certificate. For a key to be - trusted as a certification authority, it must use the M-bM-^@M-^\@cert-authorityM-bM-^@M-^] + trusted as a certification authority, it must use the "@cert-authority" marker described above. The known hosts file also provides a facility to mark keys as revoked, for example when it is known that the associated private key has been - stolen. Revoked keys are specified by including the M-bM-^@M-^\@revokedM-bM-^@M-^] marker at + stolen. Revoked keys are specified by including the "@revoked" marker at the beginning of the key line, and are never accepted for authentication or as certification authorities, but instead will produce a warning from ssh(1) when they are encountered. - It is permissible (but not recommended) to have several lines or - different host keys for the same names. This will inevitably happen when - short forms of host names from different domains are put in the file. It - is possible that the files contain conflicting information; - authentication is accepted if valid information can be found from either - file. + It is permissible (but not recommended) to have several lines or differ- + ent host keys for the same names. This will inevitably happen when short + forms of host names from different domains are put in the file. It is + possible that the files contain conflicting information; authentication + is accepted if valid information can be found from either file. Note that the lines in these files are typically hundreds of characters long, and you definitely don't want to type in the host keys by hand. - Rather, generate them by a script, ssh-keyscan(1) or by taking, for - example, /etc/ssh/ssh_host_rsa_key.pub and adding the host names at the + Rather, generate them by a script, ssh-keyscan(1) or by taking, for exam- + ple, /etc/ssh/ssh_host_rsa_key.pub and adding the host names at the front. ssh-keygen(1) also offers some basic automated editing for - ~/.ssh/known_hosts including removing hosts matching a host name and - converting all host names to their hashed representations. + ~/.ssh/known_hosts including removing hosts matching a host name and con- + verting all host names to their hashed representations. An example ssh_known_hosts file: # Comments allowed at start of line cvs.example.net,192.0.2.10 ssh-rsa AAAA1234.....= + x509host x509v3-sign-rsa Subject:/C=XX..... # A hashed hostname |1|JfKTdBh7rNbXkVAQCRp4OQoPfmI=|USECr3SWf1JUPsms5AqfD5QfxkM= ssh-rsa AAAA1234.....= @@ -540,19 +550,18 @@ FILES ~/.hushlogin This file is used to suppress printing the last login time and - /etc/motd, if PrintLastLog and PrintMotd, respectively, are - enabled. It does not suppress printing of the banner specified - by Banner. + /etc/motd, if PrintLastLog and PrintMotd, respectively, are en- + abled. It does not suppress printing of the banner specified by + Banner. ~/.rhosts This file is used for host-based authentication (see ssh(1) for more information). On some machines this file may need to be - world-readable if the user's home directory is on an NFS - partition, because sshd reads it as root. Additionally, this - file must be owned by the user, and must not have write - permissions for anyone else. The recommended permission for most - machines is read/write for the user, and not accessible by - others. + world-readable if the user's home directory is on an NFS parti- + tion, because sshd reads it as root. Additionally, this file + must be owned by the user, and must not have write permissions + for anyone else. The recommended permission for most machines is + read/write for the user, and not accessible by others. ~/.shosts This file is used in exactly the same way as .rhosts, but allows @@ -560,45 +569,51 @@ rlogin/rsh. ~/.ssh/ - This directory is the default location for all user-specific - configuration and authentication information. There is no - general requirement to keep the entire contents of this directory - secret, but the recommended permissions are read/write/execute - for the user, and not accessible by others. + This directory is the default location for all user-specific con- + figuration and authentication information. There is no general + requirement to keep the entire contents of this directory secret, + but the recommended permissions are read/write/execute for the + user, and not accessible by others. ~/.ssh/authorized_keys - Lists the public keys (DSA, ECDSA, Ed25519, RSA) that can be used - for logging in as this user. The format of this file is - described above. The content of the file is not highly + Lists the public keys (DSA, ECDSA, Ed25519, RSA), X.509 certifi- + cates or X.509 certificate "Distinguished Names" (recommended) + that can be used for logging in as this user. The format of this + file is described above. The content of the file is not highly sensitive, but the recommended permissions are read/write for the user, and not accessible by others. If this file, the ~/.ssh directory, or the user's home directory are writable by other users, then the file could be modified or - replaced by unauthorized users. In this case, sshd will not - allow it to be used unless the StrictModes option has been set to - M-bM-^@M-^\noM-bM-^@M-^]. + replaced by unauthorized users. In this case, sshd will not al- + low it to be used unless the StrictModes option has been set to + "no". ~/.ssh/environment This file is read into the environment at login (if it exists). It can only contain empty lines, comment lines (that start with - M-bM-^@M-^X#M-bM-^@M-^Y), and assignment lines of the form name=value. The file + '#'), and assignment lines of the form name=value. The file should be writable only by the user; it need not be readable by anyone else. Environment processing is disabled by default and is controlled via the PermitUserEnvironment option. ~/.ssh/known_hosts - Contains a list of host keys for all hosts the user has logged - into that are not already in the systemwide list of known host - keys. The format of this file is described above. This file - should be writable only by root/the owner and can, but need not - be, world-readable. + Contains a list of host keys or X.509 certificates for all hosts + the user has logged into that are not already in the systemwide + list of known host keys. The format of this file is described + above. This file should be writable only by root/the owner and + can, but need not be, world-readable. ~/.ssh/rc Contains initialization routines to be run before the user's home directory becomes accessible. This file should be writable only by the user, and need not be readable by anyone else. + /etc/hosts.allow + /etc/hosts.deny + Access controls that should be enforced by tcp-wrappers are de- + fined here. Further details are described in hosts_access(5). + /etc/hosts.equiv This file is for host-based authentication (see ssh(1)). It should only be writable by root. @@ -619,38 +634,61 @@ world-readable. /etc/shosts.equiv - This file is used in exactly the same way as hosts.equiv, but - allows host-based authentication without permitting login with + This file is used in exactly the same way as hosts.equiv, but al- + lows host-based authentication without permitting login with rlogin/rsh. + /etc/ssh/ca/ca-bundle.crt + /etc/ssh/ca/ca-bundle.crl + The first file contain multiple X.509 certificates and the second + "Certificate Revocation List" (CRLs) of certificate signers in + PEM format concatenated together. Used to verify and validate + client X.509 certificate. + + /etc/ssh/ca/crt + /etc/ssh/ca/crl + "Hash dirs" with X.509 certificates, the first directory or CLRs, + the second, of X.509 certificate signers. Each X.509 certificate + should be stored in separate file with name [HASH].[NUMBER] or + [HASH].r[NUMBER] for the CRL, where [HASH] is X.509 certificate + or CRL hash value and [NUMBER] is an integer starting from zero. + Used to verify and validate client X.509 certificate. + /etc/ssh/ssh_host_ecdsa_key /etc/ssh/ssh_host_ed25519_key /etc/ssh/ssh_host_rsa_key - These files contain the private parts of the host keys. These - files should only be owned by root, readable only by root, and - not accessible to others. Note that sshd does not start if these - files are group/world-accessible. + These files contain the private parts of the host keys. For RSA, + ECDSA, Ed25519 or DSA keys file may contain X.509 certificate + that match it. In addition file may contain extra X.509 certifi- + cates. Extra certificates along with certificates from X.509 + store are used to build chain of certificates leading to a + trusted certificate authority if required by public key algorithm + format. These files should only be owned by root, readable only + by root, and not accessible to others. Note that sshd does not + start if these files are group/world-accessible. /etc/ssh/ssh_host_ecdsa_key.pub /etc/ssh/ssh_host_ed25519_key.pub /etc/ssh/ssh_host_rsa_key.pub These files contain the public parts of the host keys. These files should be world-readable but writable only by root. Their - contents should match the respective private parts. These files - are not really used for anything; they are provided for the - convenience of the user so their contents can be copied to known - hosts files. These files are created using ssh-keygen(1). + contents should match the respective private parts. Note that + when corresponding host key contain X.509 certificate these files + must contains that certificate. These files are not really used + for anything; they are provided for the convenience of the user + so their contents can be copied to known hosts files. These + files are created using ssh-keygen(1). /etc/ssh/ssh_known_hosts Systemwide list of known host keys. This file should be prepared - by the system administrator to contain the public host keys of - all machines in the organization. The format of this file is - described above. This file should be writable only by root/the - owner and should be world-readable. + by the system administrator to contain the public host keys or + X.509 certificates of all machines in the organization. The for- + mat of this file is described above. This file should be + writable only by root/the owner and should be world-readable. /etc/ssh/sshd_config - Contains configuration data for sshd. The file format and - configuration options are described in sshd_config(5). + Contains configuration data for sshd. The file format and con- + figuration options are described in sshd_config(5). /etc/ssh/sshrc Similar to ~/.ssh/rc, it can be used to specify machine-specific @@ -667,20 +705,25 @@ Contains the process ID of the sshd listening for connections (if there are several daemons running concurrently for different ports, this contains the process ID of the one started last). - The content of this file is not sensitive; it can be world- - readable. + The content of this file is not sensitive; it can be world-read- + able. SEE ALSO scp(1), sftp(1), ssh(1), ssh-add(1), ssh-agent(1), ssh-keygen(1), - ssh-keyscan(1), chroot(2), login.conf(5), moduli(5), sshd_config(5), - inetd(8), sftp-server(8) + ssh-keyscan(1), chroot(2), hosts_access(5), login.conf(5), moduli(5), + sshd_config(5), inetd(8), sftp-server(8) AUTHORS - OpenSSH is a derivative of the original and free ssh 1.2.12 release by + PKIX-SSH is a derivative of the original and free ssh 1.2.12 release by Tatu Ylonen. Aaron Campbell, Bob Beck, Markus Friedl, Niels Provos, Theo - de Raadt and Dug Song removed many bugs, re-added newer features and - created OpenSSH. Markus Friedl contributed the support for SSH protocol + de Raadt and Dug Song removed many bugs, re-added newer features and cre- + ated OpenSSH. Markus Friedl contributed the support for SSH protocol versions 1.5 and 2.0. Niels Provos and Markus Friedl contributed support - for privilege separation. + for privilege separation. Roumen Petrov contributed support for X.509 + certificates. + +CAVEATS + System security is not improved unless rshd, rlogind, and rexecd are dis- + abled (thus completely disabling rlogin and rsh into the machine). -OpenBSD 7.3 February 10, 2023 OpenBSD 7.3 +BSD 10 February 2023 BSD diff -ruN openssh-9.4p1/sshd.8 openssh-9.4p1+x509-14.2.1/sshd.8 --- openssh-9.4p1/sshd.8 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/sshd.8 2023-08-20 10:07:00.000000000 +0300 @@ -1,3 +1,11 @@ +.\" Implement .Dd with the Mdocdate RCS keyword +.rn Dd xD +.de Dd +.ie \\$1$Mdocdate: \{\ +. xD \\$3 \\$2 \\$4 +.\} +.el .xD \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 +.. .\" .\" Author: Tatu Ylonen .\" Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -12,6 +20,7 @@ .\" Copyright (c) 1999,2000 Markus Friedl. All rights reserved. .\" Copyright (c) 1999 Aaron Campbell. All rights reserved. .\" Copyright (c) 1999 Theo de Raadt. All rights reserved. +.\" Copyright (c) 2002-2022 Roumen Petrov. All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions @@ -39,7 +48,7 @@ .Os .Sh NAME .Nm sshd -.Nd OpenSSH daemon +.Nd Secure shell daemon .Sh SYNOPSIS .Nm sshd .Bk -words @@ -56,7 +65,7 @@ .Ek .Sh DESCRIPTION .Nm -(OpenSSH Daemon) is the daemon program for +(SecSH Daemon) is the daemon program for .Xr ssh 1 . It provides secure encrypted communications between two untrusted hosts over an insecure network. @@ -134,9 +143,7 @@ Debug mode. The server sends verbose debug output to standard error, and does not put itself in the background. -The server also will not -.Xr fork 2 -and will only process one connection. +The server also will not fork and will only process one connection. This option is only intended for debugging for the server. Multiple .Fl d @@ -182,6 +189,12 @@ .Pa /etc/ssh/ssh_host_rsa_key . It is possible to have multiple host key files for the different host key algorithms. +.Pp +For RSA, ECDSA, Ed25519 or DSA host key may contain X.509 certificate that +match it. In addition file may contain extra X.509 certificates. +Extra certificates along with certificates from X.509 store are used +to build chain of certificates leading to a trusted certificate +authority if required by public key algorithm format. .It Fl i Specifies that .Nm @@ -263,7 +276,7 @@ Display the version number and exit. .El .Sh AUTHENTICATION -The OpenSSH SSH daemon supports SSH protocol 2 only. +The SecSH daemon supports SSH protocol 2 only. Each host has a host-specific key, used to identify the host. Whenever a client connects, the daemon responds with its public @@ -282,7 +295,7 @@ The client tries to authenticate itself using host-based authentication, public key authentication, -challenge-response authentication, +keyboard-interactive authentication, or password authentication. .Pp Regardless of the authentication type, the account is checked to @@ -441,6 +454,8 @@ .Pa ~/.ssh/authorized_keys and .Pa ~/.ssh/authorized_keys2 . +Key file may contain X.509 certificates or X.509 certificate +.Dq "Distinguished Name" . Each line of the file contains one key (empty lines and lines starting with a .Ql # @@ -453,16 +468,12 @@ .Pp .Bl -item -compact -offset indent .It -sk-ecdsa-sha2-nistp256@openssh.com -.It ecdsa-sha2-nistp256 .It ecdsa-sha2-nistp384 .It ecdsa-sha2-nistp521 .It -sk-ssh-ed25519@openssh.com -.It ssh-ed25519 .It ssh-dss @@ -472,16 +483,66 @@ .Pp The comment field is not used for anything (but may be convenient for the user to identify the key). +.Dq ssh-rsa . +In addition, user can use X.509 certificates. +In such case keytype is one of: +.Pp +.Bl -item -compact -offset indent +.It +x509v3-rsa2048-sha256 +.It +x509v3-ssh-rsa +.It +x509v3-sign-rsa +.It +x509v3-ecdsa-sha2-nistp256 +.It +x509v3-ecdsa-sha2-nistp384 +.It +x509v3-ecdsa-sha2-nistp521 +.It +x509v3-ssh-dss +.It +x509v3-sign-dss +.It +x509v3-ssh-ed25519 +.El +.Pp +Instead of +.Dq "base64 encoded key" +line must contain base64 encoded X.509 certificate (old style) or +a keyword (new style), optionally followed by symbol +.Sq = +(equal) or +.Sq \&: +(colon), zero or more spaces and X.509 certificate +.Dq "Distinguished Name" +(Subject). Keyword is case insensitive and can be one of +.Sq Subject +, +.Sq "Distinguished Name" +, +.Sq Distinguished-Name +, +.Sq Distinguished_Name +, +.Sq DistinguishedName +or +.Sq DN . +Separator of Subject items can be +.Sq / +(slash), +.Sq \&, +(comma) or mixed and order is not important. .Pp Note that lines in this file can be several hundred bytes long (because of the size of the public key encoding) up to a limit of -8 kilobytes, which permits RSA keys up to 16 kilobits. +8 kilobytes, which permits DSA keys up to 8 kilobits and RSA +keys up to 16 kilobits. You don't want to type them in; instead, copy the .Pa id_dsa.pub , .Pa id_ecdsa.pub , -.Pa id_ecdsa_sk.pub , .Pa id_ed25519.pub , -.Pa id_ed25519_sk.pub , or the .Pa id_rsa.pub file and edit it. @@ -590,7 +651,7 @@ Forbids X11 forwarding when this key is used for authentication. Any X11 forward requests by the client will return an error. .It Cm permitlisten="[host:]port" -Limit remote port forwarding with the +Limit remote port forwarding requested with the .Xr ssh 1 .Fl R option such that it may only listen on the specified host (optional) and port. @@ -616,7 +677,7 @@ and .Dq ::1 . .It Cm permitopen="host:port" -Limit local port forwarding with the +Limit local port forwarding requested with the .Xr ssh 1 .Fl L option such that it may only connect to the specified host and port. @@ -648,20 +709,6 @@ Permits tty allocation previously disabled by the .Cm restrict option. -.It Cm no-touch-required -Do not require demonstration of user presence -for signatures made using this key. -This option only makes sense for the FIDO authenticator algorithms -.Cm ecdsa-sk -and -.Cm ed25519-sk . -.It Cm verify-required -Require that signatures made using this key attest that they verified -the user, e.g. via a PIN. -This option only makes sense for the FIDO authenticator algorithms -.Cm ecdsa-sk -and -.Cm ed25519-sk . .It Cm restrict Enable all restrictions, i.e. disable port, agent and X11 forwarding, as well as disabling PTY allocation @@ -692,8 +739,10 @@ # Comments are allowed at start of line. Blank lines are allowed. # Plain key, no restrictions ssh-rsa ... -# Forced command, disable PTY and all forwarding -restrict,command="dump /home" ssh-rsa ... +# X.509 certificate, no restrictions +x509v3-rsa2048-sha256 subject=/C=XX/ST=World/O=SecSH Test Team... +# Forced command, disable all forwarding, PTY and etc. +restrict,command="uptime" ssh-rsa ... # Restriction of ssh -L forwarding destinations permitopen="192.0.2.1:80",permitopen="192.0.2.2:25" ssh-rsa ... # Restriction of ssh -R forwarding listeners @@ -702,19 +751,15 @@ tunnel="0",command="sh /etc/netstart tun0" ssh-rsa ... # Override of restriction to allow PTY allocation restrict,pty,command="nethack" ssh-rsa ... -# Allow FIDO key without requiring touch -no-touch-required sk-ecdsa-sha2-nistp256@openssh.com ... -# Require user-verification (e.g. PIN or biometric) for FIDO key -verify-required sk-ecdsa-sha2-nistp256@openssh.com ... -# Trust CA key, allow touch-less FIDO if requested in certificate -cert-authority,no-touch-required,principals="user_a" ssh-rsa ... .Ed .Sh SSH_KNOWN_HOSTS FILE FORMAT The .Pa /etc/ssh/ssh_known_hosts and .Pa ~/.ssh/known_hosts -files contain host public keys for all known hosts. +files contain host public keys, X.509 certificates (old style) or X.509 certificate +.Dq "Distinguished Name" +for all known hosts. The global file should be prepared by the administrator (optional), and the per-user file is maintained automatically: whenever the user connects to an unknown host, @@ -830,6 +875,7 @@ .Bd -literal -offset 3n # Comments allowed at start of line cvs.example.net,192.0.2.10 ssh-rsa AAAA1234.....= +x509host x509v3-sign-rsa Subject:/C=XX..... # A hashed hostname |1|JfKTdBh7rNbXkVAQCRp4OQoPfmI=|USECr3SWf1JUPsms5AqfD5QfxkM= ssh-rsa AAAA1234.....= @@ -881,7 +927,10 @@ and not accessible by others. .Pp .It Pa ~/.ssh/authorized_keys -Lists the public keys (DSA, ECDSA, Ed25519, RSA) +Lists the public keys (DSA, ECDSA, Ed25519, RSA), +X.509 certificates or X.509 certificate +.Dq Distinguished Names +(recommended) that can be used for logging in as this user. The format of this file is described above. The content of the file is not highly sensitive, but the recommended @@ -912,7 +961,7 @@ option. .Pp .It Pa ~/.ssh/known_hosts -Contains a list of host keys for all hosts the user has logged into +Contains a list of host keys or X.509 certificates for all hosts the user has logged into that are not already in the systemwide list of known host keys. The format of this file is described above. This file should be writable only by root/the owner and @@ -924,6 +973,12 @@ This file should be writable only by the user, and need not be readable by anyone else. .Pp +.It Pa /etc/hosts.allow +.It Pa /etc/hosts.deny +Access controls that should be enforced by tcp-wrappers are defined here. +Further details are described in +.Xr hosts_access 5 . +.Pp .It Pa /etc/hosts.equiv This file is for host-based authentication (see .Xr ssh 1 ) . @@ -956,10 +1011,33 @@ but allows host-based authentication without permitting login with rlogin/rsh. .Pp +.It Pa /etc/ssh/ca/ca-bundle.crt +.It Pa /etc/ssh/ca/ca-bundle.crl +The first file contain multiple X.509 certificates and the second +.Dq "Certificate Revocation List" +(CRLs) of certificate signers in PEM format concatenated together. +Used to verify and validate client X.509 certificate. +.Pp +.It Pa /etc/ssh/ca/crt +.It Pa /etc/ssh/ca/crl +.Dq "Hash dirs" +with X.509 certificates, the first directory or CLRs, the second, of +X.509 certificate signers. +Each X.509 certificate should be stored in separate file with name +[HASH].[NUMBER] or [HASH].r[NUMBER] for the CRL, where [HASH] is +X.509 certificate or CRL hash value and [NUMBER] is an integer starting +from zero. +Used to verify and validate client X.509 certificate. +.Pp .It Pa /etc/ssh/ssh_host_ecdsa_key .It Pa /etc/ssh/ssh_host_ed25519_key .It Pa /etc/ssh/ssh_host_rsa_key These files contain the private parts of the host keys. +For RSA, ECDSA, Ed25519 or DSA keys file may contain X.509 certificate that +match it. In addition file may contain extra X.509 certificates. +Extra certificates along with certificates from X.509 store are used +to build chain of certificates leading to a trusted certificate +authority if required by public key algorithm format. These files should only be owned by root, readable only by root, and not accessible to others. Note that @@ -973,6 +1051,8 @@ These files should be world-readable but writable only by root. Their contents should match the respective private parts. +Note that when corresponding host key contain X.509 certificate +these files must contains that certificate. These files are not really used for anything; they are provided for the convenience of the user so their contents can be copied to known hosts files. @@ -982,7 +1062,7 @@ .It Pa /etc/ssh/ssh_known_hosts Systemwide list of known host keys. This file should be prepared by the -system administrator to contain the public host keys of all machines in the +system administrator to contain the public host keys or X.509 certificates of all machines in the organization. The format of this file is described above. This file should be writable only by root/the owner and @@ -1026,13 +1106,14 @@ .Xr ssh-keygen 1 , .Xr ssh-keyscan 1 , .Xr chroot 2 , +.Xr hosts_access 5 , .Xr login.conf 5 , .Xr moduli 5 , .Xr sshd_config 5 , .Xr inetd 8 , .Xr sftp-server 8 .Sh AUTHORS -OpenSSH is a derivative of the original and free +PKIX-SSH is a derivative of the original and free ssh 1.2.12 release by Tatu Ylonen. Aaron Campbell, Bob Beck, Markus Friedl, Niels Provos, Theo de Raadt and Dug Song @@ -1042,3 +1123,15 @@ protocol versions 1.5 and 2.0. Niels Provos and Markus Friedl contributed support for privilege separation. +Roumen Petrov contributed support for X.509 certificates. +.Sh CAVEATS +System security is not improved unless +.Nm rshd , +.Nm rlogind , +and +.Nm rexecd +are disabled (thus completely disabling +.Xr rlogin +and +.Xr rsh +into the machine). diff -ruN openssh-9.4p1/sshd.c openssh-9.4p1+x509-14.2.1/sshd.c --- openssh-9.4p1/sshd.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/sshd.c 2023-08-20 10:07:01.000000000 +0300 @@ -20,6 +20,7 @@ * * Copyright (c) 2000, 2001, 2002 Markus Friedl. All rights reserved. * Copyright (c) 2002 Niels Provos. All rights reserved. + * Copyright (c) 2002-2023 Roumen Petrov. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -65,7 +66,11 @@ #endif #include #ifdef HAVE_POLL_H -#include +# include +#else +# ifdef HAVE_SYS_POLL_H +# include +# endif #endif #include #include @@ -80,7 +85,11 @@ #include #include #include -#include "openbsd-compat/openssl-compat.h" +#include "evp-compat.h" +#endif + +#ifdef HAVE_FIPSCHECK_H +# include #endif #ifdef HAVE_SECUREWARE @@ -102,8 +111,11 @@ #include "compat.h" #include "cipher.h" #include "digest.h" +#include "ssh-x509.h" #include "sshkey.h" +#include "ssh-xkalg.h" #include "kex.h" +#include "myproposal.h" #include "authfile.h" #include "pathnames.h" #include "atomicio.h" @@ -124,9 +136,33 @@ #include "auth-options.h" #include "version.h" #include "ssherr.h" -#include "sk-api.h" #include "srclimit.h" -#include "dh.h" + +#ifdef LIBWRAP +#include +#include +int allow_severity; +int deny_severity; +#endif /* LIBWRAP */ + +#if 0 +/* Random seed after closefrom() breaks daemon functionality. + * Failure it not common. For instance "reexec" regression test may + * fail in audit enabled builds. + * + * Remark: + * Postponed random seed is work-around for random generator provided + * by some engine, i.e. these that open descriptors for their own use. + * + * NOTE: If random seed is postponed reexec functionality may clobber + * file descriptors. Re-exec is based on hard-coded descriptor numbers + * and that all descriptors after certain number are closed. + * For instance OpenSSL 1.1.1* may keep random device file descriptors + * open. In such case postponed random seed change numbers used. In + * consequence hard-coded "reexec" number may clash with used. + */ +# define POSTPONE_RANDOM_SEED +#endif /* Re-exec fds */ #define REEXEC_DEVCRYPTO_RESERVED_FD (STDERR_FILENO + 1) @@ -136,6 +172,12 @@ extern char *__progname; +extern void dh_set_moduli_file(const char *); + +/* used in ssh-x509.c */ +extern int (*pssh_x509store_verify_cert)(X509 *cert, STACK_OF(X509) *untrusted); +extern STACK_OF(X509)* (*pssh_x509store_build_certchain)(X509 *cert, STACK_OF(X509) *untrusted); + /* Server configuration options. */ ServerOptions options; @@ -165,7 +207,7 @@ static int no_daemon_flag = 0; /* debug goes to stderr unless inetd_flag is set */ -static int log_stderr = 0; +int log_stderr = 0; /* Saved arguments to main(). */ static char **saved_argv; @@ -200,6 +242,7 @@ struct { struct sshkey **host_keys; /* all private host keys */ struct sshkey **host_pubkeys; /* all public host keys */ + const char ***host_algorithms; /* all public-key algorithms per host key */ struct sshkey **host_certificates; /* all public host certificates */ int have_ssh2_key; } sensitive_data; @@ -240,7 +283,7 @@ /* global connection state and authentication contexts */ Authctxt *the_authctxt = NULL; -struct ssh *the_active_state; +static struct ssh *the_active_state = NULL; /* global key/cert auth options. XXX move to permanent ssh->authctxt? */ struct sshauthopt *auth_opts = NULL; @@ -264,6 +307,17 @@ static char *listener_proctitle; +static inline struct ssh* +create_session(int fd_in, int fd_out) +{ + the_active_state = ssh_packet_set_connection(NULL, fd_in, fd_out); + if (the_active_state == NULL) + fatal_f("ssh_packet_set_connection failed"); + + ssh_packet_set_server(the_active_state); + return the_active_state; +} + /* * Close all listening sockets */ @@ -297,6 +351,7 @@ static void sighup_handler(int sig) { + UNUSED(sig); received_sighup = 1; } @@ -340,6 +395,7 @@ pid_t pid; int status; + UNUSED(sig); while ((pid = waitpid(-1, &status, WNOHANG)) > 0 || (pid == -1 && errno == EINTR)) ; @@ -352,6 +408,16 @@ static void grace_alarm_handler(int sig) { + UNUSED(sig); +#if 0 +/* NOTE: "OpenSSH bug 3286". See sshsigdie() in log.c + * PKIX-SSH was not impacted as it does not activate logs in sigdie. + * With removing explicit send of alarm signal log is activated. + */ + if (use_privsep && pmonitor != NULL && pmonitor->m_pid > 0) + kill(pmonitor->m_pid, SIGALRM); +#endif + /* * Try to kill any processes that we have spawned, E.g. authorized * keys command helpers or privsep children. @@ -367,6 +433,28 @@ ssh_remote_port(the_active_state)); } +static int +prepare_server_banner(struct ssh *ssh) +{ + const char *fips = ""; + int r; + +#ifdef OPENSSL_FIPS + if (FIPS_mode()) fips= " FIPS"; +#endif + + /* NOTE: Version string is prepared and sent with at end. + * After identification exchange trailing is removed for + * further use in key exchange messages. + */ + r = sshbuf_putf(ssh->kex->server_version, + "SSH-%d.%d-%s PKIX["PACKAGE_VERSION"%s]%s%s\r\n", + PROTOCOL_MAJOR_2, PROTOCOL_MINOR_2, SSH_VERSION, fips, + *options.version_addendum == '\0' ? "" : " ", + options.version_addendum); + return r; +} + /* Destroy the host and server keys. They will no longer be needed. */ void destroy_sensitive_data(void) @@ -420,8 +508,8 @@ #ifdef WITH_OPENSSL RAND_seed(rnd, sizeof(rnd)); /* give libcrypto a chance to notice the PID change */ - if ((RAND_bytes((u_char *)rnd, 1)) != 1) - fatal("%s: RAND_bytes failed", __func__); + if ((RAND_bytes((u_char *)rnd, 1)) <= 0) + fatal_f("RAND_bytes failed"); #endif explicit_bzero(rnd, sizeof(rnd)); @@ -432,7 +520,7 @@ { gid_t gidset[1]; - /* Enable challenge-response authentication for privilege separation */ + /* Enable keyboard-interactive devices for privilege separation */ privsep_challenge_enable(); #ifdef GSSAPI @@ -554,7 +642,7 @@ else if (pmonitor->m_pid != 0) { verbose("User child is on pid %ld", (long)pmonitor->m_pid); sshbuf_reset(loginmsg); - monitor_clear_keystate(ssh, pmonitor); + monitor_clear_keystate(ssh); monitor_child_postauth(ssh, pmonitor); /* NEVERREACHED */ @@ -576,7 +664,7 @@ skip: /* It is safe now to apply the key state */ - monitor_apply_keystate(ssh, pmonitor); + monitor_apply_keystate(ssh); /* * Tell the packet layer that authentication was successful, since @@ -586,6 +674,42 @@ } static void +add_hostkey_algoritms(int k, struct sshbuf *b) { + const char **algs; + + algs = sensitive_data.host_algorithms[k]; + if (algs == NULL) { + debug("no suitable algorithms for host key %d", k); + return; + } + + for (; *algs != NULL; algs++) { + const char *pkalg = *algs; + + /* Check that the key is accepted in HostkeyAlgorithms */ + if (match_pattern_list(pkalg, + options.hostkeyalgorithms, 0) != 1 + ) { + debug3_f("%s not permitted by " + "HostkeyAlgorithms for key %d", + pkalg, k); + continue; + } + + if (sshbuf_len(b) > 0) { + if (sshbuf_put(b, ",", 1) != 0) + goto err; + } + if (sshbuf_put(b, pkalg, strlen(pkalg)) != 0) + goto err; + } + + return; +err: + fatal("cannot prepare hotkey algorithm list"); +} + +static void append_hostkey_type(struct sshbuf *b, const char *s) { int r; @@ -614,21 +738,9 @@ key = sensitive_data.host_pubkeys[i]; if (key == NULL) continue; - switch (key->type) { - case KEY_RSA: - /* for RSA we also support SHA2 signatures */ - append_hostkey_type(b, "rsa-sha2-512"); - append_hostkey_type(b, "rsa-sha2-256"); - /* FALLTHROUGH */ - case KEY_DSA: - case KEY_ECDSA: - case KEY_ED25519: - case KEY_ECDSA_SK: - case KEY_ED25519_SK: - case KEY_XMSS: - append_hostkey_type(b, sshkey_ssh_name(key)); - break; - } + + add_hostkey_algoritms(i, b); + /* If the private key has a cert peer, then list that too */ key = sensitive_data.host_certificates[i]; if (key == NULL) @@ -637,15 +749,13 @@ case KEY_RSA_CERT: /* for RSA we also support SHA2 signatures */ append_hostkey_type(b, - "rsa-sha2-512-cert-v01@openssh.com"); - append_hostkey_type(b, "rsa-sha2-256-cert-v01@openssh.com"); + append_hostkey_type(b, + "rsa-sha2-512-cert-v01@openssh.com"); /* FALLTHROUGH */ case KEY_DSA_CERT: case KEY_ECDSA_CERT: case KEY_ED25519_CERT: - case KEY_ECDSA_SK_CERT: - case KEY_ED25519_SK_CERT: case KEY_XMSS_CERT: append_hostkey_type(b, sshkey_ssh_name(key)); break; @@ -659,19 +769,18 @@ } static struct sshkey * -get_hostkey_by_type(int type, int nid, int need_private, struct ssh *ssh) +get_hostkey_by_type(int type, int subtype, int need_private, struct ssh *ssh) { u_int i; struct sshkey *key; + UNUSED(ssh); for (i = 0; i < options.num_host_key_files; i++) { switch (type) { case KEY_RSA_CERT: case KEY_DSA_CERT: case KEY_ECDSA_CERT: case KEY_ED25519_CERT: - case KEY_ECDSA_SK_CERT: - case KEY_ED25519_SK_CERT: case KEY_XMSS_CERT: key = sensitive_data.host_certificates[i]; break; @@ -681,50 +790,94 @@ key = sensitive_data.host_pubkeys[i]; break; } - if (key == NULL || key->type != type) - continue; - switch (type) { - case KEY_ECDSA: - case KEY_ECDSA_SK: - case KEY_ECDSA_CERT: - case KEY_ECDSA_SK_CERT: - if (key->ecdsa_nid != nid) - continue; - /* FALLTHROUGH */ - default: + if (key != NULL && key->type == type && + (subtype == -1 || subtype == key->ecdsa_nid) + ) return need_private ? sensitive_data.host_keys[i] : key; + } + return NULL; +} + +static struct sshkey* +get_hostkey_by_alg(const char* alg, int need_private, struct ssh *ssh) { + u_int i; + struct sshkey *key; + + UNUSED(ssh); + for (i = 0; i < options.num_host_key_files; i++) { + key = sensitive_data.host_keys[i]; + if (key == NULL && !need_private) + key = sensitive_data.host_pubkeys[i]; + + if (key == NULL) continue; + + { const char **s; + for (s = sensitive_data.host_algorithms[i]; + *s != NULL; s++) { + if (strcmp(alg, *s) == 0) + break; } + if (*s != NULL) + return need_private ? + sensitive_data.host_keys[i] : key; + } } return NULL; } struct sshkey * -get_hostkey_public_by_type(int type, int nid, struct ssh *ssh) +get_hostkey_public_by_alg(const char* alg, struct ssh *ssh) { - return get_hostkey_by_type(type, nid, 0, ssh); + struct sshkey *key; + + key = get_hostkey_by_alg(alg, 0, ssh); + if (key != NULL) return key; + +{ int keytype, subtype; + sshkey_types_from_name(alg, &keytype, &subtype); + return get_hostkey_by_type(keytype, subtype, 0, ssh); +} } struct sshkey * -get_hostkey_private_by_type(int type, int nid, struct ssh *ssh) +get_hostkey_private_by_alg(const char* alg, struct ssh *ssh) { - return get_hostkey_by_type(type, nid, 1, ssh); + struct sshkey *key; + + key = get_hostkey_by_alg(alg, 1, ssh); + if (key != NULL) return key; + +{ int keytype, subtype; + sshkey_types_from_name(alg, &keytype, &subtype); + return get_hostkey_by_type(keytype, subtype, 1, ssh); +} } struct sshkey * -get_hostkey_by_index(int ind) +get_hostkey_by_index(u_int ind) { - if (ind < 0 || (u_int)ind >= options.num_host_key_files) - return (NULL); - return (sensitive_data.host_keys[ind]); + return ind < options.num_host_key_files + ? sensitive_data.host_keys[ind] + : NULL; } struct sshkey * -get_hostkey_public_by_index(int ind, struct ssh *ssh) +get_hostkey_public_by_index(u_int ind, struct ssh *ssh) { - if (ind < 0 || (u_int)ind >= options.num_host_key_files) - return (NULL); - return (sensitive_data.host_pubkeys[ind]); + UNUSED(ssh); + return ind < options.num_host_key_files + ? sensitive_data.host_pubkeys[ind] + : NULL; +} + +static const char** +get_hostkey_alg_by_index(u_int ind, struct ssh *ssh) +{ + UNUSED(ssh); + return ind < options.num_host_key_files + ? sensitive_data.host_algorithms[ind] + : NULL; } int @@ -732,6 +885,7 @@ { u_int i; + UNUSED(ssh); for (i = 0; i < options.num_host_key_files; i++) { if (sshkey_is_cert(key)) { if (key == sensitive_data.host_certificates[i] || @@ -742,11 +896,11 @@ } else { if (key == sensitive_data.host_keys[i] || (compare && sensitive_data.host_keys[i] && - sshkey_equal(key, sensitive_data.host_keys[i]))) + sshkey_equal_public(key, sensitive_data.host_keys[i]))) return (i); if (key == sensitive_data.host_pubkeys[i] || (compare && sensitive_data.host_pubkeys[i] && - sshkey_equal(key, sensitive_data.host_pubkeys[i]))) + sshkey_equal_public(key, sensitive_data.host_pubkeys[i]))) return (i); } } @@ -764,21 +918,37 @@ char *fp; /* Some clients cannot cope with the hostkeys message, skip those. */ - if (ssh->compat & SSH_BUG_HOSTKEYS) + if (ssh_compat_fellows(ssh, SSH_BUG_HOSTKEYS)) return; if ((buf = sshbuf_new()) == NULL) fatal_f("sshbuf_new"); for (i = nkeys = 0; i < options.num_host_key_files; i++) { + const char* pkalg; key = get_hostkey_public_by_index(i, ssh); if (key == NULL || key->type == KEY_UNSPEC || sshkey_is_cert(key)) continue; fp = sshkey_fingerprint(key, options.fingerprint_hash, SSH_FP_DEFAULT); - debug3_f("key %d: %s %s", i, sshkey_ssh_name(key), fp); - free(fp); - if (nkeys == 0) { + +{ /* Note rsa-sha2-256 and rsa-sha2-512 public key algorithms + * use same key blob format as ssh-rsa! + */ + const char *rsa_patern = "ssh-rsa,rsa-sha2-256,rsa-sha2-512"; + const char **key_algs = get_hostkey_alg_by_index(i, ssh); + int n_algs, rsa_format = 0; + + for (n_algs = 0; key_algs[n_algs] != NULL; n_algs++) { + pkalg = key_algs[n_algs]; + if (match_pattern_list(pkalg, rsa_patern, 0) == 1) { + if (rsa_format) continue; + rsa_format = 1; + pkalg = "ssh-rsa"; + } + + debug3_f("key %d: %s %s", i, pkalg, fp); + if (nkeys == 0 && n_algs == 0) { /* * Start building the request when we find the * first usable key. @@ -790,10 +960,13 @@ } /* Append the key to the request */ sshbuf_reset(buf); - if ((r = sshkey_putb(key, buf)) != 0) + if ((r = Xkey_putb(pkalg, key, buf)) != 0) fatal_fr(r, "couldn't put hostkey %d", i); if ((r = sshpkt_put_stringb(ssh, buf)) != 0) sshpkt_fatal(ssh, r, "%s: append key", __func__); + } +} + free(fp); nkeys++; } debug3_f("sent %u hostkeys", nkeys); @@ -842,59 +1015,61 @@ static int drop_connection(int sock, int startups, int notify_pipe) { - char *laddr, *raddr; - const char msg[] = "Exceeded MaxStartups\r\n"; - static time_t last_drop, first_drop; - static u_int ndropped; - LogLevel drop_level = SYSLOG_LEVEL_VERBOSE; - time_t now; + static u_int ndropped = 0; + static time_t first_drop, last_drop; - now = monotime(); if (!should_drop_connection(startups) && srclimit_check_allow(sock, notify_pipe) == 1) { - if (last_drop != 0 && - startups < options.max_startups_begin - 1) { + if (ndropped == 0) return 0; + + if (startups < options.max_startups_begin - 1) { + char *t = fmttime(monotime() - first_drop); /* XXX maybe need better hysteresis here */ logit("exited MaxStartups throttling after %s, " - "%u connections dropped", - fmt_timeframe(now - first_drop), ndropped); - last_drop = 0; + "%u connections dropped", t, ndropped); + free(t); } + ndropped = 0; return 0; } #define SSHD_MAXSTARTUPS_LOG_INTERVAL (5 * 60) - if (last_drop == 0) { +{ time_t now = monotime(); + + if (ndropped++ == 0) { error("beginning MaxStartups throttling"); - drop_level = SYSLOG_LEVEL_INFO; first_drop = now; - ndropped = 0; } else if (last_drop + SSHD_MAXSTARTUPS_LOG_INTERVAL < now) { /* Periodic logs */ + char *t = fmttime(now - first_drop); error("in MaxStartups throttling for %s, " - "%u connections dropped", - fmt_timeframe(now - first_drop), ndropped + 1); - drop_level = SYSLOG_LEVEL_INFO; + "%u connections dropped", t, ndropped); + free(t); } last_drop = now; - ndropped++; +} +{ + char *laddr = get_local_ipaddr(sock); + char *raddr = get_peer_ipaddr(sock); + const char msg[] = "Exceeded MaxStartups\r\n"; - laddr = get_local_ipaddr(sock); - raddr = get_peer_ipaddr(sock); - do_log2(drop_level, "drop connection #%d from [%s]:%d on [%s]:%d " - "past MaxStartups", startups, raddr, get_peer_port(sock), + verbose("drop connection #%d " + "from [%s]:%d on [%s]:%d past MaxStartups", + startups, + raddr, get_peer_port(sock), laddr, get_local_port(sock)); free(laddr); free(raddr); /* best-effort notification to client */ (void)write(sock, msg, sizeof(msg) - 1); +} return 1; } static void usage(void) { - fprintf(stderr, "%s, %s\n", SSH_RELEASE, SSH_OPENSSL_VERSION); + fprintf(stderr, "%s, %s\n", SSH_RELEASE, ssh_OpenSSL_version_text()); fprintf(stderr, "usage: sshd [-46DdeGiqTtV] [-C connection_spec] [-c host_cert_file]\n" " [-E log_file] [-f config_file] [-g login_grace_time]\n" @@ -936,6 +1111,7 @@ if ((r = sshbuf_put_stringb(m, conf)) != 0 || (r = sshbuf_put_stringb(m, inc)) != 0) fatal_fr(r, "compose config"); + if (ssh_msg_send(fd, 0, m) == -1) error_f("ssh_msg_send failed"); @@ -1119,7 +1295,6 @@ int i, j, ret, npfd; int ostartups = -1, startups = 0, listening = 0, lameduck = 0; int startup_p[2] = { -1 , -1 }, *startup_pollfd; - char c = 0; struct sockaddr_storage from; socklen_t fromlen; pid_t pid; @@ -1207,10 +1382,13 @@ continue; for (i = 0; i < options.max_startups; i++) { + char c = 0; + if (startup_pipes[i] == -1 || startup_pollfd[i] == -1 || !(pfd[startup_pollfd[i]].revents & (POLLIN|POLLHUP))) continue; + switch (read(startup_pipes[i], &c, sizeof(c))) { case -1: if (errno == EINTR || errno == EAGAIN) @@ -1227,8 +1405,10 @@ srclimit_done(startup_pipes[i]); startup_pipes[i] = -1; startups--; - if (startup_flags[i]) + if (startup_flags[i]) { listening--; + startup_flags[i] = 0; + } break; case 1: /* child has finished preliminaries */ @@ -1240,7 +1420,7 @@ } } for (i = 0; i < num_listen_socks; i++) { - if (!(pfd[i].revents & POLLIN)) + if (!(pfd[i].revents & (POLLIN|POLLHUP))) continue; fromlen = sizeof(from); *newsock = accept(listen_socks[i], @@ -1381,8 +1561,8 @@ arc4random_buf(rnd, sizeof(rnd)); #ifdef WITH_OPENSSL RAND_seed(rnd, sizeof(rnd)); - if ((RAND_bytes((u_char *)rnd, 1)) != 1) - fatal("%s: RAND_bytes failed", __func__); + if ((RAND_bytes((u_char *)rnd, 1)) <= 0) + fatal_f("RAND_bytes failed"); #endif explicit_bzero(rnd, sizeof(rnd)); } @@ -1419,7 +1599,7 @@ /* XXX IPv6 options? */ if (getsockopt(sock_in, IPPROTO_IP, IP_OPTIONS, opts, - &option_size) >= 0 && option_size != 0) { + &option_size) != -1 && option_size != 0) { text[0] = '\0'; for (i = 0; i < option_size; i++) snprintf(text + i*3, sizeof(text) - i*3, @@ -1431,6 +1611,7 @@ #endif /* IP_OPTIONS */ } +#ifdef ENABLE_ROUTING_DOMAIN /* Set the routing domain for this process */ static void set_process_rdomain(struct ssh *ssh, const char *name) @@ -1446,7 +1627,7 @@ } /* NB. We don't pass 'ssh' to sys_set_process_rdomain() */ return sys_set_process_rdomain(name); -#elif defined(__OpenBSD__) +#elif defined(HAVE_SETRTABLE) int rtable, ortable = getrtable(); const char *errstr; @@ -1466,29 +1647,35 @@ fatal("Unable to set routing domain %d: %s", rtable, strerror(errno)); debug_f("set routing domain %d (was %d)", rtable, ortable); -#else /* defined(__OpenBSD__) */ +#else /* defined(HAVE_SETRTABLE) */ + /*unreachable*/ + UNUSED(ssh); + UNUSED(name); fatal("Unable to set routing domain: not supported in this platform"); #endif } +#endif /*def ENABLE_ROUTING_DOMAIN*/ static void accumulate_host_timing_secret(struct sshbuf *server_cfg, struct sshkey *key) { - static struct ssh_digest_ctx *ctx; + static struct ssh_digest_ctx *ctx = NULL; + int digest_alg; u_char *hash; size_t len; struct sshbuf *buf; int r; - if (ctx == NULL && (ctx = ssh_digest_start(SSH_DIGEST_SHA512)) == NULL) + digest_alg = ssh_digest_maxbytes(); + if (ctx == NULL && (ctx = ssh_digest_start(digest_alg)) == NULL) fatal_f("ssh_digest_start"); if (key == NULL) { /* finalize */ /* add server config in case we are using agent for host keys */ if (ssh_digest_update(ctx, sshbuf_ptr(server_cfg), sshbuf_len(server_cfg)) != 0) fatal_f("ssh_digest_update"); - len = ssh_digest_bytes(SSH_DIGEST_SHA512); + len = ssh_digest_bytes(digest_alg); hash = xmalloc(len); if (ssh_digest_final(ctx, hash, len) != 0) fatal_f("ssh_digest_final"); @@ -1556,15 +1743,32 @@ int keytype; Authctxt *authctxt; struct connection_info *connection_info = NULL; - sigset_t sigmask; + + ssh_malloc_init(); /* must be called before any mallocs */ #ifdef HAVE_SECUREWARE (void)set_auth_parameters(ac, av); #endif __progname = ssh_get_progname(av[0]); + ssh_OpenSSL_startup(); +#ifdef OPENSSL_FIPS + if (FIPS_mode()) { + #ifdef HAVE_FIPSCHECK_H + if (!FIPSCHECK_verify(NULL, NULL)) + fatal("FIPS integrity verification test failed."); + #endif + fprintf(stderr, "%s runs in FIPS mode\n", __progname); + } +#endif /*def OPENSSL_FIPS*/ + pssh_x509store_verify_cert = ssh_x509store_verify_cert; + pssh_x509store_build_certchain = ssh_x509store_build_certchain; + +/* work-around for environments that fail to clear masked signal on fork or exec */ +{ sigset_t sigmask; sigemptyset(&sigmask); sigprocmask(SIG_SETMASK, &sigmask, NULL); +} /* Save argv. Duplicate so setproctitle emulation doesn't clobber it */ saved_argc = ac; @@ -1586,6 +1790,18 @@ /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ sanitise_stdfd(); +#ifdef HAVE_RAND_KEEP_RANDOM_DEVICES_OPEN + /* Disable the retention of file descriptors used as random seed + * sources - ensure consistent OpenSSL functionality between + * different OS version, releases and event build configurations. + * Note this is OpenSSL pre 1.1.1 functionality. + */ + RAND_keep_random_devices_open(0); +#endif +#ifndef POSTPONE_RANDOM_SEED + seed_rng(); +#endif + /* Initialize configuration options to their default values. */ initialize_server_options(&options); @@ -1657,11 +1873,19 @@ } break; case 'g': - if ((options.login_grace_time = convtime(optarg)) == -1) { + { long t = convtime(optarg); + if (t == -1) { fprintf(stderr, "Invalid login grace time.\n"); exit(1); } - break; + #if SIZEOF_LONG_INT > SIZEOF_INT + if (t > INT_MAX) { + fprintf(stderr, "Login grace time too high.\n"); + exit(1); + } + #endif + options.login_grace_time = (int)t; /*safe cast*/ + } break; case 'k': /* protocol 1, ignored */ break; @@ -1697,7 +1921,7 @@ break; case 'V': fprintf(stderr, "%s, %s\n", - SSH_VERSION, SSH_OPENSSL_VERSION); + SSH_RELEASE, ssh_OpenSSL_version_text()); exit(0); default: usage(); @@ -1713,7 +1937,9 @@ else closefrom(REEXEC_DEVCRYPTO_RESERVED_FD); +#ifdef POSTPONE_RANDOM_SEED seed_rng(); +#endif /* If requested, redirect the logs to the specified logfile. */ if (logfile != NULL) @@ -1810,7 +2036,7 @@ exit(1); } - debug("sshd version %s, %s", SSH_VERSION, SSH_OPENSSL_VERSION); + debug("sshd version %s, %s", SSH_RELEASE, ssh_OpenSSL_version_text()); if (do_dump_cfg) print_config(ssh, connection_info); @@ -1833,6 +2059,8 @@ sizeof(struct sshkey *)); sensitive_data.host_pubkeys = xcalloc(options.num_host_key_files, sizeof(struct sshkey *)); + sensitive_data.host_algorithms = xcalloc(options.num_host_key_files, + sizeof(const char **)); if (options.host_key_agent) { if (strcmp(options.host_key_agent, SSH_AUTHSOCKET_ENV_NAME)) @@ -1855,14 +2083,7 @@ &key, NULL)) != 0 && r != SSH_ERR_SYSTEM_ERROR) do_log2_r(r, ll, "Unable to load host key \"%s\"", options.host_key_files[i]); - if (sshkey_is_sk(key) && - key->sk_flags & SSH_SK_USER_PRESENCE_REQD) { - debug("host key %s requires user presence, ignoring", - options.host_key_files[i]); - key->sk_flags &= ~SSH_SK_USER_PRESENCE_REQD; - } - if (r == 0 && key != NULL && - (r = sshkey_shield_private(key)) != 0) { + if (r == 0 && (r = sshkey_shield_private(key)) != 0) { do_log2_r(r, ll, "Unable to shield host key \"%s\"", options.host_key_files[i]); sshkey_free(key); @@ -1885,15 +2106,18 @@ fatal_r(r, "Could not demote key: \"%s\"", options.host_key_files[i]); } - if (pubkey != NULL && (r = sshkey_check_rsa_length(pubkey, - options.required_rsa_size)) != 0) { + #if 0 + /* NOTE: key size is validated on read, sign and verify */ + if (pubkey != NULL && (r = sshkey_check_length(pubkey)) != 0) { error_fr(r, "Host key %s", options.host_key_files[i]); sshkey_free(pubkey); sshkey_free(key); continue; } + #endif sensitive_data.host_keys[i] = key; sensitive_data.host_pubkeys[i] = pubkey; + sensitive_data.host_algorithms[i] = Xkey_algoriths(pubkey); if (key == NULL && pubkey != NULL && have_agent) { debug("will rely on agent for hostkey %s", @@ -1915,8 +2139,6 @@ case KEY_DSA: case KEY_ECDSA: case KEY_ED25519: - case KEY_ECDSA_SK: - case KEY_ED25519_SK: case KEY_XMSS: if (have_agent || key != NULL) sensitive_data.have_ssh2_key = 1; @@ -2011,7 +2233,7 @@ * to create a file, and we can't control the code in every * module which might be used). */ - if (setgroups(0, NULL) < 0) + if (setgroups(0, NULL) == -1) debug("setgroups() failed: %.200s", strerror(errno)); if (rexec_flag) { @@ -2034,10 +2256,8 @@ /* Initialize the log (it is reinitialized below in case we forked). */ if (debug_flag && (!inetd_flag || rexeced_flag)) log_stderr = 1; - log_init(__progname, options.log_level, - options.log_facility, log_stderr); - for (i = 0; i < options.num_log_verbose; i++) - log_verbose_add(options.log_verbose[i]); + log_init(__progname, options.log_level, options.log_facility, log_stderr); + log_verbose_init(options.log_verbose, options.num_log_verbose); /* * If not in debugging mode, not started from inetd and not already @@ -2113,20 +2333,20 @@ debug("rexec start in %d out %d newsock %d pipe %d sock %d", sock_in, sock_out, newsock, startup_pipe, config_s[0]); if (dup2(newsock, STDIN_FILENO) == -1) - debug3_f("dup2 stdin: %s", strerror(errno)); + error("dup2 reexec stdin: %s", strerror(errno)); if (dup2(STDIN_FILENO, STDOUT_FILENO) == -1) - debug3_f("dup2 stdout: %s", strerror(errno)); + error("dup2 reexec, stdout: %s", strerror(errno)); if (startup_pipe == -1) close(REEXEC_STARTUP_PIPE_FD); else if (startup_pipe != REEXEC_STARTUP_PIPE_FD) { if (dup2(startup_pipe, REEXEC_STARTUP_PIPE_FD) == -1) - debug3_f("dup2 startup_p: %s", strerror(errno)); + error("dup2 reexec startup: %s", strerror(errno)); close(startup_pipe); startup_pipe = REEXEC_STARTUP_PIPE_FD; } if (dup2(config_s[1], REEXEC_CONFIG_PASS_FD) == -1) - debug3_f("dup2 config_s: %s", strerror(errno)); + error("dup2 reexec config: %s", strerror(errno)); close(config_s[1]); ssh_signal(SIGHUP, SIG_IGN); /* avoid reset to SIG_DFL */ @@ -2148,8 +2368,8 @@ } /* Executed child processes don't need these. */ - fcntl(sock_out, F_SETFD, FD_CLOEXEC); - fcntl(sock_in, F_SETFD, FD_CLOEXEC); + (void)fcntl(sock_out, F_SETFD, FD_CLOEXEC); + (void)fcntl(sock_in, F_SETFD, FD_CLOEXEC); /* We will not restart on SIGHUP since it no longer makes sense. */ ssh_signal(SIGALRM, SIG_DFL); @@ -2163,10 +2383,7 @@ * Register our connection. This turns encryption off because we do * not have a key. */ - if ((ssh = ssh_packet_set_connection(NULL, sock_in, sock_out)) == NULL) - fatal("Unable to create connection"); - the_active_state = ssh; - ssh_packet_set_server(ssh); + ssh = create_session(sock_in, sock_out); check_ip_options(ssh); @@ -2186,8 +2403,10 @@ cleanup_exit(255); } +#ifdef ENABLE_ROUTING_DOMAIN if (options.routing_domain != NULL) set_process_rdomain(ssh, options.routing_domain); +#endif /* * The rest of the code depends on the fact that @@ -2199,6 +2418,24 @@ #ifdef SSH_AUDIT_EVENTS audit_connection_from(remote_ip, remote_port); #endif +#ifdef LIBWRAP + allow_severity = options.log_facility|LOG_INFO; + deny_severity = options.log_facility|LOG_WARNING; + /* Check whether logins are denied from this host. */ + if (ssh_packet_connection_is_on_socket(ssh)) { + struct request_info req; + + request_init(&req, RQ_DAEMON, __progname, RQ_FILE, sock_in, 0); + fromhost(&req); + + if (!hosts_access(&req)) { + debug("Connection refused by tcp wrapper"); + refuse(&req); + /* NOTREACHED */ + fatal("libwrap refuse returns"); + } + } +#endif /* LIBWRAP */ rdomain = ssh_packet_rdomain_in(ssh); @@ -2223,8 +2460,10 @@ if (!debug_flag) alarm(options.login_grace_time); - if ((r = kex_exchange_identification(ssh, -1, - options.version_addendum)) != 0) + if ((r = prepare_server_banner(ssh)) != 0) + sshpkt_fatal(ssh, r, "prepare server banner"); + + if ((r = kex_exchange_identification(ssh, -1)) != 0) sshpkt_fatal(ssh, r, "banner exchange"); ssh_packet_set_nonblocking(ssh); @@ -2337,7 +2576,9 @@ PRIVSEP(audit_event(ssh, SSH_CONNECTION_CLOSE)); #endif - ssh_packet_close(ssh); + the_active_state = NULL; + (void)ssh_packet_close(ssh); + free(ssh); if (use_privsep) mm_terminate(); @@ -2346,35 +2587,46 @@ } int -sshd_hostkey_sign(struct ssh *ssh, struct sshkey *privkey, - struct sshkey *pubkey, u_char **signature, size_t *slenp, - const u_char *data, size_t dlen, const char *alg) -{ +Xsshd_hostkey_sign( + struct ssh *ssh, ssh_sign_ctx *ctx, struct sshkey *pubkey, + u_char **signature, size_t *slenp, const u_char *data, size_t dlen +) { int r; if (use_privsep) { - if (privkey) { - if (mm_sshkey_sign(ssh, privkey, signature, slenp, - data, dlen, alg, options.sk_provider, NULL, - ssh->compat) < 0) - fatal_f("privkey sign failed"); + if (ctx->key) { + r = mm_Xkey_sign(ssh, ctx, signature, slenp, data, dlen); + if (r != 0) + fatal_fr(r, "Xkey_sign failed"); } else { - if (mm_sshkey_sign(ssh, pubkey, signature, slenp, - data, dlen, alg, options.sk_provider, NULL, - ssh->compat) < 0) - fatal_f("pubkey sign failed"); + ssh_sign_ctx mm_ctx = { ctx->alg, pubkey, ctx->compat, + ctx->provider, ctx->pin }; + r = mm_Xkey_sign(ssh, &mm_ctx, signature, slenp, data, dlen); + if (r != 0) + fatal_fr(r, "pubkey Xkey_sign failed"); } } else { - if (privkey) { - if (sshkey_sign(privkey, signature, slenp, data, dlen, - alg, options.sk_provider, NULL, ssh->compat) < 0) - fatal_f("privkey sign failed"); + if (ctx->key) { + r = Xkey_sign(ctx, signature, slenp, data, dlen); + if (r != 0) + fatal_fr(r, "Xkey_sign failed"); } else { - if ((r = ssh_agent_sign(auth_sock, pubkey, - signature, slenp, data, dlen, alg, - ssh->compat)) != 0) { - fatal_fr(r, "agent sign failed"); - } + ssh_sign_ctx a_ctx = { ctx->alg, NULL, ctx->compat, + ctx->provider, ctx->pin }; + /* mimic logic in priviledged mode */ + if (sshkey_is_cert(pubkey)) { + int nxd = get_hostkey_index(pubkey, 0, ssh); + if (nxd < 0) + fatal_f("missing custom certificate"); + pubkey = get_hostkey_public_by_index(nxd, ssh); + if (pubkey == NULL) + fatal_f("missing public key"); + } + a_ctx.key = pubkey; + r = Xssh_agent_sign(auth_sock, &a_ctx, signature, slenp, + data, dlen); + if (r != 0) + fatal_fr(r, "Xssh_agent_sign failed"); } } return 0; @@ -2384,58 +2636,54 @@ static void do_ssh2_kex(struct ssh *ssh) { - char *hkalgs = NULL, *myproposal[PROPOSAL_MAX]; - const char *compression = NULL; + char *myproposal[PROPOSAL_MAX] = { KEX_SERVER }; struct kex *kex; + char *prop_kex = NULL, *prop_enc = NULL, *prop_hostkey = NULL; int r; if (options.rekey_limit || options.rekey_interval) ssh_packet_set_rekey_limits(ssh, options.rekey_limit, options.rekey_interval); - if (options.compression == COMP_NONE) - compression = "none"; - hkalgs = list_hostkey_types(); - - kex_proposal_populate_entries(ssh, myproposal, options.kex_algorithms, - options.ciphers, options.macs, compression, hkalgs); + myproposal[PROPOSAL_KEX_ALGS] = prop_kex = + compat_kex_proposal(ssh, options.kex_algorithms); + myproposal[PROPOSAL_ENC_ALGS_CTOS] = + myproposal[PROPOSAL_ENC_ALGS_STOC] = prop_enc = + xstrdup(options.ciphers); + myproposal[PROPOSAL_MAC_ALGS_CTOS] = + myproposal[PROPOSAL_MAC_ALGS_STOC] = options.macs; + + if (options.compression == COMP_NONE) { + myproposal[PROPOSAL_COMP_ALGS_CTOS] = + myproposal[PROPOSAL_COMP_ALGS_STOC] = "none"; + } - free(hkalgs); + myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = prop_hostkey = + xstrdup(list_hostkey_types()); /* start key exchange */ if ((r = kex_setup(ssh, myproposal)) != 0) - fatal_r(r, "kex_setup"); + fatal_fr(r, "kex_setup"); kex = ssh->kex; -#ifdef WITH_OPENSSL - kex->kex[KEX_DH_GRP1_SHA1] = kex_gen_server; - kex->kex[KEX_DH_GRP14_SHA1] = kex_gen_server; - kex->kex[KEX_DH_GRP14_SHA256] = kex_gen_server; - kex->kex[KEX_DH_GRP16_SHA512] = kex_gen_server; - kex->kex[KEX_DH_GRP18_SHA512] = kex_gen_server; - kex->kex[KEX_DH_GEX_SHA1] = kexgex_server; - kex->kex[KEX_DH_GEX_SHA256] = kexgex_server; -# ifdef OPENSSL_HAS_ECC - kex->kex[KEX_ECDH_SHA2] = kex_gen_server; -# endif -#endif - kex->kex[KEX_C25519_SHA256] = kex_gen_server; - kex->kex[KEX_KEM_SNTRUP761X25519_SHA512] = kex_gen_server; - kex->load_host_public_key=&get_hostkey_public_by_type; - kex->load_host_private_key=&get_hostkey_private_by_type; + kex_set_callbacks_server(kex); + kex->find_host_public_key=&get_hostkey_public_by_alg; + kex->find_host_private_key=&get_hostkey_private_by_alg; kex->host_key_index=&get_hostkey_index; - kex->sign = sshd_hostkey_sign; + kex->xsign = Xsshd_hostkey_sign; ssh_dispatch_run_fatal(ssh, DISPATCH_BLOCK, &kex->done); -#ifdef DEBUG_KEXDH +#ifdef DEBUG_KEX /* send 1st encrypted/maced/compressed message */ if ((r = sshpkt_start(ssh, SSH2_MSG_IGNORE)) != 0 || - (r = sshpkt_put_cstring(ssh, "markus")) != 0 || + (r = sshpkt_put_cstring(ssh, "roumen")) != 0 || (r = sshpkt_send(ssh)) != 0 || (r = ssh_packet_write_wait(ssh)) != 0) - fatal_fr(r, "send test"); + fatal_fr(r, "kex 1st message"); #endif - kex_proposal_free_entries(myproposal); + free(prop_kex); + free(prop_enc); + free(prop_hostkey); debug("KEX done"); } @@ -2449,10 +2697,9 @@ pmonitor != NULL && pmonitor->m_pid > 1) { debug("Killing privsep child %d", pmonitor->m_pid); if (kill(pmonitor->m_pid, SIGKILL) != 0 && - errno != ESRCH) { + errno != ESRCH) error_f("kill(%d): %s", pmonitor->m_pid, strerror(errno)); - } } } #ifdef SSH_AUDIT_EVENTS diff -ruN openssh-9.4p1/sshd_config openssh-9.4p1+x509-14.2.1/sshd_config --- openssh-9.4p1/sshd_config 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/sshd_config 2023-08-20 10:07:00.000000000 +0300 @@ -19,6 +19,83 @@ #HostKey /etc/ssh/ssh_host_ecdsa_key #HostKey /etc/ssh/ssh_host_ed25519_key +# algorithms for X.509 certificates with EC key +#X509KeyAlgorithm x509v3-ecdsa-sha2-nistp256,ssh-sha256,ecdsa-sha2-nistp256 +#X509KeyAlgorithm x509v3-ecdsa-sha2-nistp384,ssh-sha384,ecdsa-sha2-nistp384 +#X509KeyAlgorithm x509v3-ecdsa-sha2-nistp521,ssh-sha512,ecdsa-sha2-nistp521 + +# algorithms for X.509 certificates with RSA key +# Note first defined is used in signature operations! +#X509KeyAlgorithm x509v3-rsa2048-sha256,rsa2048-sha256,rsa2048-sha256 +#X509KeyAlgorithm x509v3-ssh-rsa,rsa-sha1,ssh-rsa +#X509KeyAlgorithm x509v3-sign-rsa,rsa-sha1 +#X509KeyAlgorithm x509v3-sign-rsa,rsa-md5 + +# algorithms for X.509 certificates with DSA key +# Note first defined is used in signature operations! +#X509KeyAlgorithm x509v3-ssh-dss,dss-raw,ssh-dss +#X509KeyAlgorithm x509v3-sign-dss,dss-asn1 +#X509KeyAlgorithm x509v3-sign-dss,dss-raw + +# algorithms for X.509 certificates with Ed25519 key +X509KeyAlgorithm x509v3-ssh-ed25519,none,ssh-ed25519 + +# The intended use for the X509 client certificate. Without this option +# no chain verification will be done. Currently accepted uses are case +# insensitive: +# - "sslclient", "SSL client", "SSL_client" or "client" +# - "any", "Any Purpose", "Any_Purpose" or "AnyPurpose" +# - "skip" or ""(empty): don`t check purpose. +#AllowedCertPurpose sslclient + +# Specifies whether self-issued X.509 certificate can be allowed only +# by entry in AuthorizedKeysFile that contain matching public key or +# certificate blob. +#KeyAllowSelfIssued no + +# Specifies whether CRL must present in store for all certificates in +# certificate chain with attribute "cRLDistributionPoints" +#MandatoryCRL no + +# A file with multiple certificates of certificate signers +# in PEM format concatenated together. +#CACertificateFile /etc/ssh/ca/ca-bundle.crt + +# A directory with certificates of certificate signers. +# The certificates should have name of the form: [HASH].[NUMBER] +# or have symbolic links to them of this form. +#CACertificatePath /etc/ssh/ca/crt + +# A file with multiple CRL of certificate signers +# in PEM format concatenated together. +#CARevocationFile /etc/ssh/ca/ca-bundle.crl + +# A directory with CRL of certificate signers. +# The CRL should have name of the form: [HASH].r[NUMBER] +# or have symbolic links to them of this form. +#CARevocationPath /etc/ssh/ca/crl + +# LDAP protocol version. +# Example: +# CAldapVersion 2 + +# Note because of OpenSSH options parser limitation +# use %3D instead of = ! +# LDAP initialization may require URL to be escaped, i.e. +# use %2C instead of ,(comma). Escaped URL don't depend from +# LDAP initialization method. +# Example: +# CAldapURL ldap://localhost:389/dc%3Dexample%2Cdc%3Dcom + +# SSH can use "Online Certificate Status Protocol"(OCSP) +# to validate certificate. Set VAType to +# - none : do not use OCSP to validate certificates; +# - ocspcert: validate only certificates that specify `OCSP +# Service Locator' URL; +# - ocspspec: use specified in the configuration 'OCSP Responder' +# to validate all certificates. +#VAType none + # Ciphers and keying #RekeyLimit default none @@ -57,7 +134,6 @@ #PasswordAuthentication yes #PermitEmptyPasswords no -# Change to no to disable s/key passwords #KbdInteractiveAuthentication yes # Kerberos options @@ -91,6 +167,7 @@ #PrintMotd yes #PrintLastLog yes #TCPKeepAlive yes +#UsePrivilegeSeparation sandbox #PermitUserEnvironment no #Compression delayed #ClientAliveInterval 0 diff -ruN openssh-9.4p1/sshd_config.0 openssh-9.4p1+x509-14.2.1/sshd_config.0 --- openssh-9.4p1/sshd_config.0 2023-08-10 04:11:19.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/sshd_config.0 2023-08-20 10:07:00.000000000 +0300 @@ -1,32 +1,44 @@ -SSHD_CONFIG(5) File Formats Manual SSHD_CONFIG(5) +SSHD_CONFIG(5) BSD File Formats Manual SSHD_CONFIG(5) NAME - sshd_config M-bM-^@M-^S OpenSSH daemon configuration file + sshd_config -- Secure shell daemon configuration file DESCRIPTION sshd(8) reads configuration data from /etc/ssh/sshd_config (or the file - specified with -f on the command line). The file contains keyword- - argument pairs, one per line. Unless noted otherwise, for each keyword, - the first obtained value will be used. Lines starting with M-bM-^@M-^X#M-bM-^@M-^Y and empty + specified with -f on the command line). The file contains keyword-argu- + ment pairs, one per line. Unless noted otherwise, for each keyword, the + first obtained value will be used. Lines starting with '#' and empty lines are interpreted as comments. Arguments may optionally be enclosed in double quotes (") in order to represent arguments containing spaces. - - The possible keywords and their meanings are as follows (note that - keywords are case-insensitive and arguments are case-sensitive): + Configuration options may be separated by whitespace or optional white- + space and exactly one '='; the latter format is useful to avoid the need + to quote whitespace when specifying configuration options. + + The possible keywords and their meanings are as follows (note that key- + words are case-insensitive and arguments are case-sensitive): + + AcceptedAlgorithms + Specifies the publickey algorithms as a comma-separated pattern + list that will be announced to client if client supports exten- + sion negotiation mechanism. See PATTERNS in ssh_config(5) for + more information on patterns. The default "*" will announce all + algorithms. Note algorithms that use X.509 certificates depend + from option X509KeyAlgorithm. The list of available key algo- + rithms may also be obtained using "ssh -Q key". AcceptEnv Specifies what environment variables sent by the client will be copied into the session's environ(7). See SendEnv and SetEnv in - ssh_config(5) for how to configure the client. The TERM - environment variable is always accepted whenever the client - requests a pseudo-terminal as it is required by the protocol. - Variables are specified by name, which may contain the wildcard - characters M-bM-^@M-^X*M-bM-^@M-^Y and M-bM-^@M-^X?M-bM-^@M-^Y. Multiple environment variables may be - separated by whitespace or spread across multiple AcceptEnv - directives. Be warned that some environment variables could be - used to bypass restricted user environments. For this reason, - care should be taken in the use of this directive. The default - is not to accept any environment variables. + ssh_config(5) for how to configure the client. The TERM environ- + ment variable is always accepted whenever the client requests a + pseudo-terminal as it is required by the protocol. Variables are + specified by name, which may contain the wildcard characters '*' + and '?'. Multiple environment variables may be separated by + whitespace or spread across multiple AcceptEnv directives. Be + warned that some environment variables could be used to bypass + restricted user environments. For this reason, care should be + taken in the use of this directive. The default is not to accept + any environment variables. AddressFamily Specifies which address family should be used by sshd(8). Valid @@ -34,10 +46,22 @@ (use IPv6 only). AllowAgentForwarding - Specifies whether ssh-agent(1) forwarding is permitted. The - default is yes. Note that disabling agent forwarding does not - improve security unless users are also denied shell access, as - they can always install their own forwarders. + Specifies whether ssh-agent(1) forwarding is permitted. The de- + fault is yes. Note that disabling agent forwarding does not im- + prove security unless users are also denied shell access, as they + can always install their own forwarders. + + AllowedCertPurpose + The intended use for the X.509 client certificate. Without this + option no chain verification will be done. Currently accepted + uses are case insensitive: + sslclient | SSL client | SSL_client | client + only SSL-client purpose + any | Any Purpose | Any_Purpose | AnyPurpose + allow any purpose + skip | '' (empty) + do not check purpose + The default is sslclient. AllowGroups This keyword can be followed by a list of group name patterns, @@ -55,21 +79,21 @@ AllowStreamLocalForwarding Specifies whether StreamLocal (Unix-domain socket) forwarding is permitted. The available options are yes (the default) or all to - allow StreamLocal forwarding, no to prevent all StreamLocal - forwarding, local to allow local (from the perspective of ssh(1)) + allow StreamLocal forwarding, no to prevent all StreamLocal for- + warding, local to allow local (from the perspective of ssh(1)) forwarding only or remote to allow remote forwarding only. Note that disabling StreamLocal forwarding does not improve security - unless users are also denied shell access, as they can always - install their own forwarders. + unless users are also denied shell access, as they can always in- + stall their own forwarders. AllowTcpForwarding - Specifies whether TCP forwarding is permitted. The available - options are yes (the default) or all to allow TCP forwarding, no - to prevent all TCP forwarding, local to allow local (from the - perspective of ssh(1)) forwarding only or remote to allow remote - forwarding only. Note that disabling TCP forwarding does not - improve security unless users are also denied shell access, as - they can always install their own forwarders. + Specifies whether TCP forwarding is permitted. The available op- + tions are yes (the default) or all to allow TCP forwarding, no to + prevent all TCP forwarding, local to allow local (from the per- + spective of ssh(1)) forwarding only or remote to allow remote + forwarding only. Note that disabling TCP forwarding does not im- + prove security unless users are also denied shell access, as they + can always install their own forwarders. AllowUsers This keyword can be followed by a list of user name patterns, @@ -79,9 +103,9 @@ is allowed for all users. If the pattern takes the form USER@HOST then USER and HOST are separately checked, restricting logins to particular users from particular hosts. HOST criteria - may additionally contain addresses to match in CIDR - address/masklen format. The allow/deny users directives are - processed in the following order: DenyUsers, AllowUsers. + may additionally contain addresses to match in CIDR ad- + dress/masklen format. The allow/deny users directives are pro- + cessed in the following order: DenyUsers, AllowUsers. See PATTERNS in ssh_config(5) for more information on patterns. This keyword may appear multiple times in sshd_config with each @@ -98,27 +122,27 @@ For example, "publickey,password publickey,keyboard-interactive" would require the user to complete public key authentication, - followed by either password or keyboard interactive - authentication. Only methods that are next in one or more lists - are offered at each stage, so for this example it would not be - possible to attempt password or keyboard-interactive - authentication before public key. + followed by either password or keyboard interactive authentica- + tion. Only methods that are next in one or more lists are of- + fered at each stage, so for this example it would not be possible + to attempt password or keyboard-interactive authentication before + public key. For keyboard interactive authentication it is also possible to restrict authentication to a specific device by appending a colon followed by the device identifier bsdauth or pam. depending on the server configuration. For example, - "keyboard-interactive:bsdauth" would restrict keyboard - interactive authentication to the bsdauth device. + "keyboard-interactive:bsdauth" would restrict keyboard interac- + tive authentication to the bsdauth device. - If the publickey method is listed more than once, sshd(8) - verifies that keys that have been used successfully are not - reused for subsequent authentications. For example, + If the publickey method is listed more than once, sshd(8) veri- + fies that keys that have been used successfully are not reused + for subsequent authentications. For example, "publickey,publickey" requires successful authentication using two different public keys. - Note that each authentication method listed should also be - explicitly enabled in the configuration. + Note that each authentication method listed should also be ex- + plicitly enabled in the configuration. The available authentication methods are: "gssapi-with-mic", "hostbased", "keyboard-interactive", "none" (used for access to @@ -127,8 +151,8 @@ AuthorizedKeysCommand Specifies a program to be used to look up the user's public keys. - The program must be owned by root, not writable by group or - others and specified by an absolute path. Arguments to + The program must be owned by root, not writable by group or oth- + ers and specified by an absolute path. Arguments to AuthorizedKeysCommand accept the tokens described in the TOKENS section. If no arguments are specified then the username of the target user is used. @@ -150,28 +174,28 @@ Specifies the file that contains the public keys used for user authentication. The format is described in the AUTHORIZED_KEYS FILE FORMAT section of sshd(8). Arguments to AuthorizedKeysFile - accept the tokens described in the TOKENS section. After - expansion, AuthorizedKeysFile is taken to be an absolute path or - one relative to the user's home directory. Multiple files may be + accept the tokens described in the TOKENS section. After expan- + sion, AuthorizedKeysFile is taken to be an absolute path or one + relative to the user's home directory. Multiple files may be listed, separated by whitespace. Alternately this option may be set to none to skip checking for user keys in files. The default is ".ssh/authorized_keys .ssh/authorized_keys2". AuthorizedPrincipalsCommand Specifies a program to be used to generate the list of allowed - certificate principals as per AuthorizedPrincipalsFile. The - program must be owned by root, not writable by group or others - and specified by an absolute path. Arguments to + certificate principals as per AuthorizedPrincipalsFile. The pro- + gram must be owned by root, not writable by group or others and + specified by an absolute path. Arguments to AuthorizedPrincipalsCommand accept the tokens described in the TOKENS section. If no arguments are specified then the username of the target user is used. The program should produce on standard output zero or more lines of AuthorizedPrincipalsFile output. If either - AuthorizedPrincipalsCommand or AuthorizedPrincipalsFile is - specified, then certificates offered by the client for - authentication must contain a principal that is listed. By - default, no AuthorizedPrincipalsCommand is run. + AuthorizedPrincipalsCommand or AuthorizedPrincipalsFile is speci- + fied, then certificates offered by the client for authentication + must contain a principal that is listed. By default, no + AuthorizedPrincipalsCommand is run. AuthorizedPrincipalsCommandUser Specifies the user under whose account the @@ -188,18 +212,18 @@ which must appear in the certificate for it to be accepted for authentication. Names are listed one per line preceded by key options (as described in AUTHORIZED_KEYS FILE FORMAT in sshd(8)). - Empty lines and comments starting with M-bM-^@M-^X#M-bM-^@M-^Y are ignored. + Empty lines and comments starting with '#' are ignored. Arguments to AuthorizedPrincipalsFile accept the tokens described in the TOKENS section. After expansion, AuthorizedPrincipalsFile is taken to be an absolute path or one relative to the user's - home directory. The default is none, i.e. not to use a - principals file M-bM-^@M-^S in this case, the username of the user must - appear in a certificate's principals list for it to be accepted. - - Note that AuthorizedPrincipalsFile is only used when - authentication proceeds using a CA listed in TrustedUserCAKeys - and is not consulted for certification authorities trusted via + home directory. The default is none, i.e. not to use a princi- + pals file - in this case, the username of the user must appear in + a certificate's principals list for it to be accepted. + + Note that AuthorizedPrincipalsFile is only used when authentica- + tion proceeds using a CA listed in TrustedUserCAKeys and is not + consulted for certification authorities trusted via ~/.ssh/authorized_keys, though the principals= key option offers a similar facility (see sshd(8) for details). @@ -207,37 +231,73 @@ before authentication is allowed. If the argument is none then no banner is displayed. By default, no banner is displayed. - CASignatureAlgorithms - Specifies which algorithms are allowed for signing of - certificates by certificate authorities (CAs). The default is: + CACertificateFile + "X509 store" option: This file contain multiple certificates of + certificate signers in PEM format concatenated together. The de- + fault is /etc/ssh/ca/ca-bundle.crt. + + CACertificatePath + "X509 store" option: "Hash dir" with certificates of certificate + signers. Each certificate should be stored in separate file with + name [HASH].[NUMBER], where [HASH] is certificate hash value and + [NUMBER] is an integer starting from zero. The default is + /etc/ssh/ca/crt. + + CAldapVersion + "X509 store" option: Specifies LDAP protocol version. The de- + fault is not specified and depend from LDAP library. + + CAldapURL + "X509 store" option: Specifies hostport and dn(distinguished + name) of LDAP URLs (Uniform Resource Locators) as detailed in RFC + 2255. The rest of URL is build internally. Because of options + parser limitation use '%3D' instead of '=' ! LDAP initialization + method may require URL to be escaped, i.e. use '%2C' instead of + ',' (comma). Escaped URL don't depend from LDAP initialization + method. + + CARevocationFile + "X509 store" option: This file contain multiple "Certificate + Revocation List" (CRL) of certificate signers in PEM format con- + catenated together. The default is /etc/ssh/ca/ca-bundle.crl. + + CARevocationPath + "X509 store" option: "Hash dir" with "Certificate Revocation + List" (CRL) of certificate signers. Each CRL should be stored in + separate file with name [HASH].r[NUMBER], where [HASH] is CRL + hash value and [NUMBER] is an integer starting from zero. The de- + fault is /etc/ssh/ca/crl. - ssh-ed25519,ecdsa-sha2-nistp256, - ecdsa-sha2-nistp384,ecdsa-sha2-nistp521, - sk-ssh-ed25519@openssh.com, - sk-ecdsa-sha2-nistp256@openssh.com, - rsa-sha2-512,rsa-sha2-256 - - If the specified list begins with a M-bM-^@M-^X+M-bM-^@M-^Y character, then the - specified algorithms will be appended to the default set instead - of replacing them. If the specified list begins with a M-bM-^@M-^X-M-bM-^@M-^Y - character, then the specified algorithms (including wildcards) - will be removed from the default set instead of replacing them. + CASignatureAlgorithms + Specifies which algorithms are allowed for signing of custom cer- + tificates by custom certificate authorities (CAs). The default + is: + + ssh-ed25519, + ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521, + rsa-sha2-512,rsa-sha2-256,ssh-rsa + + If the specified list begins with a '+' character, then the spec- + ified algorithms will be appended to the default set instead of + replacing them. If the specified list begins with a '-' charac- + ter, then the specified algorithms (including wildcards) will be + removed from the default set instead of replacing them. - Certificates signed using other algorithms will not be accepted - for public key or host-based authentication. + Custom certificates signed using other algorithms will not be ac- + cepted for public key or host-based authentication. ChannelTimeout Specifies whether and how quickly sshd(8) should close inactive - channels. Timeouts are specified as one or more M-bM-^@M-^\type=intervalM-bM-^@M-^] - pairs separated by whitespace, where the M-bM-^@M-^\typeM-bM-^@M-^] must be a channel - type name (as described in the table below), optionally - containing wildcard characters. - - The timeout value M-bM-^@M-^\intervalM-bM-^@M-^] is specified in seconds or may use - any of the units documented in the TIME FORMATS section. For - example, M-bM-^@M-^\session:*=5mM-bM-^@M-^] would cause all sessions to terminate - after five minutes of inactivity. Specifying a zero value - disables the inactivity timeout. + channels. Timeouts are specified as one or more "type=interval" + pairs separated by whitespace, where the "type" must be a channel + type name (as described in the table below), optionally contain- + ing wildcard characters. + + The timeout value "interval" is specified in seconds or may use + any of the units documented in the TIME FORMATS section. For ex- + ample, "session:*=5m" would cause all sessions to terminate after + five minutes of inactivity. Specifying a zero value disables the + inactivity timeout. The available channel types include: @@ -269,54 +329,54 @@ Note that in all the above cases, terminating an inactive session does not guarantee to remove all resources associated with the - session, e.g. shell processes or X11 clients relating to the - session may continue to execute. + session, e.g. shell processes or X11 clients relating to the ses- + sion may continue to execute. Moreover, terminating an inactive channel or session does not necessarily close the SSH connection, nor does it prevent a - client from requesting another channel of the same type. In - particular, expiring an inactive forwarding session does not - prevent another identical forwarding from being subsequently - created. See also UnusedConnectionTimeout, which may be used in - conjunction with this option. + client from requesting another channel of the same type. In par- + ticular, expiring an inactive forwarding session does not prevent + another identical forwarding from being subsequently created. + See also UnusedConnectionTimeout, which may be used in conjunc- + tion with this option. The default is not to expire channels of any type for inactivity. ChrootDirectory - Specifies the pathname of a directory to chroot(2) to after - authentication. At session startup sshd(8) checks that all - components of the pathname are root-owned directories which are - not writable by any other user or group. After the chroot, - sshd(8) changes the working directory to the user's home - directory. Arguments to ChrootDirectory accept the tokens - described in the TOKENS section. - - The ChrootDirectory must contain the necessary files and - directories to support the user's session. For an interactive - session this requires at least a shell, typically sh(1), and - basic /dev nodes such as null(4), zero(4), stdin(4), stdout(4), - stderr(4), and tty(4) devices. For file transfer sessions using - SFTP no additional configuration of the environment is necessary - if the in-process sftp-server is used, though sessions which use - logging may require /dev/log inside the chroot directory on some - operating systems (see sftp-server(8) for details). + Specifies the pathname of a directory to chroot(2) to after au- + thentication. At session startup sshd(8) checks that all compo- + nents of the pathname are root-owned directories which are not + writable by any other user or group. After the chroot, sshd(8) + changes the working directory to the user's home directory. Ar- + guments to ChrootDirectory accept the tokens described in the + TOKENS section. + + The ChrootDirectory must contain the necessary files and directo- + ries to support the user's session. For an interactive session + this requires at least a shell, typically sh(1), and basic /dev + nodes such as null(4), zero(4), stdin(4), stdout(4), stderr(4), + and tty(4) devices. For file transfer sessions using SFTP no ad- + ditional configuration of the environment is necessary if the in- + process sftp-server is used, though sessions which use logging + may require /dev/log inside the chroot directory on some operat- + ing systems (see sftp-server(8) for details). For safety, it is very important that the directory hierarchy be - prevented from modification by other processes on the system - (especially those outside the jail). Misconfiguration can lead - to unsafe environments which sshd(8) cannot detect. + prevented from modification by other processes on the system (es- + pecially those outside the jail). Misconfiguration can lead to + unsafe environments which sshd(8) cannot detect. The default is none, indicating not to chroot(2). Ciphers Specifies the ciphers allowed. Multiple ciphers must be comma- - separated. If the specified list begins with a M-bM-^@M-^X+M-bM-^@M-^Y character, + separated. If the specified list begins with a '+' character, then the specified ciphers will be appended to the default set instead of replacing them. If the specified list begins with a - M-bM-^@M-^X-M-bM-^@M-^Y character, then the specified ciphers (including wildcards) + '-' character, then the specified ciphers (including wildcards) will be removed from the default set instead of replacing them. - If the specified list begins with a M-bM-^@M-^X^M-bM-^@M-^Y character, then the - specified ciphers will be placed at the head of the default set. + If the specified list begins with a '^' character, then the spec- + ified ciphers will be placed at the head of the default set. The supported ciphers are: @@ -341,23 +401,23 @@ cipher". ClientAliveCountMax - Sets the number of client alive messages which may be sent - without sshd(8) receiving any messages back from the client. If - this threshold is reached while client alive messages are being - sent, sshd will disconnect the client, terminating the session. - It is important to note that the use of client alive messages is - very different from TCPKeepAlive. The client alive messages are - sent through the encrypted channel and therefore will not be - spoofable. The TCP keepalive option enabled by TCPKeepAlive is - spoofable. The client alive mechanism is valuable when the - client or server depend on knowing when a connection has become - unresponsive. + Sets the number of client alive messages which may be sent with- + out sshd(8) receiving any messages back from the client. If this + threshold is reached while client alive messages are being sent, + sshd will disconnect the client, terminating the session. It is + important to note that the use of client alive messages is very + different from TCPKeepAlive. The client alive messages are sent + through the encrypted channel and therefore will not be spoofa- + ble. The TCP keepalive option enabled by TCPKeepAlive is spoofa- + ble. The client alive mechanism is valuable when the client or + server depend on knowing when a connection has become unrespon- + sive. The default value is 3. If ClientAliveInterval is set to 15, and ClientAliveCountMax is left at the default, unresponsive SSH clients will be disconnected after approximately 45 seconds. - Setting a zero ClientAliveCountMax disables connection - termination. + Setting a zero ClientAliveCountMax disables connection termina- + tion. ClientAliveInterval Sets a timeout interval in seconds after which if no data has @@ -367,18 +427,18 @@ not be sent to the client. Compression - Specifies whether compression is enabled after the user has - authenticated successfully. The argument must be yes, delayed (a + Specifies whether compression is enabled after the user has au- + thenticated successfully. The argument must be yes, delayed (a legacy synonym for yes) or no. The default is yes. DenyGroups This keyword can be followed by a list of group name patterns, separated by spaces. Login is disallowed for users whose primary group or supplementary group list matches one of the patterns. - Only group names are valid; a numerical group ID is not - recognized. By default, login is allowed for all groups. The - allow/deny groups directives are processed in the following - order: DenyGroups, AllowGroups. + Only group names are valid; a numerical group ID is not recog- + nized. By default, login is allowed for all groups. The al- + low/deny groups directives are processed in the following order: + DenyGroups, AllowGroups. See PATTERNS in ssh_config(5) for more information on patterns. This keyword may appear multiple times in sshd_config with each @@ -387,14 +447,14 @@ DenyUsers This keyword can be followed by a list of user name patterns, separated by spaces. Login is disallowed for user names that - match one of the patterns. Only user names are valid; a - numerical user ID is not recognized. By default, login is - allowed for all users. If the pattern takes the form USER@HOST - then USER and HOST are separately checked, restricting logins to - particular users from particular hosts. HOST criteria may - additionally contain addresses to match in CIDR address/masklen - format. The allow/deny users directives are processed in the - following order: DenyUsers, AllowUsers. + match one of the patterns. Only user names are valid; a numeri- + cal user ID is not recognized. By default, login is allowed for + all users. If the pattern takes the form USER@HOST then USER and + HOST are separately checked, restricting logins to particular + users from particular hosts. HOST criteria may additionally con- + tain addresses to match in CIDR address/masklen format. The al- + low/deny users directives are processed in the following order: + DenyUsers, AllowUsers. See PATTERNS in ssh_config(5) for more information on patterns. This keyword may appear multiple times in sshd_config with each @@ -406,11 +466,11 @@ related options and may simplify restricted configurations. ExposeAuthInfo - Writes a temporary file containing a list of authentication - methods and public credentials (e.g. keys) used to authenticate - the user. The location of the file is exposed to the user - session through the SSH_USER_AUTH environment variable. The - default is no. + Writes a temporary file containing a list of authentication meth- + ods and public credentials (e.g. keys) used to authenticate the + user. The location of the file is exposed to the user session + through the SSH_USER_AUTH environment variable. The default is + no. FingerprintHash Specifies the hash algorithm used when logging key fingerprints. @@ -434,9 +494,9 @@ forwardings to the loopback address. This prevents other remote hosts from connecting to forwarded ports. GatewayPorts can be used to specify that sshd should allow remote port forwardings to - bind to non-loopback addresses, thus allowing other hosts to - connect. The argument may be no to force remote port forwardings - to be available to the local host only, yes to force remote port + bind to non-loopback addresses, thus allowing other hosts to con- + nect. The argument may be no to force remote port forwardings to + be available to the local host only, yes to force remote port forwardings to bind to the wildcard address, or clientspecified to allow the client to select the address to which the forwarding is bound. The default is no. @@ -454,59 +514,45 @@ acceptor a client authenticates against. If set to yes then the client must authenticate against the host service on the current hostname. If set to no then the client may authenticate against - any service key stored in the machine's default store. This - facility is provided to assist with operation on multi homed - machines. The default is yes. + any service key stored in the machine's default store. This fa- + cility is provided to assist with operation on multi homed ma- + chines. The default is yes. HostbasedAcceptedAlgorithms - Specifies the signature algorithms that will be accepted for - hostbased authentication as a list of comma-separated patterns. - Alternately if the specified list begins with a M-bM-^@M-^X+M-bM-^@M-^Y character, - then the specified signature algorithms will be appended to the - default set instead of replacing them. If the specified list - begins with a M-bM-^@M-^X-M-bM-^@M-^Y character, then the specified signature - algorithms (including wildcards) will be removed from the default - set instead of replacing them. If the specified list begins with - a M-bM-^@M-^X^M-bM-^@M-^Y character, then the specified signature algorithms will be - placed at the head of the default set. The default for this - option is: - - ssh-ed25519-cert-v01@openssh.com, - ecdsa-sha2-nistp256-cert-v01@openssh.com, - ecdsa-sha2-nistp384-cert-v01@openssh.com, - ecdsa-sha2-nistp521-cert-v01@openssh.com, - sk-ssh-ed25519-cert-v01@openssh.com, - sk-ecdsa-sha2-nistp256-cert-v01@openssh.com, - rsa-sha2-512-cert-v01@openssh.com, - rsa-sha2-256-cert-v01@openssh.com, - ssh-ed25519, - ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521, - sk-ssh-ed25519@openssh.com, - sk-ecdsa-sha2-nistp256@openssh.com, - rsa-sha2-512,rsa-sha2-256 - - The list of available signature algorithms may also be obtained - using "ssh -Q HostbasedAcceptedAlgorithms". This was formerly - named HostbasedAcceptedKeyTypes. + Option compatibility. See HostbasedAlgorithms + + HostbasedAcceptedKeyTypes + Option compatibility. See HostbasedAlgorithms + + HostbasedAlgorithms + Specifies the publickey algorithms that will be accepted in + "hostbased" authentication as a comma-separated pattern list. + See PATTERNS in ssh_config(5) for more information on patterns. + The default "*" will allow all algorithms. Also algorithms has + to be accepted by patterns of option AcceptedAlgorithms. Note + algorithms that use X.509 certificates depend from option + X509KeyAlgorithm. The list of available key algorithms may also + be obtained using "ssh -Q key". HostbasedAuthentication - Specifies whether rhosts or /etc/hosts.equiv authentication - together with successful public key client host authentication is - allowed (host-based authentication). The default is no. + Specifies whether rhosts or /etc/hosts.equiv authentication to- + gether with successful public key client host authentication is + allowed (host-based authentication). Also secure shell uses + equavalient shosts and /etc/shosts.equiv. The default is no. HostbasedUsesNameFromPacketOnly - Specifies whether or not the server will attempt to perform a - reverse name lookup when matching the name in the ~/.shosts, - ~/.rhosts, and /etc/hosts.equiv files during + Specifies whether or not the server will attempt to perform a re- + verse name lookup when matching the name in the ~/.shosts, + ~/.rhosts, /etc/hosts.equiv, and /etc/shosts.equiv files during HostbasedAuthentication. A setting of yes means that sshd(8) uses the name supplied by the client rather than attempting to resolve the name from the TCP connection itself. The default is no. HostCertificate - Specifies a file containing a public host certificate. The - certificate's public key must match a private host key already - specified by HostKey. The default behaviour of sshd(8) is not to + Specifies a file containing a public host certificate. The cer- + tificate's public key must match a private host key already spec- + ified by HostKey. The default behaviour of sshd(8) is not to load any certificates. HostKey @@ -518,9 +564,17 @@ accessible and that the HostKeyAlgorithms option restricts which of the keys are actually used by sshd(8). - It is possible to have multiple host key files. It is also - possible to specify public host key files instead. In this case - operations on the private key will be delegated to an + It is possible to have multiple host key files. + + For RSA, ECDSA, Ed25519 or DSA host key file may contain X.509 + certificate that match it. In addition file may contain extra + X.509 certificates. Extra certificates along with certificates + from X.509 store are used to build chain of certificates leading + to a trusted certificate authority if required by public key al- + gorithm format. + + It is also possible to specify public host key files instead. In + this case operations on the private key will be delegated to an ssh-agent(1). HostKeyAgent @@ -530,25 +584,9 @@ read from the SSH_AUTH_SOCK environment variable. HostKeyAlgorithms - Specifies the host key signature algorithms that the server - offers. The default for this option is: - - ssh-ed25519-cert-v01@openssh.com, - ecdsa-sha2-nistp256-cert-v01@openssh.com, - ecdsa-sha2-nistp384-cert-v01@openssh.com, - ecdsa-sha2-nistp521-cert-v01@openssh.com, - sk-ssh-ed25519-cert-v01@openssh.com, - sk-ecdsa-sha2-nistp256-cert-v01@openssh.com, - rsa-sha2-512-cert-v01@openssh.com, - rsa-sha2-256-cert-v01@openssh.com, - ssh-ed25519, - ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521, - sk-ssh-ed25519@openssh.com, - sk-ecdsa-sha2-nistp256@openssh.com, - rsa-sha2-512,rsa-sha2-256 - - The list of available signature algorithms may also be obtained - using "ssh -Q HostKeyAlgorithms". + Specifies the host key algorithms that the server offers. The + default "*" allows all algorithms. The list of available key al- + gorithms may also be obtained using "ssh -Q key". IgnoreRhosts Specifies whether to ignore per-user .rhosts and .shosts files @@ -556,14 +594,14 @@ and /etc/shosts.equiv are still used regardless of this setting. Accepted values are yes (the default) to ignore all per-user - files, shosts-only to allow the use of .shosts but to ignore - .rhosts or no to allow both .shosts and rhosts. + files, rhosts-only to allow the use of .shosts but to ignore + .rhosts or no to allow both .rhosts and .shosts. IgnoreUserKnownHosts Specifies whether sshd(8) should ignore the user's ~/.ssh/known_hosts during HostbasedAuthentication and use only the system-wide known hosts file /etc/ssh/ssh_known_hosts. The - default is M-bM-^@M-^\noM-bM-^@M-^]. + default is "no". Include Include the specified configuration file(s). Multiple pathnames @@ -573,23 +611,23 @@ directive may appear inside a Match block to perform conditional inclusion. - IPQoS Specifies the IPv4 type-of-service or DSCP class for the - connection. Accepted values are af11, af12, af13, af21, af22, - af23, af31, af32, af33, af41, af42, af43, cs0, cs1, cs2, cs3, - cs4, cs5, cs6, cs7, ef, le, lowdelay, throughput, reliability, a - numeric value, or none to use the operating system default. This - option may take one or two arguments, separated by whitespace. - If one argument is specified, it is used as the packet class - unconditionally. If two values are specified, the first is - automatically selected for interactive sessions and the second - for non-interactive sessions. The default is af21 (Low-Latency - Data) for interactive sessions and cs1 (Lower Effort) for non- - interactive sessions. + IPQoS Specifies the IPv4 type-of-service or DSCP class for the connec- + tion. Accepted values are af11, af12, af13, af21, af22, af23, + af31, af32, af33, af41, af42, af43, cs0, cs1, cs2, cs3, cs4, cs5, + cs6, cs7, ef, le, lowdelay, throughput, reliability, a numeric + value, or none to use the operating system default. This option + may take one or two arguments, separated by whitespace. If one + argument is specified, it is used as the packet class uncondi- + tionally. If two values are specified, the first is automati- + cally selected for interactive sessions and the second for non- + interactive sessions. The default is af21 (Low-Latency Data) for + interactive sessions and cs1 (Lower Effort) for non-interactive + sessions. KbdInteractiveAuthentication Specifies whether to allow keyboard-interactive authentication. All authentication styles from login.conf(5) are supported. The - default is yes. The argument to this keyword must be yes or no. + argument to this keyword must be yes or no. The default is yes. ChallengeResponseAuthentication is a deprecated alias for this. KerberosAuthentication @@ -605,9 +643,9 @@ The default is no. KerberosOrLocalPasswd - If password authentication through Kerberos fails then the - password will be validated via any additional local mechanism - such as /etc/passwd. The default is yes. + If password authentication through Kerberos fails then the pass- + word will be validated via any additional local mechanism such as + /etc/passwd. The default is yes. KerberosTicketCleanup Specifies whether to automatically destroy the user's ticket @@ -616,14 +654,14 @@ KexAlgorithms Specifies the available KEX (Key Exchange) algorithms. Multiple algorithms must be comma-separated. Alternately if the specified - list begins with a M-bM-^@M-^X+M-bM-^@M-^Y character, then the specified algorithms + list begins with a '+' character, then the specified algorithms will be appended to the default set instead of replacing them. - If the specified list begins with a M-bM-^@M-^X-M-bM-^@M-^Y character, then the - specified algorithms (including wildcards) will be removed from - the default set instead of replacing them. If the specified list - begins with a M-bM-^@M-^X^M-bM-^@M-^Y character, then the specified algorithms will - be placed at the head of the default set. The supported - algorithms are: + If the specified list begins with a '-' character, then the spec- + ified algorithms (including wildcards) will be removed from the + default set instead of replacing them. If the specified list be- + gins with a '^' character, then the specified algorithms will be + placed at the head of the default set. The supported algorithms + are: curve25519-sha256 curve25519-sha256@libssh.org @@ -637,41 +675,57 @@ ecdh-sha2-nistp256 ecdh-sha2-nistp384 ecdh-sha2-nistp521 - sntrup761x25519-sha512@openssh.com + sntrup761x25519-sha512@openssh.com (if build) The default is: - sntrup761x25519-sha512@openssh.com, curve25519-sha256,curve25519-sha256@libssh.org, ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521, diffie-hellman-group-exchange-sha256, - diffie-hellman-group16-sha512,diffie-hellman-group18-sha512, - diffie-hellman-group14-sha256 + diffie-hellman-group16-sha512, + diffie-hellman-group18-sha512, + diffie-hellman-group14-sha256, + sntrup761x25519-sha512@openssh.com, + diffie-hellman-group14-sha1 + + The list of available key exchange algorithms may also be ob- + tained using "ssh -Q kex". - The list of available key exchange algorithms may also be - obtained using "ssh -Q KexAlgorithms". + KeyAllowSelfIssued + Specifies whether only encoded public key or X.509 certificate + listed in AuthorizedKeysFile can allow self-issued X.509 certifi- + cate to be used for user authentication. The default is "no". + Unsupported if daemon is build without "X509 store". + + A certificate (including self-issued) is accepted for user au- + thentication if encoded public key or encoded X.509 certificate + or distinguished name is listed in AuthorizedKeysFile, if is + valid and if is verified by certificates from "X509 store". See + verify(1). If option is set to "yes" self-issued certificate is + accepted when its public key match public key extracted from en- + try in AuthorizedKeysFile. In this case validity of certificate + is not checked. ListenAddress - Specifies the local addresses sshd(8) should listen on. The - following forms may be used: + Specifies the local addresses sshd(8) should listen on. The fol- + lowing forms may be used: ListenAddress hostname|address [rdomain domain] ListenAddress hostname:port [rdomain domain] ListenAddress IPv4_address:port [rdomain domain] ListenAddress [hostname|address]:port [rdomain domain] - The optional rdomain qualifier requests sshd(8) listen in an - explicit routing domain. If port is not specified, sshd will - listen on the address and all Port options specified. The - default is to listen on all local addresses on the current - default routing domain. Multiple ListenAddress options are - permitted. For more information on routing domains, see - rdomain(4). + The optional rdomain qualifier requests sshd(8) listen in an ex- + plicit routing domain. If port is not specified, sshd will lis- + ten on the address and all Port options specified. The default + is to listen on all local addresses on the current default rout- + ing domain. Multiple ListenAddress options are permitted. For + more information on routing domains, see rdomain(4). LoginGraceTime - The server disconnects after this time if the user has not - successfully logged in. If the value is 0, there is no time - limit. The default is 120 seconds. + The server disconnects after this time if the user has not suc- + cessfully logged in. If the value is 0, there is no time limit. + The default is 120 seconds. LogLevel Gives the verbosity level that is used when logging messages from @@ -684,30 +738,29 @@ LogVerbose Specify one or more overrides to LogLevel. An override consists of a pattern lists that matches the source file, function and - line number to force detailed logging for. For example, an - override pattern of: + line number to force detailed logging for. For example, an over- + ride pattern of: kex.c:*:1000,*:kex_exchange_identification():*,packet.c:* would enable detailed logging for line 1000 of kex.c, everything in the kex_exchange_identification() function, and all code in the packet.c file. This option is intended for debugging and no - overrides are enabled by default. + overrides are enabled by default, i.e. default value is none. - MACs Specifies the available MAC (message authentication code) - algorithms. The MAC algorithm is used for data integrity - protection. Multiple algorithms must be comma-separated. If the - specified list begins with a M-bM-^@M-^X+M-bM-^@M-^Y character, then the specified - algorithms will be appended to the default set instead of - replacing them. If the specified list begins with a M-bM-^@M-^X-M-bM-^@M-^Y - character, then the specified algorithms (including wildcards) - will be removed from the default set instead of replacing them. - If the specified list begins with a M-bM-^@M-^X^M-bM-^@M-^Y character, then the - specified algorithms will be placed at the head of the default - set. + MACs Specifies the available MAC (message authentication code) algo- + rithms. The MAC algorithm is used for data integrity protection. + Multiple algorithms must be comma-separated. If the specified + list begins with a '+' character, then the specified algorithms + will be appended to the default set instead of replacing them. + If the specified list begins with a '-' character, then the spec- + ified algorithms (including wildcards) will be removed from the + default set instead of replacing them. If the specified list be- + gins with a '^' character, then the specified algorithms will be + placed at the head of the default set. - The algorithms that contain "-etm" calculate the MAC after - encryption (encrypt-then-mac). These are considered safer and + The algorithms that contain "-etm" calculate the MAC after en- + cryption (encrypt-then-mac). These are considered safer and their use recommended. The supported MACs are: hmac-md5 @@ -738,11 +791,16 @@ The list of available MAC algorithms may also be obtained using "ssh -Q mac". + MandatoryCRL + "X509 store" option: Specifies whether CRL must present in store + for all certificates in "certificate chain" with attribute + "X509v3 CRL Distribution Points". The default is no. + Match Introduces a conditional block. If all of the criteria on the Match line are satisfied, the keywords on the following lines - override those set in the global section of the config file, - until either another Match line or the end of the file. If a - keyword appears in multiple Match blocks that are satisfied, only + override those set in the global section of the config file, un- + til either another Match line or the end of the file. If a key- + word appears in multiple Match blocks that are satisfied, only the first instance of the keyword is applied. The arguments to Match are one or more criteria-pattern pairs or @@ -751,14 +809,14 @@ and Address (with RDomain representing the rdomain(4) on which the connection was received). - The match patterns may consist of single entries or comma- - separated lists and may use the wildcard and negation operators - described in the PATTERNS section of ssh_config(5). - - The patterns in an Address criteria may additionally contain - addresses to match in CIDR address/masklen format, such as - 192.0.2.0/24 or 2001:db8::/32. Note that the mask length - provided must be consistent with the address - it is an error to + The match patterns may consist of single entries or comma-sepa- + rated lists and may use the wildcard and negation operators de- + scribed in the PATTERNS section of ssh_config(5). + + The patterns in an Address criteria may additionally contain ad- + dresses to match in CIDR address/masklen format, such as + 192.0.2.0/24 or 2001:db8::/32. Note that the mask length pro- + vided must be consistent with the address - it is an error to specify a mask length that is too long for the address or one with bits set in this host portion of the address. For example, 192.0.2.0/33 and 192.0.2.0/8, respectively. @@ -773,13 +831,13 @@ Banner, CASignatureAlgorithms, ChannelTimeout, ChrootDirectory, ClientAliveCountMax, ClientAliveInterval, DenyGroups, DenyUsers, DisableForwarding, ExposeAuthInfo, ForceCommand, GatewayPorts, - GSSAPIAuthentication, HostbasedAcceptedAlgorithms, + GSSAPIAuthentication, HostbasedAlgorithms, HostbasedAuthentication, HostbasedUsesNameFromPacketOnly, IgnoreRhosts, Include, IPQoS, KbdInteractiveAuthentication, KerberosAuthentication, LogLevel, MaxAuthTries, MaxSessions, PasswordAuthentication, PermitEmptyPasswords, PermitListen, PermitOpen, PermitRootLogin, PermitTTY, PermitTunnel, - PermitUserRC, PubkeyAcceptedAlgorithms, PubkeyAuthentication, + PermitUserRC, PubkeyAlgorithms, PubkeyAuthentication, PubkeyAuthOptions, RekeyLimit, RevokedKeys, RDomain, SetEnv, StreamLocalBindMask, StreamLocalBindUnlink, TrustedUserCAKeys, UnusedConnectionTimeout, X11DisplayOffset, X11Forwarding and @@ -796,32 +854,32 @@ sessions may be established by clients that support connection multiplexing. Setting MaxSessions to 1 will effectively disable session multiplexing, whereas setting it to 0 will prevent all - shell, login and subsystem sessions while still permitting - forwarding. The default is 10. + shell, login and subsystem sessions while still permitting for- + warding. The default is 10. MaxStartups - Specifies the maximum number of concurrent unauthenticated - connections to the SSH daemon. Additional connections will be - dropped until authentication succeeds or the LoginGraceTime - expires for a connection. The default is 10:30:100. + Specifies the maximum number of concurrent unauthenticated con- + nections to the SSH daemon. Additional connections will be + dropped until authentication succeeds or the LoginGraceTime ex- + pires for a connection. The default is 10:30:100. Alternatively, random early drop can be enabled by specifying the three colon separated values start:rate:full (e.g. "10:30:60"). sshd(8) will refuse connection attempts with a probability of rate/100 (30%) if there are currently start (10) unauthenticated - connections. The probability increases linearly and all - connection attempts are refused if the number of unauthenticated - connections reaches full (60). + connections. The probability increases linearly and all connec- + tion attempts are refused if the number of unauthenticated con- + nections reaches full (60). ModuliFile Specifies the moduli(5) file that contains the Diffie-Hellman - groups used for the M-bM-^@M-^\diffie-hellman-group-exchange-sha1M-bM-^@M-^] and - M-bM-^@M-^\diffie-hellman-group-exchange-sha256M-bM-^@M-^] key exchange methods. The + groups used for the "diffie-hellman-group-exchange-sha1" and + "diffie-hellman-group-exchange-sha256" key exchange methods. The default is /etc/moduli. PasswordAuthentication - Specifies whether password authentication is allowed. The - default is yes. + Specifies whether password authentication is allowed. The de- + fault is yes. PermitEmptyPasswords When password authentication is allowed, it specifies whether the @@ -829,44 +887,44 @@ default is no. PermitListen - Specifies the addresses/ports on which a remote TCP port - forwarding may listen. The listen specification must be one of - the following forms: + Specifies the addresses/ports on which a remote TCP port forward- + ing may listen. The listen specification must be one of the fol- + lowing forms: PermitListen port PermitListen host:port Multiple permissions may be specified by separating them with - whitespace. An argument of any can be used to remove all - restrictions and permit any listen requests. An argument of none + whitespace. An argument of any can be used to remove all re- + strictions and permit any listen requests. An argument of none can be used to prohibit all listen requests. The host name may contain wildcards as described in the PATTERNS section in - ssh_config(5). The wildcard M-bM-^@M-^X*M-bM-^@M-^Y can also be used in place of a + ssh_config(5). The wildcard '*' can also be used in place of a port number to allow all ports. By default all port forwarding listen requests are permitted. Note that the GatewayPorts option may further restrict which addresses may be listened on. Note - also that ssh(1) will request a listen host of M-bM-^@M-^\localhostM-bM-^@M-^] if no + also that ssh(1) will request a listen host of "localhost" if no listen host was specifically requested, and this name is treated - differently to explicit localhost addresses of M-bM-^@M-^\127.0.0.1M-bM-^@M-^] and - M-bM-^@M-^\::1M-bM-^@M-^]. + differently to explicit localhost addresses of "127.0.0.1" and + "::1". PermitOpen - Specifies the destinations to which TCP port forwarding is - permitted. The forwarding specification must be one of the - following forms: + Specifies the destinations to which TCP port forwarding is per- + mitted. The forwarding specification must be one of the follow- + ing forms: PermitOpen host:port PermitOpen IPv4_addr:port PermitOpen [IPv6_addr]:port - Multiple forwards may be specified by separating them with - whitespace. An argument of any can be used to remove all - restrictions and permit any forwarding requests. An argument of - none can be used to prohibit all forwarding requests. The - wildcard M-bM-^@M-^X*M-bM-^@M-^Y can be used for host or port to allow all hosts or - ports respectively. Otherwise, no pattern matching or address - lookups are performed on supplied names. By default all port - forwarding requests are permitted. + Multiple forwards may be specified by separating them with white- + space. An argument of any can be used to remove all restrictions + and permit any forwarding requests. An argument of none can be + used to prohibit all forwarding requests. The wildcard '*' can + be used for host or port to allow all hosts or ports respec- + tively. Otherwise, no pattern matching or address lookups are + performed on supplied names. By default all port forwarding re- + quests are permitted. PermitRootLogin Specifies whether root can log in using ssh(1). The argument @@ -874,8 +932,8 @@ default is prohibit-password. If this option is set to prohibit-password (or its deprecated - alias, without-password), password and keyboard-interactive - authentication are disabled for root. + alias, without-password), password and keyboard-interactive au- + thentication are disabled for root. If this option is set to forced-commands-only, root login with public key authentication will be allowed, but only if the @@ -890,10 +948,10 @@ yes. PermitTunnel - Specifies whether tun(4) device forwarding is allowed. The - argument must be yes, point-to-point (layer 3), ethernet (layer - 2), or no. Specifying yes permits both point-to-point and - ethernet. The default is no. + Specifies whether tun(4) device forwarding is allowed. The argu- + ment must be yes, point-to-point (layer 3), ethernet (layer 2), + or no. Specifying yes permits both point-to-point and ethernet. + The default is no. Independent of this setting, the permissions of the selected tun(4) device must allow access to the user. @@ -901,11 +959,11 @@ PermitUserEnvironment Specifies whether ~/.ssh/environment and environment= options in ~/.ssh/authorized_keys are processed by sshd(8). Valid options - are yes, no or a pattern-list specifying which environment - variable names to accept (for example "LANG,LC_*"). The default - is no. Enabling environment processing may enable users to - bypass access restrictions in some configurations using - mechanisms such as LD_PRELOAD. + are yes, no or a pattern-list specifying which environment vari- + able names to accept (for example "LANG,LC_*"). The default is + no. Enabling environment processing may enable users to bypass + access restrictions in some configurations using mechanisms such + as LD_PRELOAD. PermitUserRC Specifies whether any ~/.ssh/rc file is executed. The default is @@ -913,21 +971,20 @@ PerSourceMaxStartups Specifies the number of unauthenticated connections allowed from - a given source address, or M-bM-^@M-^\noneM-bM-^@M-^] if there is no limit. This + a given source address, or "none" if there is no limit. This limit is applied in addition to MaxStartups, whichever is lower. The default is none. PerSourceNetBlockSize Specifies the number of bits of source address that are grouped - together for the purposes of applying PerSourceMaxStartups - limits. Values for IPv4 and optionally IPv6 may be specified, - separated by a colon. The default is 32:128, which means each - address is considered individually. + together for the purposes of applying PerSourceMaxStartups lim- + its. Values for IPv4 and optionally IPv6 may be specified, sepa- + rated by a colon. The default is 32:128, which means each ad- + dress is considered individually. PidFile - Specifies the file that contains the process ID of the SSH - daemon, or none to not write one. The default is - /var/run/sshd.pid. + Specifies the file that contains the process ID of the SSH dae- + mon, or none to not write one. The default is /var/run/sshd.pid. Port Specifies the port number that sshd(8) listens on. The default is 22. Multiple options of this type are permitted. See also @@ -944,71 +1001,47 @@ shell, /etc/profile, or equivalent.) The default is yes. PubkeyAcceptedAlgorithms - Specifies the signature algorithms that will be accepted for - public key authentication as a list of comma-separated patterns. - Alternately if the specified list begins with a M-bM-^@M-^X+M-bM-^@M-^Y character, - then the specified algorithms will be appended to the default set - instead of replacing them. If the specified list begins with a - M-bM-^@M-^X-M-bM-^@M-^Y character, then the specified algorithms (including - wildcards) will be removed from the default set instead of - replacing them. If the specified list begins with a M-bM-^@M-^X^M-bM-^@M-^Y - character, then the specified algorithms will be placed at the - head of the default set. The default for this option is: - - ssh-ed25519-cert-v01@openssh.com, - ecdsa-sha2-nistp256-cert-v01@openssh.com, - ecdsa-sha2-nistp384-cert-v01@openssh.com, - ecdsa-sha2-nistp521-cert-v01@openssh.com, - sk-ssh-ed25519-cert-v01@openssh.com, - sk-ecdsa-sha2-nistp256-cert-v01@openssh.com, - rsa-sha2-512-cert-v01@openssh.com, - rsa-sha2-256-cert-v01@openssh.com, - ssh-ed25519, - ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521, - sk-ssh-ed25519@openssh.com, - sk-ecdsa-sha2-nistp256@openssh.com, - rsa-sha2-512,rsa-sha2-256 - - The list of available signature algorithms may also be obtained - using "ssh -Q PubkeyAcceptedAlgorithms". - - PubkeyAuthOptions - Sets one or more public key authentication options. The - supported keywords are: none (the default; indicating no - additional options are enabled), touch-required and - verify-required. - - The touch-required option causes public key authentication using - a FIDO authenticator algorithm (i.e. ecdsa-sk or ed25519-sk) to - always require the signature to attest that a physically present - user explicitly confirmed the authentication (usually by touching - the authenticator). By default, sshd(8) requires user presence - unless overridden with an authorized_keys option. The - touch-required flag disables this override. + Option compatibility. See PubkeyAlgorithms - The verify-required option requires a FIDO key signature attest - that the user was verified, e.g. via a PIN. + PubkeyAcceptedKeyTypes + Option compatibility. See PubkeyAlgorithms - Neither the touch-required or verify-required options have any - effect for other, non-FIDO, public key types. + PubkeyAlgorithms + Specifies the publickey algorithms that will be accepted for + "publickey" authentication as a comma-separated pattern list. + See PATTERNS in ssh_config(5) for more information on patterns. + The default * will allow all algorithms. Also algorithms has to + be accepted by patterns of option AcceptedAlgorithms. Note algo- + rithms that use X.509 certificates depend from X509KeyAlgorithm + and is enough patter to match one of names set in + X509KeyAlgorithm for a certain key-type to enable all from that + key-type. The list of available key algorithms may also be ob- + tained using "ssh -Q key". PubkeyAuthentication - Specifies whether public key authentication is allowed. The - default is yes. + Specifies whether public key authentication is allowed. The de- + fault is yes. + + RDomain + Specifies an explicit routing domain that is applied after au- + thentication has completed. The user session, as well as any + forwarded or listening IP sockets, will be bound to this + rdomain(4). If the routing domain is set to %D, then the domain + in which the incoming connection was received will be applied. RekeyLimit Specifies the maximum amount of data that may be transmitted or - received before the session key is renegotiated, optionally - followed by a maximum amount of time that may pass before the - session key is renegotiated. The first argument is specified in - bytes and may have a suffix of M-bM-^@M-^XKM-bM-^@M-^Y, M-bM-^@M-^XMM-bM-^@M-^Y, or M-bM-^@M-^XGM-bM-^@M-^Y to indicate - Kilobytes, Megabytes, or Gigabytes, respectively. The default is - between M-bM-^@M-^X1GM-bM-^@M-^Y and M-bM-^@M-^X4GM-bM-^@M-^Y, depending on the cipher. The optional - second value is specified in seconds and may use any of the units + received before the session key is renegotiated, optionally fol- + lowed by a maximum amount of time that may pass before the ses- + sion key is renegotiated. The first argument is specified in + bytes and may have a suffix of 'K', 'M', or 'G' to indicate Kilo- + bytes, Megabytes, or Gigabytes, respectively. The default is be- + tween '1G' and '4G', depending on the cipher. The optional sec- + ond value is specified in seconds and may use any of the units documented in the TIME FORMATS section. The default value for - RekeyLimit is default none, which means that rekeying is - performed after the cipher's default amount of data has been sent - or received and no time based rekeying is done. + RekeyLimit is default none, which means that rekeying is per- + formed after the cipher's default amount of data has been sent or + received and no time based rekeying is done. RequiredRSASize Specifies the minimum RSA key size (in bits) that sshd(8) will @@ -1018,32 +1051,24 @@ RevokedKeys Specifies revoked public keys file, or none to not use one. Keys - listed in this file will be refused for public key - authentication. Note that if this file is not readable, then - public key authentication will be refused for all users. Keys - may be specified as a text file, listing one public key per line, - or as an OpenSSH Key Revocation List (KRL) as generated by - ssh-keygen(1). For more information on KRLs, see the KEY - REVOCATION LISTS section in ssh-keygen(1). - - RDomain - Specifies an explicit routing domain that is applied after - authentication has completed. The user session, as well as any - forwarded or listening IP sockets, will be bound to this - rdomain(4). If the routing domain is set to %D, then the domain - in which the incoming connection was received will be applied. - - SecurityKeyProvider - Specifies a path to a library that will be used when loading FIDO - authenticator-hosted keys, overriding the default of using the - built-in USB HID support. - - SetEnv Specifies one or more environment variables to set in child - sessions started by sshd(8) as M-bM-^@M-^\NAME=VALUEM-bM-^@M-^]. The environment - value may be quoted (e.g. if it contains whitespace characters). - Environment variables set by SetEnv override the default - environment and any variables specified by the user via AcceptEnv - or PermitUserEnvironment. + listed in this file will be refused for public key authentica- + tion. Note that if this file is not readable, then public key + authentication will be refused for all users. Keys may be speci- + fied as a text file, listing one public key per line, or as an + custom OpenSSH Key Revocation List (KRL) as generated by + ssh-keygen(1). For more information on KRLs, see the KEY REVOCA- + TION LISTS section in ssh-keygen(1). + + SetEnv Specifies one or more environment variables to set in child ses- + sions started by sshd(8) as "NAME=VALUE". Variables and their + contents are specified as pattern-list. Lists may be separated + by whitespace or spread across multiple SetEnv directives. The + environment value may be quoted (e.g. if it contains whitespace + characters). Environment variables set by SetEnv override the + default environment and any variables specified by the user via + AcceptEnv or PermitUserEnvironment. These variables do not over- + ride variables set in child session by daemon itself. Variables + set by daemon are described in ENVIRONMENT section of ssh(1). StreamLocalBindMask Sets the octal file creation mode mask (umask) used when creating @@ -1079,8 +1104,8 @@ Arguments should be a subsystem name and a command (with optional arguments) to execute upon subsystem request. - The command sftp-server implements the SFTP file transfer - subsystem. + The command sftp-server implements the SFTP file transfer subsys- + tem. Alternately the name internal-sftp implements an in-process SFTP server. This may simplify configurations using ChrootDirectory @@ -1091,18 +1116,17 @@ SyslogFacility Gives the facility code that is used when logging messages from sshd(8). The possible values are: DAEMON, USER, AUTH, LOCAL0, - LOCAL1, LOCAL2, LOCAL3, LOCAL4, LOCAL5, LOCAL6, LOCAL7. The - default is AUTH. + LOCAL1, LOCAL2, LOCAL3, LOCAL4, LOCAL5, LOCAL6, LOCAL7. The de- + fault is AUTH. TCPKeepAlive Specifies whether the system should send TCP keepalive messages to the other side. If they are sent, death of the connection or crash of one of the machines will be properly noticed. However, - this means that connections will die if the route is down - temporarily, and some people find it annoying. On the other - hand, if TCP keepalives are not sent, sessions may hang - indefinitely on the server, leaving "ghost" users and consuming - server resources. + this means that connections will die if the route is down tempo- + rarily, and some people find it annoying. On the other hand, if + TCP keepalives are not sent, sessions may hang indefinitely on + the server, leaving "ghost" users and consuming server resources. The default is yes (to send TCP keepalive messages), and the server will notice if the network goes down or the client host @@ -1111,42 +1135,42 @@ To disable TCP keepalive messages, the value should be set to no. TrustedUserCAKeys - Specifies a file containing public keys of certificate - authorities that are trusted to sign user certificates for - authentication, or none to not use one. Keys are listed one per - line; empty lines and comments starting with M-bM-^@M-^X#M-bM-^@M-^Y are allowed. If - a certificate is presented for authentication and has its signing - CA key listed in this file, then it may be used for - authentication for any user listed in the certificate's - principals list. Note that certificates that lack a list of - principals will not be permitted for authentication using - TrustedUserCAKeys. For more details on certificates, see the - CERTIFICATES section in ssh-keygen(1). + Specifies a file containing public keys of certificate authori- + ties that are trusted to sign user certificates for authentica- + tion, or none to not use one. Keys are listed one per line; + empty lines and comments starting with '#' are allowed. If a + certificate is presented for authentication and has its signing + CA key listed in this file, then it may be used for authentica- + tion for any user listed in the certificate's principals list. + Note that certificates that lack a list of principals will not be + permitted for authentication using TrustedUserCAKeys. For more + details on certificates, see the CERTIFICATES section in + ssh-keygen(1). UnusedConnectionTimeout Specifies whether and how quickly sshd(8) should close client connections with no open channels. Open channels include active - shell, command execution or subsystem sessions, connected - network, socket, agent or X11 forwardings. Forwarding listeners, + shell, command execution or subsystem sessions, connected net- + work, socket, agent or X11 forwardings. Forwarding listeners, such as those from the ssh(1) -R flag, are not considered as open channels and do not prevent the timeout. The timeout value is specified in seconds or may use any of the units documented in the TIME FORMATS section. - Note that this timeout starts when the client connection - completes user authentication but before the client has an - opportunity to open any channels. Caution should be used when - using short timeout values, as they may not provide sufficient - time for the client to request and open its channels before - terminating the connection. + Note that this timeout starts when the client connection com- + pletes user authentication but before the client has an opportu- + nity to open any channels. Caution should be used when using + short timeout values, as they may not provide sufficient time for + the client to request and open its channels before terminating + the connection. The default none is to never expire connections for having no open channels. This option may be useful in conjunction with ChannelTimeout. UseDNS Specifies whether sshd(8) should look up the remote host name, - and to check that the resolved host name for the remote IP - address maps back to the very same IP address. + and to check that the resolved host name for the remote IP ad- + dress maps back to the very same IP address. If this option is set to no (the default) then only addresses and not host names may be used in ~/.ssh/authorized_keys from and @@ -1154,9 +1178,9 @@ UsePAM Enables the Pluggable Authentication Module interface. If set to yes this will enable PAM authentication using - KbdInteractiveAuthentication and PasswordAuthentication in - addition to PAM account and session module processing for all - authentication types. + KbdInteractiveAuthentication and PasswordAuthentication in addi- + tion to PAM account and session module processing for all authen- + tication types. Because PAM keyboard-interactive authentication usually serves an equivalent role to password authentication, you should disable @@ -1165,10 +1189,52 @@ If UsePAM is enabled, you will not be able to run sshd(8) as a non-root user. The default is no. + UsePrivilegeSeparation + Specifies whether sshd(8) separates privileges by creating an un- + privileged child process to deal with incoming network traffic. + After successful authentication, another process will be created + that has the privilege of the authenticated user. The goal of + privilege separation is to prevent privilege escalation by con- + taining any corruption within the unprivileged processes. The + argument must be yes, no, or sandbox. If UsePrivilegeSeparation + is set to sandbox then the pre-authentication unprivileged + process is subject to additional restrictions. The default is + sandbox. + + VACertificateFile + File with X.509 certificates in PEM format concatenated together. + In use when VAType is set to ocspspec. The default value is '' + (empty). Certificates from that file explicitly trust 'OCSP + Responder' public key. They are used as trusted certificates in + addition to certificates from CACertificateFile and + CACertificatePath to verify responder certificate. + + ValidateFirst + Specifies whether first to perform validation of X.509 certifi- + cate and then authorization of public key. Process is applicable + for x509v3-* public key algorithms. The default is no, i.e. + first key is authorized and then X.509 certificate is validated. + + VAOCSPResponderURL + 'Access Location' / 'OCSP Service Locator' URL of the OCSP + provider. In use when VAType is set to ocspspec. + + VAType Specifies whether 'Online Certificate Status Protocol' (OCSP) is + used to validate X.509 certificates. Accepted values are case + insensitive: + none do not use OCSP to validate certificates; + ocspcert + validate only certificates that specify 'OCSP + Service Locator' URL; + ocspspec + use specified in the configuration 'OCSP Responder' + to validate all certificates. + The default is none. + VersionAddendum - Optionally specifies additional text to append to the SSH - protocol banner sent by the server upon connection. The default - is none. + Optionally specifies additional text to append to the SSH proto- + col banner sent by the server upon connection. The default is + none. X11DisplayOffset Specifies the first display number available for sshd(8)'s X11 @@ -1187,10 +1253,10 @@ and substitution occur on the client side. The security risk of using X11 forwarding is that the client's X11 display server may be exposed to attack when the SSH client requests forwarding (see - the warnings for ForwardX11 in ssh_config(5)). A system - administrator may have a stance in which they want to protect - clients that may expose themselves to attack by unwittingly - requesting X11 forwarding, which can warrant a no setting. + the warnings for ForwardX11 in ssh_config(5)). A system adminis- + trator may have a stance in which they want to protect clients + that may expose themselves to attack by unwittingly requesting + X11 forwarding, which can warrant a no setting. Note that disabling X11 forwarding does not prevent users from forwarding X11 traffic, as users can always install their own @@ -1204,21 +1270,55 @@ localhost. This prevents remote hosts from connecting to the proxy display. However, some older X11 clients may not function with this configuration. X11UseLocalhost may be set to no to - specify that the forwarding server should be bound to the - wildcard address. The argument must be yes or no. The default - is yes. + specify that the forwarding server should be bound to the wild- + card address. The argument must be yes or no. The default is + yes. + + X509KeyAlgorithm + Specifies how X.509 certificates and signatures are encoded. It + is possible to have multiple algorithms in form specified in X509 + Key Algorithms Format. Programs use the first listed for ECDSA, + Ed25519, RSA, or DSA key in signing and accept all listed. + + The default for certificates with ECDSA keys is: + X509KeyAlgorithm + x509v3-ecdsa-sha2-nistp256,ssh-sha256,ecdsa-sha2-nistp256 + X509KeyAlgorithm + x509v3-ecdsa-sha2-nistp384,ssh-sha384,ecdsa-sha2-nistp384 + X509KeyAlgorithm + x509v3-ecdsa-sha2-nistp521,ssh-sha512,ecdsa-sha2-nistp521 + + The default for certificates with Ed25519 keys is: + X509KeyAlgorithm x509v3-ssh-ed25519,none,ssh-ed25519 + + The default for certificates with RSA key is: + X509KeyAlgorithm + x509v3-rsa2048-sha256,rsa2048-sha256,rsa2048-sha256 + X509KeyAlgorithm x509v3-ssh-rsa,rsa-sha1,ssh-rsa + X509KeyAlgorithm x509v3-sign-rsa,rsa-sha1 + X509KeyAlgorithm x509v3-sign-rsa,rsa-md5 + + The default for certificates with DSA key is: + X509KeyAlgorithm x509v3-ssh-dss,dss-raw,ssh-dss + X509KeyAlgorithm x509v3-sign-dss,dss-asn1 + X509KeyAlgorithm x509v3-sign-dss,dss-raw + + Note for EC curves nistp256, nistp384, and nistp521 correspond + crypto(3) library curves prime256v1, secp384r1, and secp521r1. + Support of EC curves depend from library version. See ecparam(1) + to find how to list curves supported by library. XAuthLocation Specifies the full pathname of the xauth(1) program, or none to not use one. The default is /usr/X11R6/bin/xauth. TIME FORMATS - sshd(8) command-line arguments and configuration file options that - specify time may be expressed using a sequence of the form: - time[qualifier], where time is a positive integer value and qualifier is - one of the following: + sshd(8) command-line arguments and configuration file options that spec- + ify time may be expressed using a sequence of the form: time[qualifier], + where time is a positive integer value and qualifier is one of the fol- + lowing: - M-bM-^_M-(noneM-bM-^_M-) seconds + seconds s | S seconds m | M minutes h | H hours @@ -1238,12 +1338,12 @@ Arguments to some keywords can make use of tokens, which are expanded at runtime: - %% A literal M-bM-^@M-^X%M-bM-^@M-^Y. + %% A literal '%'. %C Identifies the connection endpoints, containing four space- separated values: client address, client port number, server address, and server port number. - %D The routing domain in which the incoming connection was - received. + %D The routing domain in which the incoming connection was re- + ceived (OS specific). %F The fingerprint of the CA key. %f The fingerprint of the key or certificate. %h The home directory of the user. @@ -1268,23 +1368,57 @@ ChrootDirectory accepts the tokens %%, %h, %U, and %u. - RoutingDomain accepts the token %D. + RDomain accepts the token %D. + +X509 Key Algorithms Format + sshd command-line arguments and configuration file options that specify + 'X509 Key Algorithms' expressed using a sequence of the form: + algorithm-name,digest-name[,signature-identifier], where algorithm-name + is name of public key algorithm, digest-name is + rsa-sha1 + : RSA key and signature using the SHA-1 hash; + rsa-md5 + : RSA key and signature using the MD5 hash; + rsa2048-sha256 + : RSA key and signature using the SHA-256 hash as specified + in "RFC 6187"; + dss-asn1 + : DSA key and signature as specified in "RFC 3279"; + dss-raw + : DSA key and signature in "ssh-dss" format as specified in + "RFC 4253". + ssh-sha256 + ssh-sha384 + ssh-sha512 + : ECDSA key and signature as specified in "RFC 6187". + none : Ed25519 key with PureEdDSA signature as specified in "RFC + 8032". + and optional signature-identifier. When signature-identifier is omitted + algorithm-name is used as identifier. + + For compatibility with old versions following signatures are supported: + sha256 + sha384 + sha512 : ECDSA key and signature encoded using ASN.1 notation. + Daemon sshd(8) and client ssh(1) switch automatically to those signatures + if is detected old version. FILES /etc/ssh/sshd_config Contains configuration data for sshd(8). This file should be - writable by root only, but it is recommended (though not - necessary) that it be world-readable. + writable by root only, but it is recommended (though not neces- + sary) that it be world-readable. SEE ALSO sftp-server(8), sshd(8) AUTHORS - OpenSSH is a derivative of the original and free ssh 1.2.12 release by + PKIX-SSH is a derivative of the original and free ssh 1.2.12 release by Tatu Ylonen. Aaron Campbell, Bob Beck, Markus Friedl, Niels Provos, Theo - de Raadt and Dug Song removed many bugs, re-added newer features and - created OpenSSH. Markus Friedl contributed the support for SSH protocol + de Raadt and Dug Song removed many bugs, re-added newer features and cre- + ated OpenSSH. Markus Friedl contributed the support for SSH protocol versions 1.5 and 2.0. Niels Provos and Markus Friedl contributed support - for privilege separation. + for privilege separation. Roumen Petrov contributed support for X.509 + certificates. -OpenBSD 7.3 July 28, 2023 OpenBSD 7.3 +BSD 28 July 2023 BSD diff -ruN openssh-9.4p1/sshd_config.5 openssh-9.4p1+x509-14.2.1/sshd_config.5 --- openssh-9.4p1/sshd_config.5 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/sshd_config.5 2023-08-20 10:07:00.000000000 +0300 @@ -1,3 +1,11 @@ +.\" Implement .Dd with the Mdocdate RCS keyword +.rn Dd xD +.de Dd +.ie \\$1$Mdocdate: \{\ +. xD \\$3 \\$2 \\$4 +.\} +.el .xD \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 +.. .\" .\" Author: Tatu Ylonen .\" Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -12,6 +20,7 @@ .\" Copyright (c) 1999,2000 Markus Friedl. All rights reserved. .\" Copyright (c) 1999 Aaron Campbell. All rights reserved. .\" Copyright (c) 1999 Theo de Raadt. All rights reserved. +.\" Copyright (c) 2002-2022 Roumen Petrov. All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions @@ -39,7 +48,7 @@ .Os .Sh NAME .Nm sshd_config -.Nd OpenSSH daemon configuration file +.Nd Secure shell daemon configuration file .Sh DESCRIPTION .Xr sshd 8 reads configuration data from @@ -55,11 +64,32 @@ Arguments may optionally be enclosed in double quotes .Pq \&" in order to represent arguments containing spaces. +Configuration options may be separated by whitespace or +optional whitespace and exactly one +.Ql = ; +the latter format is useful to avoid the need to quote whitespace +when specifying configuration options. .Pp The possible keywords and their meanings are as follows (note that keywords are case-insensitive and arguments are case-sensitive): .Bl -tag -width Ds +.It Cm AcceptedAlgorithms +Specifies the publickey algorithms as a comma-separated pattern +list that will be announced to client if client supports extension +negotiation mechanism. +See +.Em PATTERNS +in +.Xr ssh_config 5 +for more information on patterns. +The default +.Dq * +will announce all algorithms. +Note algorithms that use X.509 certificates depend from option +.Cm X509KeyAlgorithm . +The list of available key algorithms may also be obtained using +.Qq ssh -Q key . .It Cm AcceptEnv Specifies what environment variables sent by the client will be copied into the session's @@ -106,6 +136,20 @@ Note that disabling agent forwarding does not improve security unless users are also denied shell access, as they can always install their own forwarders. +.It Cm AllowedCertPurpose +The intended use for the X.509 client certificate. Without this option +no chain verification will be done. Currently accepted uses are case +insensitive: +.Bl -tag -width Ds -compact +.It Cm sslclient | Cm SSL client | Cm SSL_client | Cm client +only SSL-client purpose +.It Cm any | Cm Any Purpose | Cm Any_Purpose | Cm AnyPurpose +allow any purpose +.It Cm skip | Cm '' Li (empty) +do not check purpose +.El +The default is +.Cm sslclient . .It Cm AllowGroups This keyword can be followed by a list of group name patterns, separated by spaces. @@ -117,7 +161,9 @@ .Cm DenyGroups , .Cm AllowGroups . .Pp -See PATTERNS in +See +.Em PATTERNS +in .Xr ssh_config 5 for more information on patterns. This keyword may appear multiple times in @@ -177,7 +223,9 @@ .Cm DenyUsers , .Cm AllowUsers . .Pp -See PATTERNS in +See +.Em PATTERNS +in .Xr ssh_config 5 for more information on patterns. This keyword may appear multiple times in @@ -250,7 +298,7 @@ .Pp The program should produce on standard output zero or more lines of authorized_keys output (see -.Sx AUTHORIZED_KEYS +.Em AUTHORIZED_KEYS in .Xr sshd 8 ) . .Cm AuthorizedKeysCommand @@ -275,7 +323,9 @@ will refuse to start. .It Cm AuthorizedKeysFile Specifies the file that contains the public keys used for user authentication. -The format is described in the AUTHORIZED_KEYS FILE FORMAT section of +The format is described in the +.Em AUTHORIZED_KEYS FILE FORMAT +section of .Xr sshd 8 . Arguments to .Cm AuthorizedKeysFile @@ -339,7 +389,7 @@ this file lists names, one of which must appear in the certificate for it to be accepted for authentication. Names are listed one per line preceded by key options (as described in -.Sx AUTHORIZED_KEYS FILE FORMAT +.Em AUTHORIZED_KEYS FILE FORMAT in .Xr sshd 8 ) . Empty lines and comments starting with @@ -378,16 +428,68 @@ .Cm none then no banner is displayed. By default, no banner is displayed. +.It Cm CACertificateFile +.Dq X509 store +option: +This file contain multiple certificates of certificate signers in +PEM format concatenated together. The default is +.Pa /etc/ssh/ca/ca-bundle.crt . +.It Cm CACertificatePath +.Dq X509 store +option: +.Dq "Hash dir" +with certificates of certificate signers. Each certificate should be +stored in separate file with name [HASH].[NUMBER], where [HASH] is +certificate hash value and [NUMBER] is an integer starting from zero. +The default is +.Pa /etc/ssh/ca/crt . +.It Cm CAldapVersion +.Dq X509 store +option: +Specifies LDAP protocol version. +The default is not specified and depend from LDAP library. +.It Cm CAldapURL +.Dq X509 store +option: +Specifies hostport and dn(distinguished name) of LDAP URLs (Uniform Resource Locators) as detailed in RFC 2255. +The rest of URL is build internally. +Because of options parser limitation use +.Sq %3D +instead of +.Sq = +! +LDAP initialization method may require URL to be escaped, i.e. use +.Sq %2C +instead of +.Sq \&, +(comma). +Escaped URL don't depend from LDAP initialization method. +.It Cm CARevocationFile +.Dq X509 store +option: +This file contain multiple +.Dq "Certificate Revocation List" +(CRL) of certificate signers in PEM format concatenated together. +The default is +.Pa /etc/ssh/ca/ca-bundle.crl . +.It Cm CARevocationPath +.Dq X509 store +option: +.Dq "Hash dir" +with +.Dq "Certificate Revocation List" +(CRL) of certificate signers. Each CRL should be stored in separate +file with name [HASH].r[NUMBER], where [HASH] is CRL hash value and +[NUMBER] is an integer starting from zero. The default is +.Pa /etc/ssh/ca/crl . .It Cm CASignatureAlgorithms -Specifies which algorithms are allowed for signing of certificates -by certificate authorities (CAs). +Specifies which algorithms are allowed for signing of custom certificates +by custom certificate authorities (CAs). The default is: .Bd -literal -offset indent -ssh-ed25519,ecdsa-sha2-nistp256, -ecdsa-sha2-nistp384,ecdsa-sha2-nistp521, -sk-ssh-ed25519@openssh.com, -sk-ecdsa-sha2-nistp256@openssh.com, -rsa-sha2-512,rsa-sha2-256 +ssh-ed25519, +ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521, +rsa-sha2-512,rsa-sha2-256,ssh-rsa .Ed .Pp If the specified list begins with a @@ -399,7 +501,7 @@ character, then the specified algorithms (including wildcards) will be removed from the default set instead of replacing them. .Pp -Certificates signed using other algorithms will not be accepted for +Custom certificates signed using other algorithms will not be accepted for public key or host-based authentication. .It Cm ChannelTimeout Specifies whether and how quickly @@ -632,7 +734,9 @@ .Cm DenyGroups , .Cm AllowGroups . .Pp -See PATTERNS in +See +.Em PATTERNS +in .Xr ssh_config 5 for more information on patterns. This keyword may appear multiple times in @@ -653,7 +757,9 @@ .Cm DenyUsers , .Cm AllowUsers . .Pp -See PATTERNS in +See +.Em PATTERNS +in .Xr ssh_config 5 for more information on patterns. This keyword may appear multiple times in @@ -746,44 +852,34 @@ The default is .Cm yes . .It Cm HostbasedAcceptedAlgorithms -Specifies the signature algorithms that will be accepted for hostbased -authentication as a list of comma-separated patterns. -Alternately if the specified list begins with a -.Sq + -character, then the specified signature algorithms will be appended to -the default set instead of replacing them. -If the specified list begins with a -.Sq - -character, then the specified signature algorithms (including wildcards) -will be removed from the default set instead of replacing them. -If the specified list begins with a -.Sq ^ -character, then the specified signature algorithms will be placed at -the head of the default set. -The default for this option is: -.Bd -literal -offset 3n -ssh-ed25519-cert-v01@openssh.com, -ecdsa-sha2-nistp256-cert-v01@openssh.com, -ecdsa-sha2-nistp384-cert-v01@openssh.com, -ecdsa-sha2-nistp521-cert-v01@openssh.com, -sk-ssh-ed25519-cert-v01@openssh.com, -sk-ecdsa-sha2-nistp256-cert-v01@openssh.com, -rsa-sha2-512-cert-v01@openssh.com, -rsa-sha2-256-cert-v01@openssh.com, -ssh-ed25519, -ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521, -sk-ssh-ed25519@openssh.com, -sk-ecdsa-sha2-nistp256@openssh.com, -rsa-sha2-512,rsa-sha2-256 -.Ed -.Pp -The list of available signature algorithms may also be obtained using -.Qq ssh -Q HostbasedAcceptedAlgorithms . -This was formerly named HostbasedAcceptedKeyTypes. +Option compatibility. See +.Cm HostbasedAlgorithms +.It Cm HostbasedAcceptedKeyTypes +Option compatibility. See +.Cm HostbasedAlgorithms +.It Cm HostbasedAlgorithms +Specifies the publickey algorithms that will be accepted in +.Dq hostbased +authentication as a comma-separated pattern list. +See +.Em PATTERNS +in +.Xr ssh_config 5 +for more information on patterns. +The default +.Dq * +will allow all algorithms. +Also algorithms has to be accepted by patterns of option +.Cm AcceptedAlgorithms . +Note algorithms that use X.509 certificates depend from option +.Cm X509KeyAlgorithm . +The list of available key algorithms may also be obtained using +.Qq ssh -Q key . .It Cm HostbasedAuthentication Specifies whether rhosts or /etc/hosts.equiv authentication together with successful public key client host authentication is allowed (host-based authentication). +Also secure shell uses equavalient shosts and /etc/shosts.equiv. The default is .Cm no . .It Cm HostbasedUsesNameFromPacketOnly @@ -791,8 +887,9 @@ name lookup when matching the name in the .Pa ~/.shosts , .Pa ~/.rhosts , +.Pa /etc/hosts.equiv , and -.Pa /etc/hosts.equiv +.Pa /etc/shosts.equiv files during .Cm HostbasedAuthentication . A setting of @@ -829,6 +926,13 @@ .Xr sshd 8 . .Pp It is possible to have multiple host key files. +.Pp +For RSA, ECDSA, Ed25519 or DSA host key file may contain X.509 certificate that +match it. In addition file may contain extra X.509 certificates. +Extra certificates along with certificates from X.509 store are used +to build chain of certificates leading to a trusted certificate +authority if required by public key algorithm format. +.Pp It is also possible to specify public host key files instead. In this case operations on the private key will be delegated to an @@ -842,27 +946,13 @@ .Ev SSH_AUTH_SOCK environment variable. .It Cm HostKeyAlgorithms -Specifies the host key signature algorithms +Specifies the host key algorithms that the server offers. -The default for this option is: -.Bd -literal -offset 3n -ssh-ed25519-cert-v01@openssh.com, -ecdsa-sha2-nistp256-cert-v01@openssh.com, -ecdsa-sha2-nistp384-cert-v01@openssh.com, -ecdsa-sha2-nistp521-cert-v01@openssh.com, -sk-ssh-ed25519-cert-v01@openssh.com, -sk-ecdsa-sha2-nistp256-cert-v01@openssh.com, -rsa-sha2-512-cert-v01@openssh.com, -rsa-sha2-256-cert-v01@openssh.com, -ssh-ed25519, -ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521, -sk-ssh-ed25519@openssh.com, -sk-ecdsa-sha2-nistp256@openssh.com, -rsa-sha2-512,rsa-sha2-256 -.Ed -.Pp -The list of available signature algorithms may also be obtained using -.Qq ssh -Q HostKeyAlgorithms . +The default +.Dq * +allows all algorithms. +The list of available key algorithms may also be obtained using +.Qq ssh -Q key . .It Cm IgnoreRhosts Specifies whether to ignore per-user .Pa .rhosts @@ -879,7 +969,7 @@ Accepted values are .Cm yes (the default) to ignore all per-user files, -.Cm shosts-only +.Cm rhosts-only to allow the use of .Pa .shosts but to ignore @@ -887,9 +977,9 @@ or .Cm no to allow both -.Pa .shosts +.Pa .rhosts and -.Pa rhosts . +.Pa .shosts . .It Cm IgnoreUserKnownHosts Specifies whether .Xr sshd 8 @@ -961,12 +1051,12 @@ All authentication styles from .Xr login.conf 5 are supported. -The default is -.Cm yes . The argument to this keyword must be .Cm yes or .Cm no . +The default is +.Cm yes . .Cm ChallengeResponseAuthentication is a deprecated alias for this. .It Cm KerberosAuthentication @@ -1037,21 +1127,46 @@ .It ecdh-sha2-nistp521 .It -sntrup761x25519-sha512@openssh.com +sntrup761x25519-sha512@openssh.com (if build) .El .Pp The default is: .Bd -literal -offset indent -sntrup761x25519-sha512@openssh.com, curve25519-sha256,curve25519-sha256@libssh.org, ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521, diffie-hellman-group-exchange-sha256, -diffie-hellman-group16-sha512,diffie-hellman-group18-sha512, -diffie-hellman-group14-sha256 +diffie-hellman-group16-sha512, +diffie-hellman-group18-sha512, +diffie-hellman-group14-sha256, +sntrup761x25519-sha512@openssh.com, +diffie-hellman-group14-sha1 .Ed .Pp The list of available key exchange algorithms may also be obtained using -.Qq ssh -Q KexAlgorithms . +.Qq ssh -Q kex . +.It Cm KeyAllowSelfIssued +Specifies whether only encoded public key or X.509 certificate listed in +.Cm AuthorizedKeysFile +can allow self-issued X.509 certificate to be used for user authentication. +The default is +.Dq no . +Unsupported if daemon is build without +.Dq X509 store . +.Pp +A certificate (including self-issued) is accepted for user authentication +if encoded public key or encoded X.509 certificate or distinguished name +is listed in +.Cm AuthorizedKeysFile , +if is valid and if is verified by certificates from +.Dq X509 store . +See +.Xr verify 1 . +If option is set to +.Dq yes +self-issued certificate is accepted when its public key +match public key extracted from entry in +.Cm AuthorizedKeysFile . +In this case validity of certificate is not checked. .It Cm ListenAddress Specifies the local addresses .Xr sshd 8 @@ -1133,7 +1248,9 @@ function, and all code in the .Pa packet.c file. -This option is intended for debugging and no overrides are enabled by default. +This option is intended for debugging and no overrides are enabled by default, +i.e. default value is +.Cm none . .It Cm MACs Specifies the available MAC (message authentication code) algorithms. The MAC algorithm is used for data integrity protection. @@ -1203,6 +1320,15 @@ .Pp The list of available MAC algorithms may also be obtained using .Qq ssh -Q mac . +.It Cm MandatoryCRL +.Dq X509 store +option: +Specifies whether CRL must present in store for all certificates in +.Dq certificate chain +with attribute +.Dq X509v3 CRL Distribution Points . +The default is +.Cm no . .It Cm Match Introduces a conditional block. If all of the criteria on the @@ -1238,7 +1364,7 @@ .Pp The match patterns may consist of single entries or comma-separated lists and may use the wildcard and negation operators described in the -.Sx PATTERNS +.Em PATTERNS section of .Xr ssh_config 5 . .Pp @@ -1282,7 +1408,7 @@ .Cm ForceCommand , .Cm GatewayPorts , .Cm GSSAPIAuthentication , -.Cm HostbasedAcceptedAlgorithms , +.Cm HostbasedAlgorithms , .Cm HostbasedAuthentication , .Cm HostbasedUsesNameFromPacketOnly , .Cm IgnoreRhosts , @@ -1301,7 +1427,7 @@ .Cm PermitTTY , .Cm PermitTunnel , .Cm PermitUserRC , -.Cm PubkeyAcceptedAlgorithms , +.Cm PubkeyAlgorithms , .Cm PubkeyAuthentication , .Cm PubkeyAuthOptions , .Cm RekeyLimit , @@ -1582,78 +1708,45 @@ The default is .Cm yes . .It Cm PubkeyAcceptedAlgorithms -Specifies the signature algorithms that will be accepted for public key -authentication as a list of comma-separated patterns. -Alternately if the specified list begins with a -.Sq + -character, then the specified algorithms will be appended to the default set -instead of replacing them. -If the specified list begins with a -.Sq - -character, then the specified algorithms (including wildcards) will be removed -from the default set instead of replacing them. -If the specified list begins with a -.Sq ^ -character, then the specified algorithms will be placed at the head of the -default set. -The default for this option is: -.Bd -literal -offset 3n -ssh-ed25519-cert-v01@openssh.com, -ecdsa-sha2-nistp256-cert-v01@openssh.com, -ecdsa-sha2-nistp384-cert-v01@openssh.com, -ecdsa-sha2-nistp521-cert-v01@openssh.com, -sk-ssh-ed25519-cert-v01@openssh.com, -sk-ecdsa-sha2-nistp256-cert-v01@openssh.com, -rsa-sha2-512-cert-v01@openssh.com, -rsa-sha2-256-cert-v01@openssh.com, -ssh-ed25519, -ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521, -sk-ssh-ed25519@openssh.com, -sk-ecdsa-sha2-nistp256@openssh.com, -rsa-sha2-512,rsa-sha2-256 -.Ed -.Pp -The list of available signature algorithms may also be obtained using -.Qq ssh -Q PubkeyAcceptedAlgorithms . -.It Cm PubkeyAuthOptions -Sets one or more public key authentication options. -The supported keywords are: -.Cm none -(the default; indicating no additional options are enabled), -.Cm touch-required -and -.Cm verify-required . -.Pp -The -.Cm touch-required -option causes public key authentication using a FIDO authenticator algorithm -(i.e.\& -.Cm ecdsa-sk -or -.Cm ed25519-sk ) -to always require the signature to attest that a physically present user -explicitly confirmed the authentication (usually by touching the authenticator). -By default, -.Xr sshd 8 -requires user presence unless overridden with an authorized_keys option. -The -.Cm touch-required -flag disables this override. -.Pp -The -.Cm verify-required -option requires a FIDO key signature attest that the user was verified, -e.g. via a PIN. -.Pp -Neither the -.Cm touch-required -or -.Cm verify-required -options have any effect for other, non-FIDO, public key types. +Option compatibility. See +.Cm PubkeyAlgorithms +.It Cm PubkeyAcceptedKeyTypes +Option compatibility. See +.Cm PubkeyAlgorithms +.It Cm PubkeyAlgorithms +Specifies the publickey algorithms that will be accepted for +.Dq publickey +authentication as a comma-separated pattern list. +See +.Em PATTERNS +in +.Xr ssh_config 5 +for more information on patterns. +The default +.Cm * +will allow all algorithms. +Also algorithms has to be accepted by patterns of option +.Cm AcceptedAlgorithms . +Note algorithms that use X.509 certificates depend from +.Cm X509KeyAlgorithm +and is enough patter to match one of names set in +.Cm X509KeyAlgorithm +for a certain key-type to enable all from that key-type. +The list of available key algorithms may also be obtained using +.Qq ssh -Q key . .It Cm PubkeyAuthentication Specifies whether public key authentication is allowed. The default is .Cm yes . +.It Cm RDomain +Specifies an explicit routing domain that is applied after authentication +has completed. +The user session, as well as any forwarded or listening IP sockets, +will be bound to this +.Xr rdomain 4 . +If the routing domain is set to +.Cm \&%D , +then the domain in which the incoming connection was received will be applied. .It Cm RekeyLimit Specifies the maximum amount of data that may be transmitted or received before the session key is renegotiated, optionally followed by a maximum @@ -1697,29 +1790,20 @@ Note that if this file is not readable, then public key authentication will be refused for all users. Keys may be specified as a text file, listing one public key per line, or as -an OpenSSH Key Revocation List (KRL) as generated by +an custom OpenSSH Key Revocation List (KRL) as generated by .Xr ssh-keygen 1 . For more information on KRLs, see the KEY REVOCATION LISTS section in .Xr ssh-keygen 1 . -.It Cm RDomain -Specifies an explicit routing domain that is applied after authentication -has completed. -The user session, as well as any forwarded or listening IP sockets, -will be bound to this -.Xr rdomain 4 . -If the routing domain is set to -.Cm \&%D , -then the domain in which the incoming connection was received will be applied. -.It Cm SecurityKeyProvider -Specifies a path to a library that will be used when loading -FIDO authenticator-hosted keys, overriding the default of using -the built-in USB HID support. .It Cm SetEnv Specifies one or more environment variables to set in child sessions started by .Xr sshd 8 as .Dq NAME=VALUE . +Variables and their contents are specified as pattern-list. +Lists may be separated by whitespace or spread across multiple +.Cm SetEnv +directives. The environment value may be quoted (e.g. if it contains whitespace characters). Environment variables set by @@ -1729,6 +1813,12 @@ .Cm AcceptEnv or .Cm PermitUserEnvironment . +These variables do not override variables set in child session +by daemon itself. +Variables set by daemon are described in +.Em ENVIRONMENT +section of +.Xr ssh 1 . .It Cm StreamLocalBindMask Sets the octal file creation mode mask .Pq umask @@ -1896,6 +1986,80 @@ as a non-root user. The default is .Cm no . +.It Cm UsePrivilegeSeparation +Specifies whether +.Xr sshd 8 +separates privileges by creating an unprivileged child process +to deal with incoming network traffic. +After successful authentication, another process will be created that has +the privilege of the authenticated user. +The goal of privilege separation is to prevent privilege +escalation by containing any corruption within the unprivileged processes. +The argument must be +.Cm yes , +.Cm no , +or +.Cm sandbox . +If +.Cm UsePrivilegeSeparation +is set to +.Cm sandbox +then the pre-authentication unprivileged process is subject to additional +restrictions. +The default is +.Cm sandbox . +.It Cm VACertificateFile +File with X.509 certificates in PEM format concatenated together. +In use when +.Cm VAType +is set to +.Cm ocspspec . +The default value is +.Sq +.. +(empty). +Certificates from that file explicitly trust +.Sq "OCSP Responder" +public key. +They are used as trusted certificates in addition to certificates from +.Cm CACertificateFile +and +.Cm CACertificatePath +to verify responder certificate. +.It Cm ValidateFirst +Specifies whether first to perform validation of X.509 certificate +and then authorization of public key. +Process is applicable for x509v3-* public key algorithms. +The default is +.Cm no , +i.e. first key is authorized and then X.509 certificate is validated. +.It Cm VAOCSPResponderURL +.Sq "Access Location" +/ +.Sq "OCSP Service Locator" +URL of the OCSP provider. In use when +.Cm VAType +is set to +.Cm ocspspec . +.It Cm VAType +Specifies whether +.Sq "Online Certificate Status Protocol" +(OCSP) is used to validate X.509 certificates. +Accepted values are case insensitive: +.Bl -tag -offset indent -compact +.It none +do not use OCSP to validate certificates; +.It ocspcert +validate only certificates that specify +.Sq "OCSP Service Locator" +URL; +.It ocspspec +use specified in the configuration +.Sq "OCSP Responder" +to validate all certificates. +.El +The default is +.Cm none . .It Cm VersionAddendum Optionally specifies additional text to append to the SSH protocol banner sent by the server upon connection. @@ -1963,6 +2127,98 @@ .Cm no . The default is .Cm yes . +.It Cm X509KeyAlgorithm +Specifies how X.509 certificates and signatures are encoded. +It is possible to have multiple algorithms +in form specified in +.Sx X509 Key Algorithms Format . +Programs use the first listed for +.Cm ECDSA , +.Cm Ed25519 , +.Cm RSA , +or +.Cm DSA +key in signing and +accept all listed. +.Pp +The default for certificates with ECDSA keys is: +.Bl -item -offset indent -compact +.It +.Cm X509KeyAlgorithm +.Sm off +.Ar x509v3-ecdsa-sha2-nistp256 , Ar ssh-sha256 , Ar ecdsa-sha2-nistp256 +.Sm on +.It +.Cm X509KeyAlgorithm +.Sm off +.Ar x509v3-ecdsa-sha2-nistp384 , Ar ssh-sha384 , Ar ecdsa-sha2-nistp384 +.Sm on +.It +.Cm X509KeyAlgorithm +.Sm off +.Ar x509v3-ecdsa-sha2-nistp521 , Ar ssh-sha512 , Ar ecdsa-sha2-nistp521 +.Sm on +.El +.Pp +The default for certificates with Ed25519 keys is: +.Bl -item -offset indent -compact +.It +.Cm X509KeyAlgorithm +.Sm off +.Ar x509v3-ssh-ed25519 , Ar none , Ar ssh-ed25519 +.Sm on +.El +.Pp +The default for certificates with RSA key is: +.Bl -item -offset indent -compact +.It +.Cm X509KeyAlgorithm +.Sm off +.Ar x509v3-rsa2048-sha256 , Ar rsa2048-sha256 , Ar rsa2048-sha256 +.Sm on +.It +.Cm X509KeyAlgorithm +.Sm off +.Ar x509v3-ssh-rsa , Ar rsa-sha1 , Ar ssh-rsa +.Sm on +.It +.Cm X509KeyAlgorithm +.Sm off +.Ar x509v3-sign-rsa , Ar rsa-sha1 +.Sm on +.It +.Cm X509KeyAlgorithm +.Sm off +.Ar x509v3-sign-rsa , Ar rsa-md5 +.Sm on +.El +.Pp +The default for certificates with DSA key is: +.Bl -item -offset indent -compact +.It +.Cm X509KeyAlgorithm +.Sm off +.Ar x509v3-ssh-dss , Ar dss-raw , Ar ssh-dss +.Sm on +.It +.Cm X509KeyAlgorithm +.Sm off +.Ar x509v3-sign-dss , Ar dss-asn1 +.Sm on +.It +.Cm X509KeyAlgorithm +.Sm off +.Ar x509v3-sign-dss , Ar dss-raw +.Sm on +.El +.Pp +Note for EC curves nistp256, nistp384, and nistp521 correspond +.Xr crypto 3 +library curves prime256v1, secp384r1, and secp521r1. +Support of EC curves depend from library version. +See +.Xr ecparam 1 +to find how to list curves supported by library. .It Cm XAuthLocation Specifies the full pathname of the .Xr xauth 1 @@ -2026,7 +2282,7 @@ four space-separated values: client address, client port number, server address, and server port number. .It \&%D -The routing domain in which the incoming connection was received. +The routing domain in which the incoming connection was received (OS specific). .It %F The fingerprint of the CA key. .It %f @@ -2066,8 +2322,67 @@ .Cm ChrootDirectory accepts the tokens %%, %h, %U, and %u. .Pp -.Cm RoutingDomain +.Cm RDomain accepts the token %D. +.Sh X509 Key Algorithms Format +.Nm sshd +command-line arguments and configuration file options that specify +.Sq X509 Key Algorithms +expressed using a sequence of the form: +.Sm off +.Ar algorithm-name , Ar digest-name +.Op Ar \&, signature-identifier , +.Sm on +where +.Ar algorithm-name +is name of public key algorithm, +.Ar digest-name +is +.Bl -tag -compact -offset indent +.It Cm rsa-sha1 +: RSA key and signature using the SHA-1 hash; +.It Cm rsa-md5 +: RSA key and signature using the MD5 hash; +.It Cm rsa2048-sha256 +: RSA key and signature using the SHA-256 hash as specified in +.Dq RFC 6187 ; +.It Cm dss-asn1 +: DSA key and signature as specified in +.Dq RFC 3279 ; +.It Cm dss-raw +: DSA key and signature in +.Dq ssh-dss +format as specified in +.Dq RFC 4253 . +.It Cm ssh-sha256 +.It Cm ssh-sha384 +.It Cm ssh-sha512 +: ECDSA key and signature as specified in +.Dq RFC 6187 . +.It Cm none +: Ed25519 key with PureEdDSA signature as specified in +.Dq RFC 8032 . +.El +and optional +.Ar signature-identifier . +When +.Ar signature-identifier +is omitted +.Ar algorithm-name +is used as identifier. +.Pp +For compatibility with old versions following signatures are supported: +.Bl -tag -compact -offset indent +.It Cm sha256 +.It Cm sha384 +.It Cm sha512 +: ECDSA key and signature encoded using ASN.1 notation. +.El +Daemon +.Xr sshd 8 +and client +.Xr ssh 1 +switch automatically to those signatures if is detected old version. .Sh FILES .Bl -tag -width Ds .It Pa /etc/ssh/sshd_config @@ -2081,7 +2396,7 @@ .Xr sshd 8 .Sh AUTHORS .An -nosplit -OpenSSH is a derivative of the original and free +PKIX-SSH is a derivative of the original and free ssh 1.2.12 release by .An Tatu Ylonen . .An Aaron Campbell , Bob Beck , Markus Friedl , Niels Provos , @@ -2096,3 +2411,5 @@ and .An Markus Friedl contributed support for privilege separation. +.An Roumen Petrov +contributed support for X.509 certificates. diff -ruN openssh-9.4p1/ssh-dss.c openssh-9.4p1+x509-14.2.1/ssh-dss.c --- openssh-9.4p1/ssh-dss.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/ssh-dss.c 2023-08-20 10:07:01.000000000 +0300 @@ -1,6 +1,8 @@ /* $OpenBSD: ssh-dss.c,v 1.49 2023/03/05 05:34:09 dtucker Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. + * Copyright (c) 2011 Dr. Stephen Henson. All rights reserved. + * Copyright (c) 2011-2023 Roumen Petrov. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -23,15 +25,23 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifndef USE_OPENSSL_PROVIDER +/* TODO: implement OpenSSL 4.0 API, as OpenSSL 3.* is quite nonfunctional */ +# define OPENSSL_SUPPRESS_DEPRECATED +#endif + #include "includes.h" #ifdef WITH_OPENSSL #include +#include "evp-compat.h" #include -#include -#include #include #include @@ -40,311 +50,597 @@ #include "ssherr.h" #include "digest.h" #define SSHKEY_INTERNAL -#include "sshkey.h" +#include "sshxkey.h" +#include "xmalloc.h" +#include "log.h" -#include "openbsd-compat/openssl-compat.h" #define INTBLOB_LEN 20 #define SIGBLOB_LEN (2*INTBLOB_LEN) -static u_int -ssh_dss_size(const struct sshkey *key) + +int +sshdsa_verify_length(int bits) { + return bits != SSH_DSA_BITS + ? SSH_ERR_KEY_LENGTH : 0; +} + + +#ifdef WITH_OPENSSL_4_0_API +/* TODO: new methods compatible with OpenSSL 4.0 API. + * Remark: OpenSSL 3* is too buggy - almost each release fail + * or crash in regression tests. + */ +#else +/* management of elementary DSA key */ + +#ifndef HAVE_DSA_GENERATE_PARAMETERS_EX /* OpenSSL < 0.9.8 */ +static int +DSA_generate_parameters_ex(DSA *dsa, int bits, const unsigned char *seed, + int seed_len, int *counter_ret, unsigned long *h_ret, void *cb) { - const BIGNUM *dsa_p; + DSA *new_dsa, tmp_dsa; + + if (cb != NULL) + fatal_f("callback args not supported"); + new_dsa = DSA_generate_parameters(bits, (unsigned char *)seed, seed_len, + counter_ret, h_ret, NULL, NULL); + if (new_dsa == NULL) + return 0; + /* swap dsa/new_dsa then free new_dsa */ + tmp_dsa = *dsa; + *dsa = *new_dsa; + *new_dsa = tmp_dsa; + DSA_free(new_dsa); + return 1; +} +#endif + +#ifndef HAVE_DSA_GET0_KEY +/* opaque DSA key structure */ +static inline void +DSA_get0_key(const DSA *dsa, const BIGNUM **pub_key, const BIGNUM **priv_key) { + if (pub_key != NULL) *pub_key = dsa->pub_key; + if (priv_key != NULL) *priv_key = dsa->priv_key; +} + +static inline int +DSA_set0_key(DSA *dsa, BIGNUM *pub_key, BIGNUM *priv_key) { +/* If the pub_key in d is NULL, the corresponding input parameters MUST + * be non-NULL. The priv_key field may be left NULL. + * + * It is an error to give the results from get0 on d as input + * parameters. + */ + if (pub_key == dsa->pub_key + || (dsa->priv_key != NULL && priv_key == dsa->priv_key) + ) + return 0; - if (key->dsa == NULL) + if (pub_key != NULL) { BN_free(dsa->pub_key ); dsa->pub_key = pub_key ; } + if (priv_key != NULL) { BN_free(dsa->priv_key); dsa->priv_key = priv_key; } + + return 1; +} + + +static inline void +DSA_get0_pqg(const DSA *dsa, const BIGNUM **p, const BIGNUM **q, const BIGNUM **g) { + if (p != NULL) *p = dsa->p; + if (q != NULL) *q = dsa->q; + if (g != NULL) *g = dsa->g; +} + +static /*inline*/ int +DSA_set0_pqg(DSA *dsa, BIGNUM *p, BIGNUM *q, BIGNUM *g) { + /* If the fields in d are NULL, the corresponding input + * parameters MUST be non-NULL. + * + * It is an error to give the results from get0 on d + * as input parameters. + */ + if (p == dsa->p || q == dsa->q || g == dsa->g) return 0; - DSA_get0_pqg(key->dsa, &dsa_p, NULL, NULL); - return BN_num_bits(dsa_p); + + if (p != NULL) { BN_free(dsa->p); dsa->p = p; } + if (q != NULL) { BN_free(dsa->q); dsa->q = q; } + if (g != NULL) { BN_free(dsa->g); dsa->g = g; } + + return 1; } +#endif /* ndef HAVE_DSA_GET0_KEY */ + +#ifndef HAVE_EVP_PKEY_CMP /* OpenSSL < 0.9.8 */ +extern int /* see sshkey-crypto.c */ +ssh_EVP_PKEY_cmp_dsa(const EVP_PKEY *ka, const EVP_PKEY *kb); + +int +ssh_EVP_PKEY_cmp_dsa(const EVP_PKEY *ka, const EVP_PKEY *kb) { + int ret = -1; + DSA *a, *b = NULL; + const BIGNUM *a_p, *a_q, *a_g, *a_pub_key; + const BIGNUM *b_p, *b_q, *b_g, *b_pub_key; + + a = EVP_PKEY_get1_DSA((EVP_PKEY*)ka); + b = EVP_PKEY_get1_DSA((EVP_PKEY*)kb); + if (a == NULL || b == NULL) goto err; + + DSA_get0_pqg(a, &a_p, &a_q, &a_g); + DSA_get0_key(a, &a_pub_key, NULL); + + DSA_get0_pqg(b, &b_p, &b_q, &b_g); + DSA_get0_key(b, &b_pub_key, NULL); + + ret = + BN_cmp(a_p, b_p) == 0 && + BN_cmp(a_q, b_q) == 0 && + BN_cmp(a_g, b_g) == 0 && + BN_cmp(a_pub_key, b_pub_key) == 0; + +err: + DSA_free(b); + DSA_free(a); + return ret; +} +#endif + static int -ssh_dss_alloc(struct sshkey *k) -{ - if ((k->dsa = DSA_new()) == NULL) +sshkey_init_dsa_params(struct sshkey *key, BIGNUM *p, BIGNUM *q, BIGNUM *g) { + int r; + EVP_PKEY *pk = NULL; + DSA *dsa = NULL; + + pk = EVP_PKEY_new(); + if (pk == NULL) return SSH_ERR_ALLOC_FAIL; + + dsa = DSA_new(); + if (dsa == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto err; + } + + if (!EVP_PKEY_set1_DSA(pk, dsa)) { + r = SSH_ERR_LIBCRYPTO_ERROR; + goto err; + } + + /* transfer to key must be last operation - + if fail then caller could free arguments */ + if (!DSA_set0_pqg(dsa, p, q, g)) { + r = SSH_ERR_LIBCRYPTO_ERROR; + goto err; + } + + /* success */ + key->pk = pk; + pk = NULL; + r = 0; + +err: + DSA_free(dsa); + EVP_PKEY_free(pk); + return r; +} + +static int +sshkey_set_dsa_key(struct sshkey *key, BIGNUM *pub_key, BIGNUM *priv_key) { + int r; + DSA *dsa; + + dsa = EVP_PKEY_get1_DSA(key->pk); + if (dsa == NULL) + return SSH_ERR_INVALID_ARGUMENT; + + if (!DSA_set0_key(dsa, pub_key, priv_key)) { + r = SSH_ERR_LIBCRYPTO_ERROR; + goto err; + } + + /* success */ + r = 0; +err: + DSA_free(dsa); + return r; +} + + +static int +sshkey_validate_dsa_pub(const DSA *dsa) { + int r; + const BIGNUM *p = NULL; + + DSA_get0_pqg(dsa, &p, NULL, NULL); + + r = sshdsa_verify_length(BN_num_bits(p)); + if (r != 0) return r; + + /* other checks ? */ return 0; } -static void -ssh_dss_cleanup(struct sshkey *k) -{ - DSA_free(k->dsa); - k->dsa = NULL; +int +sshkey_validate_public_dsa(const struct sshkey *key) { + int r; + + if (key == NULL) return SSH_ERR_INVALID_ARGUMENT; + +{ DSA *dsa = EVP_PKEY_get1_DSA(key->pk); + if (dsa == NULL) + return SSH_ERR_INVALID_ARGUMENT; + r = sshkey_validate_dsa_pub(dsa); + DSA_free(dsa); } + return r; +} + + +extern int /* see sshkey-crypto.c */ +ssh_EVP_PKEY_complete_pub_dsa(EVP_PKEY *pk); + +int +ssh_EVP_PKEY_complete_pub_dsa(EVP_PKEY *pk) { + int r; + DSA *dsa; + + dsa = EVP_PKEY_get1_DSA(pk); + if (dsa == NULL) + return SSH_ERR_INVALID_ARGUMENT; + + r = sshkey_validate_dsa_pub(dsa); + + DSA_free(dsa); + return r; +} + static int -ssh_dss_equal(const struct sshkey *a, const struct sshkey *b) -{ - const BIGNUM *dsa_p_a, *dsa_q_a, *dsa_g_a, *dsa_pub_key_a; - const BIGNUM *dsa_p_b, *dsa_q_b, *dsa_g_b, *dsa_pub_key_b; +sshbuf_read_pub_dsa(struct sshbuf *buf, struct sshkey *key) { + int r; + BIGNUM *p = NULL, *q = NULL, *g = NULL; + BIGNUM *pub_key = NULL; - if (a->dsa == NULL || b->dsa == NULL) - return 0; - DSA_get0_pqg(a->dsa, &dsa_p_a, &dsa_q_a, &dsa_g_a); - DSA_get0_pqg(b->dsa, &dsa_p_b, &dsa_q_b, &dsa_g_b); - DSA_get0_key(a->dsa, &dsa_pub_key_a, NULL); - DSA_get0_key(b->dsa, &dsa_pub_key_b, NULL); - if (dsa_p_a == NULL || dsa_p_b == NULL || - dsa_q_a == NULL || dsa_q_b == NULL || - dsa_g_a == NULL || dsa_g_b == NULL || - dsa_pub_key_a == NULL || dsa_pub_key_b == NULL) - return 0; - if (BN_cmp(dsa_p_a, dsa_p_b) != 0) - return 0; - if (BN_cmp(dsa_q_a, dsa_q_b) != 0) - return 0; - if (BN_cmp(dsa_g_a, dsa_g_b) != 0) - return 0; - if (BN_cmp(dsa_pub_key_a, dsa_pub_key_b) != 0) - return 0; - return 1; + if ((r = sshbuf_get_bignum2(buf, &p)) != 0 || + (r = sshbuf_get_bignum2(buf, &q)) != 0 || + (r = sshbuf_get_bignum2(buf, &g)) != 0 || + (r = sshbuf_get_bignum2(buf, &pub_key)) != 0) + goto err; + + /* key attribute allocation */ + r = sshkey_init_dsa_params(key, p, q, g); + if (r != 0) goto err; + p = q = g = NULL; /* transferred */ + + r = sshkey_set_dsa_key(key, pub_key, NULL); + if (r != 0) goto err; + pub_key = NULL; /* transferred */ + + r = sshkey_validate_public_dsa(key); + if (r != 0) goto err; + + /* success */ + SSHKEY_DUMP(key); + return 0; + +err: + BN_clear_free(p); + BN_clear_free(q); + BN_clear_free(g); + BN_clear_free(pub_key); + sshkey_clear_pkey(key); + return r; } static int -ssh_dss_serialize_public(const struct sshkey *key, struct sshbuf *b, - enum sshkey_serialize_rep opts) -{ +sshbuf_write_pub_dsa(struct sshbuf *buf, const struct sshkey *key) { int r; - const BIGNUM *dsa_p, *dsa_q, *dsa_g, *dsa_pub_key; + const BIGNUM *p = NULL, *q = NULL, *g = NULL; + const BIGNUM *pub_key = NULL; - if (key->dsa == NULL) + if (key->pk == NULL) return SSH_ERR_INVALID_ARGUMENT; - DSA_get0_pqg(key->dsa, &dsa_p, &dsa_q, &dsa_g); - DSA_get0_key(key->dsa, &dsa_pub_key, NULL); - if (dsa_p == NULL || dsa_q == NULL || - dsa_g == NULL || dsa_pub_key == NULL) - return SSH_ERR_INTERNAL_ERROR; - if ((r = sshbuf_put_bignum2(b, dsa_p)) != 0 || - (r = sshbuf_put_bignum2(b, dsa_q)) != 0 || - (r = sshbuf_put_bignum2(b, dsa_g)) != 0 || - (r = sshbuf_put_bignum2(b, dsa_pub_key)) != 0) + +{ DSA *dsa = EVP_PKEY_get1_DSA(key->pk); + if (dsa == NULL) + return SSH_ERR_INVALID_ARGUMENT; + DSA_get0_pqg(dsa, &p, &q, &g); + DSA_get0_key(dsa, &pub_key, NULL); + DSA_free(dsa); +} + if ((r = sshbuf_put_bignum2(buf, p)) != 0 || + (r = sshbuf_put_bignum2(buf, q)) != 0 || + (r = sshbuf_put_bignum2(buf, g)) != 0 || + (r = sshbuf_put_bignum2(buf, pub_key)) != 0) return r; return 0; } + static int -ssh_dss_serialize_private(const struct sshkey *key, struct sshbuf *b, - enum sshkey_serialize_rep opts) -{ +sshbuf_read_priv_dsa(struct sshbuf *buf, struct sshkey *key) { int r; - const BIGNUM *dsa_priv_key; + BIGNUM *priv_key = NULL; - DSA_get0_key(key->dsa, NULL, &dsa_priv_key); - if (!sshkey_is_cert(key)) { - if ((r = ssh_dss_serialize_public(key, b, opts)) != 0) - return r; - } - if ((r = sshbuf_put_bignum2(b, dsa_priv_key)) != 0) - return r; + if ((r = sshbuf_get_bignum2(buf, &priv_key)) != 0) + goto err; + r = sshkey_set_dsa_key(key, NULL, priv_key); + if (r != 0) goto err; + /* priv_key = NULL; transferred */ + + /* success */ + SSHKEY_DUMP(key); return 0; + +err: + BN_clear_free(priv_key); + return r; } static int -ssh_dss_generate(struct sshkey *k, int bits) -{ - DSA *private; +sshbuf_write_priv_dsa(struct sshbuf *buf, const struct sshkey *key) { + const BIGNUM *priv_key = NULL; - if (bits != 1024) - return SSH_ERR_KEY_LENGTH; - if ((private = DSA_new()) == NULL) - return SSH_ERR_ALLOC_FAIL; - if (!DSA_generate_parameters_ex(private, bits, NULL, 0, NULL, - NULL, NULL) || !DSA_generate_key(private)) { - DSA_free(private); - return SSH_ERR_LIBCRYPTO_ERROR; - } - k->dsa = private; +{ DSA *dsa = EVP_PKEY_get1_DSA(key->pk); + if (dsa == NULL) + return SSH_ERR_INVALID_ARGUMENT; + DSA_get0_key(dsa, NULL, &priv_key); + DSA_free(dsa); +} + return sshbuf_put_bignum2(buf, priv_key); +} + + +extern int /* method used localy only in ssh-keygen.c */ +sshbuf_read_custom_dsa(struct sshbuf *buf, struct sshkey *key); + +int +sshbuf_read_custom_dsa(struct sshbuf *buf, struct sshkey *key) { + int r; + BIGNUM *p = NULL, *q = NULL, *g = NULL; + BIGNUM *pub_key = NULL, *priv_key = NULL; + + if ((r = sshbuf_get_bignum1x(buf, &p)) != 0 || + (r = sshbuf_get_bignum1x(buf, &g)) != 0 || + (r = sshbuf_get_bignum1x(buf, &q)) != 0 || + (r = sshbuf_get_bignum1x(buf, &pub_key)) != 0 || + (r = sshbuf_get_bignum1x(buf, &priv_key)) != 0) + goto err; + + /* key attribute allocation */ + r = sshkey_init_dsa_params(key, p, q, g); + if (r != 0) goto err; + p = q = g = NULL; /* transferred */ + + r = sshkey_set_dsa_key(key, pub_key, priv_key); + if (r != 0) goto err; + pub_key = priv_key = NULL; /* transferred */ + + r = sshkey_validate_public_dsa(key); + if (r != 0) goto err; + + /* success */ + key->type = KEY_DSA; + SSHKEY_DUMP(key); return 0; + +err: + BN_clear_free(p); + BN_clear_free(q); + BN_clear_free(g); + BN_clear_free(pub_key); + BN_clear_free(priv_key); + sshkey_clear_pkey(key); + return r; +} +#endif /* def WITH_OPENSSL_3_1_API */ + + +/* key implementation */ + +static u_int +ssh_dss_size(const struct sshkey *key) +{ + return (key->pk != NULL) ? EVP_PKEY_bits(key->pk) : 0; +} + +static void +ssh_dss_cleanup(struct sshkey *k) +{ + sshkey_clear_pkey(k); +} + +static int +ssh_dss_equal(const struct sshkey *a, const struct sshkey *b) +{ + return sshkey_equal_public_pkey(a, b); +} + +static int +ssh_dss_serialize_public(const struct sshkey *key, struct sshbuf *buf, + enum sshkey_serialize_rep opts) +{ + UNUSED(opts); + return sshbuf_write_pub_dsa(buf, key); } static int -ssh_dss_copy_public(const struct sshkey *from, struct sshkey *to) +ssh_dss_serialize_private(const struct sshkey *key, struct sshbuf *buf, + enum sshkey_serialize_rep opts) { - const BIGNUM *dsa_p, *dsa_q, *dsa_g, *dsa_pub_key; - BIGNUM *dsa_p_dup = NULL, *dsa_q_dup = NULL, *dsa_g_dup = NULL; - BIGNUM *dsa_pub_key_dup = NULL; - int r = SSH_ERR_INTERNAL_ERROR; - - DSA_get0_pqg(from->dsa, &dsa_p, &dsa_q, &dsa_g); - DSA_get0_key(from->dsa, &dsa_pub_key, NULL); - if ((dsa_p_dup = BN_dup(dsa_p)) == NULL || - (dsa_q_dup = BN_dup(dsa_q)) == NULL || - (dsa_g_dup = BN_dup(dsa_g)) == NULL || - (dsa_pub_key_dup = BN_dup(dsa_pub_key)) == NULL) { + int r; + + UNUSED(opts); + if (!sshkey_is_cert(key)) { + if ((r = sshbuf_write_pub_dsa(buf, key)) != 0) + return r; + } + return sshbuf_write_priv_dsa(buf, key); +} + +static int +ssh_dss_generate(struct sshkey *key, int bits) { + EVP_PKEY *pk; + DSA *private = NULL; + int r; + + r = sshdsa_verify_length(bits); + if (r != 0) return r; + + if ((pk = EVP_PKEY_new()) == NULL || + (private = DSA_new()) == NULL + ) { r = SSH_ERR_ALLOC_FAIL; - goto out; + goto err; } - if (!DSA_set0_pqg(to->dsa, dsa_p_dup, dsa_q_dup, dsa_g_dup)) { + + if (!DSA_generate_parameters_ex(private, bits, NULL, 0, NULL, NULL, NULL) || + !DSA_generate_key(private)) { r = SSH_ERR_LIBCRYPTO_ERROR; - goto out; + goto err; } - dsa_p_dup = dsa_q_dup = dsa_g_dup = NULL; /* transferred */ - if (!DSA_set0_key(to->dsa, dsa_pub_key_dup, NULL)) { + + if (!EVP_PKEY_set1_DSA(pk, private)) { r = SSH_ERR_LIBCRYPTO_ERROR; - goto out; + goto err; } - dsa_pub_key_dup = NULL; /* transferred */ - /* success */ - r = 0; - out: - BN_clear_free(dsa_p_dup); - BN_clear_free(dsa_q_dup); - BN_clear_free(dsa_g_dup); - BN_clear_free(dsa_pub_key_dup); + + key->pk = pk; + pk = NULL; + +err: + EVP_PKEY_free(pk); + DSA_free(private); return r; } +static void +ssh_dss_move_public(struct sshkey *from, struct sshkey *to) { + sshkey_move_pk(from, to); +} + static int -ssh_dss_deserialize_public(const char *ktype, struct sshbuf *b, - struct sshkey *key) -{ - int ret = SSH_ERR_INTERNAL_ERROR; - BIGNUM *dsa_p = NULL, *dsa_q = NULL, *dsa_g = NULL, *dsa_pub_key = NULL; +ssh_dss_copy_public(const struct sshkey *from, struct sshkey *to) { + int r; + BIGNUM *p = NULL, *q = NULL, *g = NULL, *pub_key = NULL; - if (sshbuf_get_bignum2(b, &dsa_p) != 0 || - sshbuf_get_bignum2(b, &dsa_q) != 0 || - sshbuf_get_bignum2(b, &dsa_g) != 0 || - sshbuf_get_bignum2(b, &dsa_pub_key) != 0) { - ret = SSH_ERR_INVALID_FORMAT; - goto out; - } - if (!DSA_set0_pqg(key->dsa, dsa_p, dsa_q, dsa_g)) { - ret = SSH_ERR_LIBCRYPTO_ERROR; - goto out; - } - dsa_p = dsa_q = dsa_g = NULL; /* transferred */ - if (!DSA_set0_key(key->dsa, dsa_pub_key, NULL)) { - ret = SSH_ERR_LIBCRYPTO_ERROR; - goto out; +{ DSA *dsa = EVP_PKEY_get1_DSA(from->pk); + const BIGNUM *k_p, *k_q, *k_g, *k_pub_key; + + if (dsa == NULL) + return SSH_ERR_INVALID_ARGUMENT; + DSA_get0_pqg(dsa, &k_p, &k_q, &k_g); + DSA_get0_key(dsa, &k_pub_key, NULL); + DSA_free(dsa); + + if ((p = BN_dup(k_p)) == NULL || + (q = BN_dup(k_q)) == NULL || + (g = BN_dup(k_g)) == NULL || + (pub_key = BN_dup(k_pub_key)) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto err; } - dsa_pub_key = NULL; /* transferred */ -#ifdef DEBUG_PK - DSA_print_fp(stderr, key->dsa, 8); -#endif +} + + r = sshkey_init_dsa_params(to, p, q, g); + if (r != 0) goto err; + p = q = g = NULL; /* transferred */ + + r = sshkey_set_dsa_key(to, pub_key, NULL); + if (r != 0) goto err; + /* pub_key = NULL; transferred */ + /* success */ - ret = 0; - out: - BN_clear_free(dsa_p); - BN_clear_free(dsa_q); - BN_clear_free(dsa_g); - BN_clear_free(dsa_pub_key); - return ret; + return 0; + +err: + BN_clear_free(p); + BN_clear_free(q); + BN_clear_free(g); + BN_clear_free(pub_key); + sshkey_clear_pkey(to); + return r; +} + +static int +ssh_dss_deserialize_public(const char *pkalg, struct sshbuf *buf, + struct sshkey *key) +{ + UNUSED(pkalg); + return sshbuf_read_pub_dsa(buf, key); } static int -ssh_dss_deserialize_private(const char *ktype, struct sshbuf *b, +ssh_dss_deserialize_private(const char *pkalg, struct sshbuf *buf, struct sshkey *key) { int r; - BIGNUM *dsa_priv_key = NULL; + UNUSED(pkalg); if (!sshkey_is_cert(key)) { - if ((r = ssh_dss_deserialize_public(ktype, b, key)) != 0) + if ((r = sshbuf_read_pub_dsa(buf, key))!= 0) return r; } - - if ((r = sshbuf_get_bignum2(b, &dsa_priv_key)) != 0) - return r; - if (!DSA_set0_key(key->dsa, NULL, dsa_priv_key)) { - BN_clear_free(dsa_priv_key); - return SSH_ERR_LIBCRYPTO_ERROR; - } - return 0; + return sshbuf_read_priv_dsa(buf, key); } + static int -ssh_dss_sign(struct sshkey *key, - u_char **sigp, size_t *lenp, - const u_char *data, size_t datalen, - const char *alg, const char *sk_provider, const char *sk_pin, u_int compat) +ssh_dss_sign(const ssh_sign_ctx *ctx, u_char **sigp, size_t *lenp, + const u_char *data, size_t datalen) { - DSA_SIG *sig = NULL; - const BIGNUM *sig_r, *sig_s; - u_char digest[SSH_DIGEST_MAX_LENGTH], sigblob[SIGBLOB_LEN]; - size_t rlen, slen, len, dlen = ssh_digest_bytes(SSH_DIGEST_SHA1); - struct sshbuf *b = NULL; - int ret = SSH_ERR_INVALID_ARGUMENT; + const struct sshkey *key = ctx->key; + const ssh_evp_md *dgst; + u_char sigblob[SIGBLOB_LEN]; + size_t siglen = sizeof(sigblob); + int ret; if (lenp != NULL) *lenp = 0; if (sigp != NULL) *sigp = NULL; - if (key == NULL || key->dsa == NULL || - sshkey_type_plain(key->type) != KEY_DSA) - return SSH_ERR_INVALID_ARGUMENT; - if (dlen == 0) - return SSH_ERR_INTERNAL_ERROR; + ret = sshkey_validate_public_dsa(key); + if (ret != 0) return ret; - if ((ret = ssh_digest_memory(SSH_DIGEST_SHA1, data, datalen, - digest, sizeof(digest))) != 0) - goto out; + dgst = ssh_evp_md_find(SSH_MD_DSA_RAW); - if ((sig = DSA_do_sign(digest, dlen, key->dsa)) == NULL) { + if (ssh_pkey_sign(dgst, key->pk, sigblob, &siglen, data, datalen) <= 0) { ret = SSH_ERR_LIBCRYPTO_ERROR; goto out; } - DSA_SIG_get0(sig, &sig_r, &sig_s); - rlen = BN_num_bytes(sig_r); - slen = BN_num_bytes(sig_s); - if (rlen > INTBLOB_LEN || slen > INTBLOB_LEN) { - ret = SSH_ERR_INTERNAL_ERROR; - goto out; - } - explicit_bzero(sigblob, SIGBLOB_LEN); - BN_bn2bin(sig_r, sigblob + SIGBLOB_LEN - INTBLOB_LEN - rlen); - BN_bn2bin(sig_s, sigblob + SIGBLOB_LEN - slen); - - if ((b = sshbuf_new()) == NULL) { - ret = SSH_ERR_ALLOC_FAIL; - goto out; - } - if ((ret = sshbuf_put_cstring(b, "ssh-dss")) != 0 || - (ret = sshbuf_put_string(b, sigblob, SIGBLOB_LEN)) != 0) - goto out; + ret = ssh_encode_signature(sigp, lenp, + "ssh-dss", sigblob, siglen); - len = sshbuf_len(b); - if (sigp != NULL) { - if ((*sigp = malloc(len)) == NULL) { - ret = SSH_ERR_ALLOC_FAIL; - goto out; - } - memcpy(*sigp, sshbuf_ptr(b), len); - } - if (lenp != NULL) - *lenp = len; - ret = 0; out: - explicit_bzero(digest, sizeof(digest)); - DSA_SIG_free(sig); - sshbuf_free(b); return ret; } + static int -ssh_dss_verify(const struct sshkey *key, +ssh_dss_verify(const ssh_verify_ctx *ctx, const u_char *sig, size_t siglen, - const u_char *data, size_t dlen, const char *alg, u_int compat, - struct sshkey_sig_details **detailsp) + const u_char *data, size_t datalen) { - DSA_SIG *dsig = NULL; - BIGNUM *sig_r = NULL, *sig_s = NULL; - u_char digest[SSH_DIGEST_MAX_LENGTH], *sigblob = NULL; - size_t len, hlen = ssh_digest_bytes(SSH_DIGEST_SHA1); + const struct sshkey *key = ctx->key; + const ssh_evp_md *dgst; + u_char *sigblob = NULL; + size_t len; int ret = SSH_ERR_INTERNAL_ERROR; struct sshbuf *b = NULL; char *ktype = NULL; - if (key == NULL || key->dsa == NULL || - sshkey_type_plain(key->type) != KEY_DSA || - sig == NULL || siglen == 0) + if (sig == NULL || siglen == 0) return SSH_ERR_INVALID_ARGUMENT; - if (hlen == 0) - return SSH_ERR_INTERNAL_ERROR; + + dgst = ssh_evp_md_find(SSH_MD_DSA_RAW); + if (dgst == NULL) return SSH_ERR_INTERNAL_ERROR; + + ret = sshkey_validate_public_dsa(key); + if (ret != 0) return ret; /* fetch signature */ if ((b = sshbuf_from(sig, siglen)) == NULL) @@ -362,52 +658,17 @@ ret = SSH_ERR_UNEXPECTED_TRAILING_DATA; goto out; } - if (len != SIGBLOB_LEN) { ret = SSH_ERR_INVALID_FORMAT; goto out; } - /* parse signature */ - if ((dsig = DSA_SIG_new()) == NULL || - (sig_r = BN_new()) == NULL || - (sig_s = BN_new()) == NULL) { - ret = SSH_ERR_ALLOC_FAIL; - goto out; - } - if ((BN_bin2bn(sigblob, INTBLOB_LEN, sig_r) == NULL) || - (BN_bin2bn(sigblob + INTBLOB_LEN, INTBLOB_LEN, sig_s) == NULL)) { - ret = SSH_ERR_LIBCRYPTO_ERROR; - goto out; - } - if (!DSA_SIG_set0(dsig, sig_r, sig_s)) { - ret = SSH_ERR_LIBCRYPTO_ERROR; - goto out; - } - sig_r = sig_s = NULL; /* transferred */ - - /* sha1 the data */ - if ((ret = ssh_digest_memory(SSH_DIGEST_SHA1, data, dlen, - digest, sizeof(digest))) != 0) - goto out; - - switch (DSA_do_verify(digest, hlen, dsig, key->dsa)) { - case 1: - ret = 0; - break; - case 0: + if (ssh_pkey_verify(dgst, key->pk, + sigblob, len, data, datalen) <= 0) { ret = SSH_ERR_SIGNATURE_INVALID; - goto out; - default: - ret = SSH_ERR_LIBCRYPTO_ERROR; - goto out; } out: - explicit_bzero(digest, sizeof(digest)); - DSA_SIG_free(dsig); - BN_clear_free(sig_r); - BN_clear_free(sig_s); sshbuf_free(b); free(ktype); if (sigblob != NULL) @@ -417,17 +678,18 @@ static const struct sshkey_impl_funcs sshkey_dss_funcs = { /* .size = */ ssh_dss_size, - /* .alloc = */ ssh_dss_alloc, + /* .alloc = NULL, */ /* .cleanup = */ ssh_dss_cleanup, /* .equal = */ ssh_dss_equal, - /* .ssh_serialize_public = */ ssh_dss_serialize_public, - /* .ssh_deserialize_public = */ ssh_dss_deserialize_public, - /* .ssh_serialize_private = */ ssh_dss_serialize_private, - /* .ssh_deserialize_private = */ ssh_dss_deserialize_private, + /* .serialize_public = */ ssh_dss_serialize_public, + /* .deserialize_public = */ ssh_dss_deserialize_public, + /* .serialize_private = */ ssh_dss_serialize_private, + /* .deserialize_private = */ ssh_dss_deserialize_private, /* .generate = */ ssh_dss_generate, + /* .move_public = */ ssh_dss_move_public, /* .copy_public = */ ssh_dss_copy_public, /* .sign = */ ssh_dss_sign, - /* .verify = */ ssh_dss_verify, + /* .verify = */ ssh_dss_verify }; const struct sshkey_impl sshkey_dss_impl = { @@ -439,7 +701,7 @@ /* .cert = */ 0, /* .sigonly = */ 0, /* .keybits = */ 0, - /* .funcs = */ &sshkey_dss_funcs, + /* .funcs = */ &sshkey_dss_funcs }; const struct sshkey_impl sshkey_dsa_cert_impl = { @@ -451,6 +713,10 @@ /* .cert = */ 1, /* .sigonly = */ 0, /* .keybits = */ 0, - /* .funcs = */ &sshkey_dss_funcs, + /* .funcs = */ &sshkey_dss_funcs }; +#else + +typedef int ssh_dss_empty_translation_unit; + #endif /* WITH_OPENSSL */ diff -ruN openssh-9.4p1/ssh-ecdsa.c openssh-9.4p1+x509-14.2.1/ssh-ecdsa.c --- openssh-9.4p1/ssh-ecdsa.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/ssh-ecdsa.c 2023-08-20 10:07:01.000000000 +0300 @@ -1,7 +1,8 @@ -/* $OpenBSD: ssh-ecdsa.c,v 1.26 2023/03/08 04:43:12 guenther Exp $ */ +/* $OpenBSD: ssh-ecdsa.c,v 1.25 2022/10/28 00:44:44 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * Copyright (c) 2010 Damien Miller. All rights reserved. + * Copyright (c) 2020-2023 Roumen Petrov. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -24,292 +25,636 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifndef USE_OPENSSL_PROVIDER +/* TODO: implement OpenSSL 4.0 API, as OpenSSL 3.* is quite nonfunctional */ +# define OPENSSL_SUPPRESS_DEPRECATED +#endif + +#define SSHKEY_INTERNAL #include "includes.h" #if defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC) #include +#include "evp-compat.h" #include -#include -#include -#include #include +#include "sshxkey.h" #include "sshbuf.h" #include "ssherr.h" -#include "digest.h" -#define SSHKEY_INTERNAL -#include "sshkey.h" +#include "log.h" +#include "xmalloc.h" -#include "openbsd-compat/openssl-compat.h" -static u_int -ssh_ecdsa_size(const struct sshkey *key) +#ifndef HAVE_EC_POINT_GET_AFFINE_COORDINATES /* OpenSSL < 1.1.1 */ +#ifdef OPENSSL_HAS_ECC +/* Functions are available even in 0.9.7* but EC is not activated + * as NIST curves are not supported yet. + */ +static inline int +EC_POINT_get_affine_coordinates( + const EC_GROUP *group, const EC_POINT *p, + BIGNUM *x, BIGNUM *y, BN_CTX *ctx +) { + return EC_POINT_get_affine_coordinates_GFp(group, p, x, y, ctx); +} +#endif /*def OPENSSL_HAS_ECC*/ +#endif /*ndef HAVE_EC_POINT_GET_AFFINE_COORDINATES*/ + + +#ifndef HAVE_EC_GROUP_GET_FIELD_TYPE /* OpenSSL < 3.0.0 */ +static inline int +EC_GROUP_get_field_type(const EC_GROUP *group) { + return EC_METHOD_get_field_type(EC_GROUP_method_of(group)); +} +#endif /*ndef HAVE_EC_GROUP_GET_FIELD_TYPE*/ + + +#ifdef DEBUG_KEXECDH +static void +dump_ec_point(const EC_GROUP *g, const EC_POINT *p) +{ + BIGNUM *x, *y = NULL; + + if (p == NULL) { + fputs("point=(NULL)\n", stderr); + return; + } + if (EC_GROUP_get_field_type(g) != NID_X9_62_prime_field) { + fprintf(stderr, "%s: group is not a prime field\n", __func__); + return; + } + + x = BN_new(); + y = BN_new(); + if (x == NULL || y == NULL) { + fprintf(stderr, "%s: BN_new failed\n", __func__); + goto err; + } + if (EC_POINT_get_affine_coordinates(g, p, x, y, NULL) != 1) { + fprintf(stderr, "%s: EC_POINT_get_affine_coordinates\n", __func__); + goto err; + } + + fputs("x=", stderr); + BN_print_fp(stderr, x); + fputs("\n", stderr); + + fputs("y=", stderr); + BN_print_fp(stderr, y); + fputs("\n", stderr); + +err: + BN_clear_free(x); + BN_clear_free(y); +} +#endif + + +static const ssh_evp_md* +ssh_ecdsa_dgst(const struct sshkey *key) { + int id; + switch (key->ecdsa_nid) { - case NID_X9_62_prime256v1: - return 256; - case NID_secp384r1: - return 384; + case NID_X9_62_prime256v1: id = SSH_MD_EC_SHA256_SSH; break; + case NID_secp384r1: id = SSH_MD_EC_SHA384_SSH; break; #ifdef OPENSSL_HAS_NISTP521 - case NID_secp521r1: - return 521; -#endif + case NID_secp521r1: id = SSH_MD_EC_SHA512_SSH; break; +#endif /* OPENSSL_HAS_NISTP521 */ default: - return 0; + return NULL; + } + return ssh_evp_md_find(id); +} + + +#ifdef WITH_OPENSSL_4_0_API +/* TODO: new methods compatible with OpenSSL 4.0 API. + * Remark: OpenSSL 3* is too buggy - almost each release fail + * or crash in regression tests. + */ +#else +/* management of elementary EC key */ + +static inline EC_KEY* +ssh_EC_KEY_new_by_curve_name(int nid) { + EC_KEY *ec; + + ec = EC_KEY_new_by_curve_name(nid); + if (ec == NULL) return NULL; + +#if defined(OPENSSL_VERSION_NUMBER) && (OPENSSL_VERSION_NUMBER < 0x10100000L) || \ + defined(LIBRESSL_VERSION_NUMBER) + /* Note since 1.1.0 OpenSSL uses named curve parameter encoding by default. + * It seems to me default is changed in upcomming 3.0 but key is marked + * properly when created by nid. + */ + EC_KEY_set_asn1_flag(ec, OPENSSL_EC_NAMED_CURVE); +#endif + return ec; +} + +static int +sshkey_init_ecdsa_curve(struct sshkey *key, int nid) { + int r; + EVP_PKEY *pk; + EC_KEY *ec; + + pk = EVP_PKEY_new(); + if (pk == NULL) + return SSH_ERR_ALLOC_FAIL; + + ec = ssh_EC_KEY_new_by_curve_name(nid); + if (ec == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto err; + } + + if (!EVP_PKEY_set1_EC_KEY(pk, ec)) { + r = SSH_ERR_LIBCRYPTO_ERROR; + goto err; + } + + /* success */ + key->pk = pk; + pk = NULL; + key->ecdsa_nid = nid; + r = 0; + +err: + EC_KEY_free(ec); + EVP_PKEY_free(pk); + return r; +} + +static int +sshbuf_read_ec_curve(struct sshbuf *buf, const char *pkalg, struct sshkey *key) { + int r, nid; + + nid = sshkey_ecdsa_nid_from_name(pkalg); + debug3_f("pkalg/nid: %s/%d", pkalg, nid); + if (nid == -1) + return SSH_ERR_INVALID_ARGUMENT; + +{ char *curve; + + r = sshbuf_get_cstring(buf, &curve, NULL); + if (r != 0) return r; + + if (nid != sshkey_curve_name_to_nid(curve)) + r = SSH_ERR_EC_CURVE_MISMATCH; + + free(curve); +} + if (r == 0) + key->ecdsa_nid = nid; + return r; +} + +static inline int +sshbuf_write_ec_curve(struct sshbuf *buf, const struct sshkey *key) { + const char *curve_name = sshkey_curve_nid_to_name(key->ecdsa_nid); + return sshbuf_put_cstring(buf, curve_name); +} + + +int +sshkey_ec_validate_public(const EC_GROUP *group, const EC_POINT *public) +{ + EC_POINT *nq = NULL; + BIGNUM *order = NULL, *x = NULL, *y = NULL, *tmp = NULL; + int ret = SSH_ERR_KEY_INVALID_EC_VALUE; + + /* + * NB. This assumes OpenSSL has already verified that the public + * point lies on the curve. This is done by EC_POINT_oct2point() + * implicitly calling EC_POINT_is_on_curve(). If this code is ever + * reachable with public points not unmarshalled using + * EC_POINT_oct2point then the caller will need to explicitly check. + */ +#ifdef DEBUG_KEXECDH + fputs("public key:\n", stderr); + dump_ec_point(group, public); +#endif + + /* + * We shouldn't ever hit this case because bignum_get_ecpoint() + * refuses to load GF2m points. + */ + if (EC_GROUP_get_field_type(group) != + NID_X9_62_prime_field) + goto out; + + /* Q != infinity */ + if (EC_POINT_is_at_infinity(group, public)) + goto out; + + if ((x = BN_new()) == NULL || + (y = BN_new()) == NULL || + (order = BN_new()) == NULL || + (tmp = BN_new()) == NULL) { + ret = SSH_ERR_ALLOC_FAIL; + goto out; + } + + /* log2(x) > log2(order)/2, log2(y) > log2(order)/2 */ + if (EC_GROUP_get_order(group, order, NULL) != 1 || + EC_POINT_get_affine_coordinates(group, public, + x, y, NULL) != 1) { + ret = SSH_ERR_LIBCRYPTO_ERROR; + goto out; + } + if (BN_num_bits(x) <= BN_num_bits(order) / 2 || + BN_num_bits(y) <= BN_num_bits(order) / 2) + goto out; + + /* nQ == infinity (n == order of subgroup) */ + if ((nq = EC_POINT_new(group)) == NULL) { + ret = SSH_ERR_ALLOC_FAIL; + goto out; + } + if (EC_POINT_mul(group, nq, NULL, public, order, NULL) != 1) { + ret = SSH_ERR_LIBCRYPTO_ERROR; + goto out; } + if (EC_POINT_is_at_infinity(group, nq) != 1) + goto out; + + /* x < order - 1, y < order - 1 */ + if (!BN_sub(tmp, order, BN_value_one())) { + ret = SSH_ERR_LIBCRYPTO_ERROR; + goto out; + } + if (BN_cmp(x, tmp) >= 0 || BN_cmp(y, tmp) >= 0) + goto out; + ret = 0; + out: + BN_clear_free(x); + BN_clear_free(y); + BN_clear_free(order); + BN_clear_free(tmp); + EC_POINT_free(nq); + return ret; +} + + +static int +sshkey_validate_ec_pub(const EC_KEY *ec) { + int r; + + r = sshkey_ec_validate_public(EC_KEY_get0_group(ec), + EC_KEY_get0_public_key(ec)); + if (r != 0) return r; + + /* other checks ? */ + return 0; +} + +int +sshkey_validate_public_ecdsa(const struct sshkey *key) { + int r; + + if (key == NULL) return SSH_ERR_INVALID_ARGUMENT; + +{ EC_KEY *ec = EVP_PKEY_get1_EC_KEY(key->pk); + if (ec == NULL) + return SSH_ERR_INVALID_ARGUMENT; + r = sshkey_validate_ec_pub(ec); + EC_KEY_free(ec); +} + return r; +} + + +extern int /* see sshkey-crypto.c */ +ssh_EVP_PKEY_complete_pub_ecdsa(EVP_PKEY *pk); + +int +ssh_EVP_PKEY_complete_pub_ecdsa(EVP_PKEY *pk) { + int r, nid; + EC_KEY *ec; + + ec = EVP_PKEY_get1_EC_KEY(pk); + if (ec == NULL) + return SSH_ERR_INVALID_ARGUMENT; + + nid = ssh_EC_KEY_preserve_nid(ec); + if (nid < 0) { + error_f("unsupported elliptic curve"); + r = SSH_ERR_EC_CURVE_INVALID; + goto err; + } + + r = sshkey_validate_ec_pub(ec); + +err: + EC_KEY_free(ec); + return r; +} + + +extern int /* TODO static - see sshkey-crypto.c */ +sshkey_validate_ec_priv(const EC_KEY *ec); + + +static int +sshbuf_read_pub_ecdsa(struct sshbuf *buf, struct sshkey *key) { + int r; + EC_KEY *ec; + + r = sshkey_init_ecdsa_curve(key, key->ecdsa_nid); + if (r != 0) return r; + + ec = EVP_PKEY_get1_EC_KEY(key->pk); + if (ec == NULL) + return SSH_ERR_LIBCRYPTO_ERROR; + + r = sshbuf_get_eckey(buf, ec); + if (r != 0) goto err; + + r = sshkey_validate_ec_pub(ec); + if (r != 0) goto err; + + /* success */ + SSHKEY_DUMP(key); + +err: + EC_KEY_free(ec); + return r; +} + +static int +sshbuf_write_pub_ecdsa(struct sshbuf *buf, const struct sshkey *key) { + int r; + EC_KEY *ec; + + if (key->pk == NULL) + return SSH_ERR_INVALID_ARGUMENT; + + ec = EVP_PKEY_get1_EC_KEY(key->pk); + if (ec == NULL) + return SSH_ERR_INVALID_ARGUMENT; + + r = sshbuf_put_eckey(buf, ec); + + EC_KEY_free(ec); + return r; +} + + +static int +sshbuf_read_priv_ecdsa(struct sshbuf *buf, struct sshkey *key) { + int r; + EC_KEY *ec = NULL; + BIGNUM *exponent = NULL; + + if ((r = sshbuf_get_bignum2(buf, &exponent)) != 0) + goto err; + + ec = EVP_PKEY_get1_EC_KEY(key->pk); + if (ec == NULL) { + r = SSH_ERR_INVALID_ARGUMENT; + goto err; + } + + if (EC_KEY_set_private_key(ec, exponent) != 1) { + r = SSH_ERR_LIBCRYPTO_ERROR; + goto err; + } + /*no! exponent = NULL; transferred */ + + r = sshkey_validate_ec_priv(ec); + if (r != 0) goto err; + + SSHKEY_DUMP(key); + +err: + BN_clear_free(exponent); + EC_KEY_free(ec); + return r; +} + +static int +sshbuf_write_priv_ecdsa(struct sshbuf *buf, const struct sshkey *key) { + const BIGNUM *exponent = NULL; + +{ EC_KEY *ec = EVP_PKEY_get1_EC_KEY(key->pk); + if (ec == NULL) + return SSH_ERR_INVALID_ARGUMENT; + exponent = EC_KEY_get0_private_key(ec); + EC_KEY_free(ec); +} + return sshbuf_put_bignum2(buf, exponent); +} +#endif /* def WITH_OPENSSL_3_1_API */ + + +/* key implementation */ + +static u_int +ssh_ecdsa_size(const struct sshkey *key) +{ + return (key->pk != NULL) ? EVP_PKEY_bits(key->pk) : 0; } static void ssh_ecdsa_cleanup(struct sshkey *k) { - EC_KEY_free(k->ecdsa); - k->ecdsa = NULL; + sshkey_clear_pkey(k); } static int ssh_ecdsa_equal(const struct sshkey *a, const struct sshkey *b) { - const EC_GROUP *grp_a, *grp_b; - const EC_POINT *pub_a, *pub_b; - - if (a->ecdsa == NULL || b->ecdsa == NULL) - return 0; - if ((grp_a = EC_KEY_get0_group(a->ecdsa)) == NULL || - (grp_b = EC_KEY_get0_group(b->ecdsa)) == NULL) - return 0; - if ((pub_a = EC_KEY_get0_public_key(a->ecdsa)) == NULL || - (pub_b = EC_KEY_get0_public_key(b->ecdsa)) == NULL) - return 0; - if (EC_GROUP_cmp(grp_a, grp_b, NULL) != 0) - return 0; - if (EC_POINT_cmp(grp_a, pub_a, pub_b, NULL) != 0) - return 0; - - return 1; + return sshkey_equal_public_pkey(a, b); } static int -ssh_ecdsa_serialize_public(const struct sshkey *key, struct sshbuf *b, +ssh_ecdsa_serialize_public(const struct sshkey *key, struct sshbuf *buf, enum sshkey_serialize_rep opts) { int r; - if (key->ecdsa == NULL) - return SSH_ERR_INVALID_ARGUMENT; - if ((r = sshbuf_put_cstring(b, - sshkey_curve_nid_to_name(key->ecdsa_nid))) != 0 || - (r = sshbuf_put_eckey(b, key->ecdsa)) != 0) + UNUSED(opts); + if ((r = sshbuf_write_ec_curve(buf, key)) != 0) return r; - - return 0; + return sshbuf_write_pub_ecdsa(buf, key); } static int -ssh_ecdsa_serialize_private(const struct sshkey *key, struct sshbuf *b, +ssh_ecdsa_serialize_private(const struct sshkey *key, struct sshbuf *buf, enum sshkey_serialize_rep opts) { int r; + UNUSED(opts); if (!sshkey_is_cert(key)) { - if ((r = ssh_ecdsa_serialize_public(key, b, opts)) != 0) + if ((r = sshbuf_write_ec_curve(buf, key)) != 0 || + (r = sshbuf_write_pub_ecdsa(buf, key)) != 0) return r; } - if ((r = sshbuf_put_bignum2(b, - EC_KEY_get0_private_key(key->ecdsa))) != 0) - return r; - return 0; + return sshbuf_write_priv_ecdsa(buf, key); } static int -ssh_ecdsa_generate(struct sshkey *k, int bits) -{ - EC_KEY *private; +ssh_ecdsa_generate(struct sshkey *key, int bits) { + EVP_PKEY *pk; + EC_KEY *private = NULL; + int r = 0, nid; + + nid = sshkey_ecdsa_bits_to_nid(bits); + if (nid == -1) return SSH_ERR_KEY_LENGTH; + + if ((pk = EVP_PKEY_new()) == NULL || + (private = ssh_EC_KEY_new_by_curve_name(nid)) == NULL + ) { + r = SSH_ERR_ALLOC_FAIL; + goto err; + } - if ((k->ecdsa_nid = sshkey_ecdsa_bits_to_nid(bits)) == -1) - return SSH_ERR_KEY_LENGTH; - if ((private = EC_KEY_new_by_curve_name(k->ecdsa_nid)) == NULL) - return SSH_ERR_ALLOC_FAIL; if (EC_KEY_generate_key(private) != 1) { - EC_KEY_free(private); - return SSH_ERR_LIBCRYPTO_ERROR; + r = SSH_ERR_LIBCRYPTO_ERROR; + goto err; } - EC_KEY_set_asn1_flag(private, OPENSSL_EC_NAMED_CURVE); - k->ecdsa = private; - return 0; + + if (!EVP_PKEY_set1_EC_KEY(pk, private)) { + r = SSH_ERR_LIBCRYPTO_ERROR; + goto err; + } + + key->pk = pk; + pk = NULL; + key->ecdsa_nid = nid; + +err: + EVP_PKEY_free(pk); + EC_KEY_free(private); + return r; } -static int -ssh_ecdsa_copy_public(const struct sshkey *from, struct sshkey *to) -{ +static void +ssh_ecdsa_move_public(struct sshkey *from, struct sshkey *to) { + sshkey_move_pk(from, to); to->ecdsa_nid = from->ecdsa_nid; - if ((to->ecdsa = EC_KEY_new_by_curve_name(from->ecdsa_nid)) == NULL) - return SSH_ERR_ALLOC_FAIL; - if (EC_KEY_set_public_key(to->ecdsa, - EC_KEY_get0_public_key(from->ecdsa)) != 1) - return SSH_ERR_LIBCRYPTO_ERROR; /* caller will free k->ecdsa */ - return 0; + from->ecdsa_nid = -1; } +extern int sshkey_copy_pub_ecdsa(const struct sshkey *from, struct sshkey *to); + static int -ssh_ecdsa_deserialize_public(const char *ktype, struct sshbuf *b, - struct sshkey *key) -{ +ssh_ecdsa_copy_public(const struct sshkey *from, struct sshkey *to) { int r; - char *curve = NULL; + EC_KEY *ec, *from_ec = NULL; - if ((key->ecdsa_nid = sshkey_ecdsa_nid_from_name(ktype)) == -1) - return SSH_ERR_INVALID_ARGUMENT; - if ((r = sshbuf_get_cstring(b, &curve, NULL)) != 0) - goto out; - if (key->ecdsa_nid != sshkey_curve_name_to_nid(curve)) { - r = SSH_ERR_EC_CURVE_MISMATCH; - goto out; - } - EC_KEY_free(key->ecdsa); - key->ecdsa = NULL; - if ((key->ecdsa = EC_KEY_new_by_curve_name(key->ecdsa_nid)) == NULL) { + r = sshkey_init_ecdsa_curve(to, from->ecdsa_nid); + if (r != 0) return r; + + ec = EVP_PKEY_get1_EC_KEY(to->pk); + if (ec == NULL) { r = SSH_ERR_LIBCRYPTO_ERROR; - goto out; + goto err; } - if ((r = sshbuf_get_eckey(b, key->ecdsa)) != 0) - goto out; - if (sshkey_ec_validate_public(EC_KEY_get0_group(key->ecdsa), - EC_KEY_get0_public_key(key->ecdsa)) != 0) { - r = SSH_ERR_KEY_INVALID_EC_VALUE; - goto out; - } - /* success */ - r = 0; -#ifdef DEBUG_PK - sshkey_dump_ec_point(EC_KEY_get0_group(key->ecdsa), - EC_KEY_get0_public_key(key->ecdsa)); -#endif - out: - free(curve); - if (r != 0) { - EC_KEY_free(key->ecdsa); - key->ecdsa = NULL; + + from_ec = EVP_PKEY_get1_EC_KEY(from->pk); + if (from_ec == NULL) { + r = SSH_ERR_LIBCRYPTO_ERROR; + goto err; } + + if (EC_KEY_set_public_key(ec, EC_KEY_get0_public_key(from_ec)) != 1) + r = SSH_ERR_LIBCRYPTO_ERROR; + +err: + EC_KEY_free(from_ec); + EC_KEY_free(ec); return r; } static int -ssh_ecdsa_deserialize_private(const char *ktype, struct sshbuf *b, +ssh_ecdsa_deserialize_public(const char *pkalg, struct sshbuf *buf, + struct sshkey *key) +{ + int r; + + if ((r = sshbuf_read_ec_curve(buf, pkalg, key)) != 0) + return r; + return sshbuf_read_pub_ecdsa(buf, key); +} + +static int +ssh_ecdsa_deserialize_private(const char *pkalg, struct sshbuf *buf, struct sshkey *key) { int r; - BIGNUM *exponent = NULL; if (!sshkey_is_cert(key)) { - if ((r = ssh_ecdsa_deserialize_public(ktype, b, key)) != 0) + if ((r = sshbuf_read_ec_curve(buf, pkalg, key)) != 0 || + (r = sshbuf_read_pub_ecdsa(buf, key)) != 0) return r; } - if ((r = sshbuf_get_bignum2(b, &exponent)) != 0) - goto out; - if (EC_KEY_set_private_key(key->ecdsa, exponent) != 1) { - r = SSH_ERR_LIBCRYPTO_ERROR; - goto out; - } - if ((r = sshkey_ec_validate_private(key->ecdsa)) != 0) - goto out; - /* success */ - r = 0; - out: - BN_clear_free(exponent); - return r; + return sshbuf_read_priv_ecdsa(buf, key); } static int -ssh_ecdsa_sign(struct sshkey *key, - u_char **sigp, size_t *lenp, - const u_char *data, size_t dlen, - const char *alg, const char *sk_provider, const char *sk_pin, u_int compat) -{ - ECDSA_SIG *esig = NULL; - const BIGNUM *sig_r, *sig_s; - int hash_alg; - u_char digest[SSH_DIGEST_MAX_LENGTH]; - size_t len, hlen; - struct sshbuf *b = NULL, *bb = NULL; - int ret = SSH_ERR_INTERNAL_ERROR; +ssh_ecdsa_sign(const ssh_sign_ctx *ctx, u_char **sigp, size_t *lenp, + const u_char *data, size_t datalen) +{ + const struct sshkey *key = ctx->key; + const ssh_evp_md *dgst; + u_char sigblob[20+2*64/*SHA512_DIGEST_LENGTH*/]; + size_t siglen = sizeof(sigblob); + int ret; if (lenp != NULL) *lenp = 0; if (sigp != NULL) *sigp = NULL; - if (key == NULL || key->ecdsa == NULL || - sshkey_type_plain(key->type) != KEY_ECDSA) - return SSH_ERR_INVALID_ARGUMENT; + dgst = ssh_ecdsa_dgst(key); + if (dgst == NULL) return SSH_ERR_INTERNAL_ERROR; - if ((hash_alg = sshkey_ec_nid_to_hash_alg(key->ecdsa_nid)) == -1 || - (hlen = ssh_digest_bytes(hash_alg)) == 0) - return SSH_ERR_INTERNAL_ERROR; - if ((ret = ssh_digest_memory(hash_alg, data, dlen, - digest, sizeof(digest))) != 0) - goto out; + ret = sshkey_validate_public_ecdsa(key); + if (ret != 0) return ret; - if ((esig = ECDSA_do_sign(digest, hlen, key->ecdsa)) == NULL) { + if (ssh_pkey_sign(dgst, key->pk, sigblob, &siglen, data, datalen) <= 0) { ret = SSH_ERR_LIBCRYPTO_ERROR; goto out; } - if ((bb = sshbuf_new()) == NULL || (b = sshbuf_new()) == NULL) { - ret = SSH_ERR_ALLOC_FAIL; - goto out; - } - ECDSA_SIG_get0(esig, &sig_r, &sig_s); - if ((ret = sshbuf_put_bignum2(bb, sig_r)) != 0 || - (ret = sshbuf_put_bignum2(bb, sig_s)) != 0) - goto out; - if ((ret = sshbuf_put_cstring(b, sshkey_ssh_name_plain(key))) != 0 || - (ret = sshbuf_put_stringb(b, bb)) != 0) - goto out; - len = sshbuf_len(b); - if (sigp != NULL) { - if ((*sigp = malloc(len)) == NULL) { - ret = SSH_ERR_ALLOC_FAIL; - goto out; - } - memcpy(*sigp, sshbuf_ptr(b), len); - } - if (lenp != NULL) - *lenp = len; - ret = 0; + ret = ssh_encode_signature(sigp, lenp, + sshkey_ssh_name_plain(key), sigblob, siglen); + out: - explicit_bzero(digest, sizeof(digest)); - sshbuf_free(b); - sshbuf_free(bb); - ECDSA_SIG_free(esig); return ret; } static int -ssh_ecdsa_verify(const struct sshkey *key, +ssh_ecdsa_verify(const ssh_verify_ctx *ctx, const u_char *sig, size_t siglen, - const u_char *data, size_t dlen, const char *alg, u_int compat, - struct sshkey_sig_details **detailsp) + const u_char *data, size_t datalen) { - ECDSA_SIG *esig = NULL; - BIGNUM *sig_r = NULL, *sig_s = NULL; - int hash_alg; - u_char digest[SSH_DIGEST_MAX_LENGTH]; - size_t hlen; - int ret = SSH_ERR_INTERNAL_ERROR; + const struct sshkey *key = ctx->key; + const ssh_evp_md *dgst; struct sshbuf *b = NULL, *sigbuf = NULL; char *ktype = NULL; + int ret; - if (key == NULL || key->ecdsa == NULL || - sshkey_type_plain(key->type) != KEY_ECDSA || - sig == NULL || siglen == 0) + if (sig == NULL || siglen == 0) return SSH_ERR_INVALID_ARGUMENT; - if ((hash_alg = sshkey_ec_nid_to_hash_alg(key->ecdsa_nid)) == -1 || - (hlen = ssh_digest_bytes(hash_alg)) == 0) - return SSH_ERR_INTERNAL_ERROR; + dgst = ssh_ecdsa_dgst(key); + if (dgst == NULL) return SSH_ERR_INTERNAL_ERROR; + + ret = sshkey_validate_public_ecdsa(key); + if (ret != 0) return ret; /* fetch signature */ if ((b = sshbuf_from(sig, siglen)) == NULL) @@ -328,67 +673,33 @@ goto out; } - /* parse signature */ - if (sshbuf_get_bignum2(sigbuf, &sig_r) != 0 || - sshbuf_get_bignum2(sigbuf, &sig_s) != 0) { - ret = SSH_ERR_INVALID_FORMAT; - goto out; - } - if ((esig = ECDSA_SIG_new()) == NULL) { - ret = SSH_ERR_ALLOC_FAIL; - goto out; - } - if (!ECDSA_SIG_set0(esig, sig_r, sig_s)) { - ret = SSH_ERR_LIBCRYPTO_ERROR; - goto out; - } - sig_r = sig_s = NULL; /* transferred */ - - if (sshbuf_len(sigbuf) != 0) { - ret = SSH_ERR_UNEXPECTED_TRAILING_DATA; - goto out; - } - if ((ret = ssh_digest_memory(hash_alg, data, dlen, - digest, sizeof(digest))) != 0) - goto out; - - switch (ECDSA_do_verify(digest, hlen, esig, key->ecdsa)) { - case 1: - ret = 0; - break; - case 0: +{ size_t len = sshbuf_len(sigbuf); + if (ssh_pkey_verify(dgst, key->pk, + sshbuf_ptr(sigbuf), len, data, datalen) <= 0) ret = SSH_ERR_SIGNATURE_INVALID; - goto out; - default: - ret = SSH_ERR_LIBCRYPTO_ERROR; - goto out; - } +} out: - explicit_bzero(digest, sizeof(digest)); sshbuf_free(sigbuf); sshbuf_free(b); - ECDSA_SIG_free(esig); - BN_clear_free(sig_r); - BN_clear_free(sig_s); free(ktype); return ret; } -/* NB. not static; used by ECDSA-SK */ -const struct sshkey_impl_funcs sshkey_ecdsa_funcs = { +static const struct sshkey_impl_funcs sshkey_ecdsa_funcs = { /* .size = */ ssh_ecdsa_size, - /* .alloc = */ NULL, + /* .alloc = NULL, */ /* .cleanup = */ ssh_ecdsa_cleanup, /* .equal = */ ssh_ecdsa_equal, - /* .ssh_serialize_public = */ ssh_ecdsa_serialize_public, - /* .ssh_deserialize_public = */ ssh_ecdsa_deserialize_public, - /* .ssh_serialize_private = */ ssh_ecdsa_serialize_private, - /* .ssh_deserialize_private = */ ssh_ecdsa_deserialize_private, + /* .serialize_public = */ ssh_ecdsa_serialize_public, + /* .deserialize_public = */ ssh_ecdsa_deserialize_public, + /* .serialize_private = */ ssh_ecdsa_serialize_private, + /* .deserialize_private = */ ssh_ecdsa_deserialize_private, /* .generate = */ ssh_ecdsa_generate, + /* .move_public = */ ssh_ecdsa_move_public, /* .copy_public = */ ssh_ecdsa_copy_public, /* .sign = */ ssh_ecdsa_sign, - /* .verify = */ ssh_ecdsa_verify, + /* .verify = */ ssh_ecdsa_verify }; const struct sshkey_impl sshkey_ecdsa_nistp256_impl = { @@ -400,7 +711,7 @@ /* .cert = */ 0, /* .sigonly = */ 0, /* .keybits = */ 0, - /* .funcs = */ &sshkey_ecdsa_funcs, + /* .funcs = */ &sshkey_ecdsa_funcs }; const struct sshkey_impl sshkey_ecdsa_nistp256_cert_impl = { @@ -412,7 +723,7 @@ /* .cert = */ 1, /* .sigonly = */ 0, /* .keybits = */ 0, - /* .funcs = */ &sshkey_ecdsa_funcs, + /* .funcs = */ &sshkey_ecdsa_funcs }; const struct sshkey_impl sshkey_ecdsa_nistp384_impl = { @@ -424,7 +735,7 @@ /* .cert = */ 0, /* .sigonly = */ 0, /* .keybits = */ 0, - /* .funcs = */ &sshkey_ecdsa_funcs, + /* .funcs = */ &sshkey_ecdsa_funcs }; const struct sshkey_impl sshkey_ecdsa_nistp384_cert_impl = { @@ -436,7 +747,7 @@ /* .cert = */ 1, /* .sigonly = */ 0, /* .keybits = */ 0, - /* .funcs = */ &sshkey_ecdsa_funcs, + /* .funcs = */ &sshkey_ecdsa_funcs }; #ifdef OPENSSL_HAS_NISTP521 @@ -449,7 +760,7 @@ /* .cert = */ 0, /* .sigonly = */ 0, /* .keybits = */ 0, - /* .funcs = */ &sshkey_ecdsa_funcs, + /* .funcs = */ &sshkey_ecdsa_funcs }; const struct sshkey_impl sshkey_ecdsa_nistp521_cert_impl = { @@ -461,8 +772,11 @@ /* .cert = */ 1, /* .sigonly = */ 0, /* .keybits = */ 0, - /* .funcs = */ &sshkey_ecdsa_funcs, + /* .funcs = */ &sshkey_ecdsa_funcs }; -#endif +#endif /* OPENSSL_HAS_NISTP521 */ +#else + +typedef int ssh_ecdsa_empty_translation_unit; #endif /* WITH_OPENSSL && OPENSSL_HAS_ECC */ diff -ruN openssh-9.4p1/ssh-ecdsa-sk.c openssh-9.4p1+x509-14.2.1/ssh-ecdsa-sk.c --- openssh-9.4p1/ssh-ecdsa-sk.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/ssh-ecdsa-sk.c 1970-01-01 02:00:00.000000000 +0200 @@ -1,467 +0,0 @@ -/* $OpenBSD: ssh-ecdsa-sk.c,v 1.18 2023/03/08 04:43:12 guenther Exp $ */ -/* - * Copyright (c) 2000 Markus Friedl. All rights reserved. - * Copyright (c) 2010 Damien Miller. All rights reserved. - * Copyright (c) 2019 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* #define DEBUG_SK 1 */ - -#include "includes.h" - -#include - -#ifdef WITH_OPENSSL -#include -#include -#include -#include -#endif - -#include -#include /* needed for DEBUG_SK only */ - -#include "openbsd-compat/openssl-compat.h" - -#include "sshbuf.h" -#include "ssherr.h" -#include "digest.h" -#define SSHKEY_INTERNAL -#include "sshkey.h" - -#ifndef OPENSSL_HAS_ECC -/* ARGSUSED */ -int -ssh_ecdsa_sk_verify(const struct sshkey *key, - const u_char *signature, size_t signaturelen, - const u_char *data, size_t datalen, u_int compat, - struct sshkey_sig_details **detailsp) -{ - return SSH_ERR_FEATURE_UNSUPPORTED; -} -#else /* OPENSSL_HAS_ECC */ - -/* Reuse some ECDSA internals */ -extern struct sshkey_impl_funcs sshkey_ecdsa_funcs; - -static void -ssh_ecdsa_sk_cleanup(struct sshkey *k) -{ - sshkey_sk_cleanup(k); - sshkey_ecdsa_funcs.cleanup(k); -} - -static int -ssh_ecdsa_sk_equal(const struct sshkey *a, const struct sshkey *b) -{ - if (!sshkey_sk_fields_equal(a, b)) - return 0; - if (!sshkey_ecdsa_funcs.equal(a, b)) - return 0; - return 1; -} - -static int -ssh_ecdsa_sk_serialize_public(const struct sshkey *key, struct sshbuf *b, - enum sshkey_serialize_rep opts) -{ - int r; - - if ((r = sshkey_ecdsa_funcs.serialize_public(key, b, opts)) != 0) - return r; - if ((r = sshkey_serialize_sk(key, b)) != 0) - return r; - - return 0; -} - -static int -ssh_ecdsa_sk_serialize_private(const struct sshkey *key, struct sshbuf *b, - enum sshkey_serialize_rep opts) -{ - int r; - - if (!sshkey_is_cert(key)) { - if ((r = sshkey_ecdsa_funcs.serialize_public(key, - b, opts)) != 0) - return r; - } - if ((r = sshkey_serialize_private_sk(key, b)) != 0) - return r; - - return 0; -} - -static int -ssh_ecdsa_sk_copy_public(const struct sshkey *from, struct sshkey *to) -{ - int r; - - if ((r = sshkey_ecdsa_funcs.copy_public(from, to)) != 0) - return r; - if ((r = sshkey_copy_public_sk(from, to)) != 0) - return r; - return 0; -} - -static int -ssh_ecdsa_sk_deserialize_public(const char *ktype, struct sshbuf *b, - struct sshkey *key) -{ - int r; - - if ((r = sshkey_ecdsa_funcs.deserialize_public(ktype, b, key)) != 0) - return r; - if ((r = sshkey_deserialize_sk(b, key)) != 0) - return r; - return 0; -} - -static int -ssh_ecdsa_sk_deserialize_private(const char *ktype, struct sshbuf *b, - struct sshkey *key) -{ - int r; - - if (!sshkey_is_cert(key)) { - if ((r = sshkey_ecdsa_funcs.deserialize_public(ktype, - b, key)) != 0) - return r; - } - if ((r = sshkey_private_deserialize_sk(b, key)) != 0) - return r; - - return 0; -} - -/* - * Check FIDO/W3C webauthn signatures clientData field against the expected - * format and prepare a hash of it for use in signature verification. - * - * webauthn signatures do not sign the hash of the message directly, but - * instead sign a JSON-like "clientData" wrapper structure that contains the - * message hash along with a other information. - * - * Fortunately this structure has a fixed format so it is possible to verify - * that the hash of the signed message is present within the clientData - * structure without needing to implement any JSON parsing. - */ -static int -webauthn_check_prepare_hash(const u_char *data, size_t datalen, - const char *origin, const struct sshbuf *wrapper, - uint8_t flags, const struct sshbuf *extensions, - u_char *msghash, size_t msghashlen) -{ - int r = SSH_ERR_INTERNAL_ERROR; - struct sshbuf *chall = NULL, *m = NULL; - - if ((m = sshbuf_new()) == NULL || - (chall = sshbuf_from(data, datalen)) == NULL) { - r = SSH_ERR_ALLOC_FAIL; - goto out; - } - /* - * Ensure origin contains no quote character and that the flags are - * consistent with what we received - */ - if (strchr(origin, '\"') != NULL || - (flags & 0x40) != 0 /* AD */ || - ((flags & 0x80) == 0 /* ED */) != (sshbuf_len(extensions) == 0)) { - r = SSH_ERR_INVALID_FORMAT; - goto out; - } - - /* - * Prepare the preamble to clientData that we expect, poking the - * challenge and origin into their canonical positions in the - * structure. The crossOrigin flag and any additional extension - * fields present are ignored. - */ -#define WEBAUTHN_0 "{\"type\":\"webauthn.get\",\"challenge\":\"" -#define WEBAUTHN_1 "\",\"origin\":\"" -#define WEBAUTHN_2 "\"" - if ((r = sshbuf_put(m, WEBAUTHN_0, sizeof(WEBAUTHN_0) - 1)) != 0 || - (r = sshbuf_dtourlb64(chall, m, 0)) != 0 || - (r = sshbuf_put(m, WEBAUTHN_1, sizeof(WEBAUTHN_1) - 1)) != 0 || - (r = sshbuf_put(m, origin, strlen(origin))) != 0 || - (r = sshbuf_put(m, WEBAUTHN_2, sizeof(WEBAUTHN_2) - 1)) != 0) - goto out; -#ifdef DEBUG_SK - fprintf(stderr, "%s: received origin: %s\n", __func__, origin); - fprintf(stderr, "%s: received clientData:\n", __func__); - sshbuf_dump(wrapper, stderr); - fprintf(stderr, "%s: expected clientData premable:\n", __func__); - sshbuf_dump(m, stderr); -#endif - /* Check that the supplied clientData has the preamble we expect */ - if ((r = sshbuf_cmp(wrapper, 0, sshbuf_ptr(m), sshbuf_len(m))) != 0) - goto out; - - /* Prepare hash of clientData */ - if ((r = ssh_digest_buffer(SSH_DIGEST_SHA256, wrapper, - msghash, msghashlen)) != 0) - goto out; - - /* success */ - r = 0; - out: - sshbuf_free(chall); - sshbuf_free(m); - return r; -} - -static int -ssh_ecdsa_sk_verify(const struct sshkey *key, - const u_char *sig, size_t siglen, - const u_char *data, size_t dlen, const char *alg, u_int compat, - struct sshkey_sig_details **detailsp) -{ - ECDSA_SIG *esig = NULL; - BIGNUM *sig_r = NULL, *sig_s = NULL; - u_char sig_flags; - u_char msghash[32], apphash[32], sighash[32]; - u_int sig_counter; - int is_webauthn = 0, ret = SSH_ERR_INTERNAL_ERROR; - struct sshbuf *b = NULL, *sigbuf = NULL, *original_signed = NULL; - struct sshbuf *webauthn_wrapper = NULL, *webauthn_exts = NULL; - char *ktype = NULL, *webauthn_origin = NULL; - struct sshkey_sig_details *details = NULL; -#ifdef DEBUG_SK - char *tmp = NULL; -#endif - - if (detailsp != NULL) - *detailsp = NULL; - if (key == NULL || key->ecdsa == NULL || - sshkey_type_plain(key->type) != KEY_ECDSA_SK || - sig == NULL || siglen == 0) - return SSH_ERR_INVALID_ARGUMENT; - - if (key->ecdsa_nid != NID_X9_62_prime256v1) - return SSH_ERR_INTERNAL_ERROR; - - /* fetch signature */ - if ((b = sshbuf_from(sig, siglen)) == NULL) - return SSH_ERR_ALLOC_FAIL; - if ((details = calloc(1, sizeof(*details))) == NULL) { - ret = SSH_ERR_ALLOC_FAIL; - goto out; - } - if (sshbuf_get_cstring(b, &ktype, NULL) != 0) { - ret = SSH_ERR_INVALID_FORMAT; - goto out; - } - if (strcmp(ktype, "webauthn-sk-ecdsa-sha2-nistp256@openssh.com") == 0) - is_webauthn = 1; - else if (strcmp(ktype, "sk-ecdsa-sha2-nistp256@openssh.com") != 0) { - ret = SSH_ERR_INVALID_FORMAT; - goto out; - } - if (sshbuf_froms(b, &sigbuf) != 0 || - sshbuf_get_u8(b, &sig_flags) != 0 || - sshbuf_get_u32(b, &sig_counter) != 0) { - ret = SSH_ERR_INVALID_FORMAT; - goto out; - } - if (is_webauthn) { - if (sshbuf_get_cstring(b, &webauthn_origin, NULL) != 0 || - sshbuf_froms(b, &webauthn_wrapper) != 0 || - sshbuf_froms(b, &webauthn_exts) != 0) { - ret = SSH_ERR_INVALID_FORMAT; - goto out; - } - } - if (sshbuf_len(b) != 0) { - ret = SSH_ERR_UNEXPECTED_TRAILING_DATA; - goto out; - } - - /* parse signature */ - if (sshbuf_get_bignum2(sigbuf, &sig_r) != 0 || - sshbuf_get_bignum2(sigbuf, &sig_s) != 0) { - ret = SSH_ERR_INVALID_FORMAT; - goto out; - } - if (sshbuf_len(sigbuf) != 0) { - ret = SSH_ERR_UNEXPECTED_TRAILING_DATA; - goto out; - } - -#ifdef DEBUG_SK - fprintf(stderr, "%s: data: (len %zu)\n", __func__, datalen); - /* sshbuf_dump_data(data, datalen, stderr); */ - fprintf(stderr, "%s: sig_r: %s\n", __func__, (tmp = BN_bn2hex(sig_r))); - free(tmp); - fprintf(stderr, "%s: sig_s: %s\n", __func__, (tmp = BN_bn2hex(sig_s))); - free(tmp); - fprintf(stderr, "%s: sig_flags = 0x%02x, sig_counter = %u\n", - __func__, sig_flags, sig_counter); - if (is_webauthn) { - fprintf(stderr, "%s: webauthn origin: %s\n", __func__, - webauthn_origin); - fprintf(stderr, "%s: webauthn_wrapper:\n", __func__); - sshbuf_dump(webauthn_wrapper, stderr); - } -#endif - if ((esig = ECDSA_SIG_new()) == NULL) { - ret = SSH_ERR_ALLOC_FAIL; - goto out; - } - if (!ECDSA_SIG_set0(esig, sig_r, sig_s)) { - ret = SSH_ERR_LIBCRYPTO_ERROR; - goto out; - } - sig_r = sig_s = NULL; /* transferred */ - - /* Reconstruct data that was supposedly signed */ - if ((original_signed = sshbuf_new()) == NULL) { - ret = SSH_ERR_ALLOC_FAIL; - goto out; - } - if (is_webauthn) { - if ((ret = webauthn_check_prepare_hash(data, dlen, - webauthn_origin, webauthn_wrapper, sig_flags, webauthn_exts, - msghash, sizeof(msghash))) != 0) - goto out; - } else if ((ret = ssh_digest_memory(SSH_DIGEST_SHA256, data, dlen, - msghash, sizeof(msghash))) != 0) - goto out; - /* Application value is hashed before signature */ - if ((ret = ssh_digest_memory(SSH_DIGEST_SHA256, key->sk_application, - strlen(key->sk_application), apphash, sizeof(apphash))) != 0) - goto out; -#ifdef DEBUG_SK - fprintf(stderr, "%s: hashed application:\n", __func__); - sshbuf_dump_data(apphash, sizeof(apphash), stderr); - fprintf(stderr, "%s: hashed message:\n", __func__); - sshbuf_dump_data(msghash, sizeof(msghash), stderr); -#endif - if ((ret = sshbuf_put(original_signed, - apphash, sizeof(apphash))) != 0 || - (ret = sshbuf_put_u8(original_signed, sig_flags)) != 0 || - (ret = sshbuf_put_u32(original_signed, sig_counter)) != 0 || - (ret = sshbuf_putb(original_signed, webauthn_exts)) != 0 || - (ret = sshbuf_put(original_signed, msghash, sizeof(msghash))) != 0) - goto out; - /* Signature is over H(original_signed) */ - if ((ret = ssh_digest_buffer(SSH_DIGEST_SHA256, original_signed, - sighash, sizeof(sighash))) != 0) - goto out; - details->sk_counter = sig_counter; - details->sk_flags = sig_flags; -#ifdef DEBUG_SK - fprintf(stderr, "%s: signed buf:\n", __func__); - sshbuf_dump(original_signed, stderr); - fprintf(stderr, "%s: signed hash:\n", __func__); - sshbuf_dump_data(sighash, sizeof(sighash), stderr); -#endif - - /* Verify it */ - switch (ECDSA_do_verify(sighash, sizeof(sighash), esig, key->ecdsa)) { - case 1: - ret = 0; - break; - case 0: - ret = SSH_ERR_SIGNATURE_INVALID; - goto out; - default: - ret = SSH_ERR_LIBCRYPTO_ERROR; - goto out; - } - /* success */ - if (detailsp != NULL) { - *detailsp = details; - details = NULL; - } - out: - explicit_bzero(&sig_flags, sizeof(sig_flags)); - explicit_bzero(&sig_counter, sizeof(sig_counter)); - explicit_bzero(msghash, sizeof(msghash)); - explicit_bzero(sighash, sizeof(msghash)); - explicit_bzero(apphash, sizeof(apphash)); - sshkey_sig_details_free(details); - sshbuf_free(webauthn_wrapper); - sshbuf_free(webauthn_exts); - free(webauthn_origin); - sshbuf_free(original_signed); - sshbuf_free(sigbuf); - sshbuf_free(b); - ECDSA_SIG_free(esig); - BN_clear_free(sig_r); - BN_clear_free(sig_s); - free(ktype); - return ret; -} - -static const struct sshkey_impl_funcs sshkey_ecdsa_sk_funcs = { - /* .size = */ NULL, - /* .alloc = */ NULL, - /* .cleanup = */ ssh_ecdsa_sk_cleanup, - /* .equal = */ ssh_ecdsa_sk_equal, - /* .ssh_serialize_public = */ ssh_ecdsa_sk_serialize_public, - /* .ssh_deserialize_public = */ ssh_ecdsa_sk_deserialize_public, - /* .ssh_serialize_private = */ ssh_ecdsa_sk_serialize_private, - /* .ssh_deserialize_private = */ ssh_ecdsa_sk_deserialize_private, - /* .generate = */ NULL, - /* .copy_public = */ ssh_ecdsa_sk_copy_public, - /* .sign = */ NULL, - /* .verify = */ ssh_ecdsa_sk_verify, -}; - -const struct sshkey_impl sshkey_ecdsa_sk_impl = { - /* .name = */ "sk-ecdsa-sha2-nistp256@openssh.com", - /* .shortname = */ "ECDSA-SK", - /* .sigalg = */ NULL, - /* .type = */ KEY_ECDSA_SK, - /* .nid = */ NID_X9_62_prime256v1, - /* .cert = */ 0, - /* .sigonly = */ 0, - /* .keybits = */ 256, - /* .funcs = */ &sshkey_ecdsa_sk_funcs, -}; - -const struct sshkey_impl sshkey_ecdsa_sk_cert_impl = { - /* .name = */ "sk-ecdsa-sha2-nistp256-cert-v01@openssh.com", - /* .shortname = */ "ECDSA-SK-CERT", - /* .sigalg = */ NULL, - /* .type = */ KEY_ECDSA_SK_CERT, - /* .nid = */ NID_X9_62_prime256v1, - /* .cert = */ 1, - /* .sigonly = */ 0, - /* .keybits = */ 256, - /* .funcs = */ &sshkey_ecdsa_sk_funcs, -}; - -const struct sshkey_impl sshkey_ecdsa_sk_webauthn_impl = { - /* .name = */ "webauthn-sk-ecdsa-sha2-nistp256@openssh.com", - /* .shortname = */ "ECDSA-SK", - /* .sigalg = */ NULL, - /* .type = */ KEY_ECDSA_SK, - /* .nid = */ NID_X9_62_prime256v1, - /* .cert = */ 0, - /* .sigonly = */ 1, - /* .keybits = */ 256, - /* .funcs = */ &sshkey_ecdsa_sk_funcs, -}; - -#endif /* OPENSSL_HAS_ECC */ diff -ruN openssh-9.4p1/ssh-ed25519.c openssh-9.4p1+x509-14.2.1/ssh-ed25519.c --- openssh-9.4p1/ssh-ed25519.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/ssh-ed25519.c 2023-08-20 10:07:01.000000000 +0300 @@ -1,6 +1,7 @@ /* $OpenBSD: ssh-ed25519.c,v 1.19 2022/10/28 00:44:44 djm Exp $ */ /* * Copyright (c) 2013 Markus Friedl + * Copyright (c) 2022 Roumen Petrov. All rights reserved. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -25,6 +26,8 @@ #include #include +#include "evp-compat.h" + #include "log.h" #include "sshbuf.h" #define SSHKEY_INTERNAL @@ -32,12 +35,117 @@ #include "ssherr.h" #include "ssh.h" +static int +sshbuf_read_pub_ed25519(struct sshbuf *buf, struct sshkey *key) { + int r; + u_char *ed25519_pk = NULL; + size_t pklen = 0; + + r = sshbuf_get_string(buf, &ed25519_pk, &pklen); + if (r != 0) goto err; + + if (pklen != ED25519_PK_SZ) { + r = SSH_ERR_INVALID_FORMAT; + goto err; + } + +#ifdef OPENSSL_HAS_ED25519 +{ EVP_PKEY *pk = EVP_PKEY_new_raw_public_key(EVP_PKEY_ED25519, NULL, ed25519_pk, pklen); + if (pk == NULL) { + r = SSH_ERR_INVALID_FORMAT; + goto err; + } + key->pk = pk; +} +#endif + key->ed25519_pk = ed25519_pk; + ed25519_pk = NULL; /* transferred */ + +err: + freezero(ed25519_pk, pklen); + return r; +} + +static inline int +sshbuf_write_pub_ed25519(struct sshbuf *buf, const struct sshkey *key) { + return sshbuf_put_string(buf, key->ed25519_pk, ED25519_PK_SZ); +} + + +static int +sshbuf_read_priv_ed25519(struct sshbuf *buf, struct sshkey *key) { + int r; + u_char *ed25519_sk = NULL; + size_t sklen = 0; + + r = sshbuf_get_string(buf, &ed25519_sk, &sklen); + if (r != 0) goto err; + + if (sklen != ED25519_SK_SZ) { + r = SSH_ERR_INVALID_FORMAT; + goto err; + } + +#ifdef OPENSSL_HAS_ED25519 +{ EVP_PKEY *pk = EVP_PKEY_new_raw_private_key(EVP_PKEY_ED25519, NULL, + ed25519_sk, sklen - ED25519_PK_SZ); + if (pk == NULL) { + r = SSH_ERR_INVALID_FORMAT; + goto err; + } + if (key->pk != NULL) { + /* TODO match public vs private ? */ + if (ssh_EVP_PKEY_eq(key->pk, pk) != 1) { + EVP_PKEY_free(pk); + r = SSH_ERR_INVALID_ARGUMENT; + goto err; + } + EVP_PKEY_free(key->pk); + } + key->pk = pk; +} +#endif + key->ed25519_sk = ed25519_sk; + ed25519_sk = NULL; /* transferred */ + +err: + freezero(ed25519_sk, sklen); + return r; +} + +static inline int +sshbuf_write_priv_ed25519(struct sshbuf *buf, const struct sshkey *key) { + return sshbuf_put_string(buf, key->ed25519_sk, ED25519_SK_SZ); +} + + +/* key implementation */ + +static u_int +ssh_ed25519_size(const struct sshkey *key) +{ +#ifdef WITH_OPENSSL + if (key->pk != NULL) { + /* work-around, see OpenSSL issue #19070: + * 253 in OpenSSL 1.1.1 + * 253 in OpenSSL 3.0 for non provider keys + return EVP_PKEY_bits(key->pk); + */ + return 256; + } +#endif + return 256; +} + static void ssh_ed25519_cleanup(struct sshkey *k) { +#ifdef OPENSSL_HAS_ED25519 + sshkey_clear_pkey(k); +#endif freezero(k->ed25519_pk, ED25519_PK_SZ); - freezero(k->ed25519_sk, ED25519_SK_SZ); k->ed25519_pk = NULL; + freezero(k->ed25519_sk, ED25519_SK_SZ); k->ed25519_sk = NULL; } @@ -52,42 +160,56 @@ } static int -ssh_ed25519_serialize_public(const struct sshkey *key, struct sshbuf *b, +ssh_ed25519_serialize_public(const struct sshkey *key, struct sshbuf *buf, enum sshkey_serialize_rep opts) { - int r; - + UNUSED(opts); if (key->ed25519_pk == NULL) return SSH_ERR_INVALID_ARGUMENT; - if ((r = sshbuf_put_string(b, key->ed25519_pk, ED25519_PK_SZ)) != 0) - return r; - return 0; + return sshbuf_write_pub_ed25519(buf, key); } static int -ssh_ed25519_serialize_private(const struct sshkey *key, struct sshbuf *b, +ssh_ed25519_serialize_private(const struct sshkey *key, struct sshbuf *buf, enum sshkey_serialize_rep opts) { int r; - if ((r = sshbuf_put_string(b, key->ed25519_pk, ED25519_PK_SZ)) != 0 || - (r = sshbuf_put_string(b, key->ed25519_sk, ED25519_SK_SZ)) != 0) + UNUSED(opts); + /* NOTE !cert */ + if ((r = sshbuf_write_pub_ed25519(buf, key)) != 0) return r; - - return 0; + return sshbuf_write_priv_ed25519(buf, key); } static int -ssh_ed25519_generate(struct sshkey *k, int bits) -{ - if ((k->ed25519_pk = malloc(ED25519_PK_SZ)) == NULL || - (k->ed25519_sk = malloc(ED25519_SK_SZ)) == NULL) +ssh_ed25519_generate(struct sshkey *key, int bits) { + UNUSED(bits); + + if ((key->ed25519_pk = malloc(ED25519_PK_SZ)) == NULL || + (key->ed25519_sk = malloc(ED25519_SK_SZ)) == NULL) return SSH_ERR_ALLOC_FAIL; - crypto_sign_ed25519_keypair(k->ed25519_pk, k->ed25519_sk); + crypto_sign_ed25519_keypair(key->ed25519_pk, key->ed25519_sk); +#ifdef OPENSSL_HAS_ED25519 + key->pk = EVP_PKEY_new_raw_private_key(EVP_PKEY_ED25519, NULL, + key->ed25519_sk, ED25519_SK_SZ - ED25519_PK_SZ); + if (key->pk == NULL) + return SSH_ERR_LIBCRYPTO_ERROR; +#endif return 0; } +static void +ssh_ed25519_move_public(struct sshkey *from, struct sshkey *to) { +#ifdef OPENSSL_HAS_ED25519 + sshkey_move_pk(from, to); +#endif + freezero(to->ed25519_pk, ED25519_PK_SZ); + to->ed25519_pk = from->ed25519_pk; + from->ed25519_pk = NULL; +} + static int ssh_ed25519_copy_public(const struct sshkey *from, struct sshkey *to) { @@ -96,63 +218,45 @@ if ((to->ed25519_pk = malloc(ED25519_PK_SZ)) == NULL) return SSH_ERR_ALLOC_FAIL; memcpy(to->ed25519_pk, from->ed25519_pk, ED25519_PK_SZ); +#ifdef OPENSSL_HAS_ED25519 + to->pk = EVP_PKEY_new_raw_public_key(EVP_PKEY_ED25519, NULL, + to->ed25519_pk, ED25519_PK_SZ); + if (to->pk == NULL) + return SSH_ERR_LIBCRYPTO_ERROR; +#endif return 0; } static int -ssh_ed25519_deserialize_public(const char *ktype, struct sshbuf *b, +ssh_ed25519_deserialize_public(const char *pkalg, struct sshbuf *buf, struct sshkey *key) { - u_char *pk = NULL; - size_t len = 0; - int r; - - if ((r = sshbuf_get_string(b, &pk, &len)) != 0) - return r; - if (len != ED25519_PK_SZ) { - freezero(pk, len); - return SSH_ERR_INVALID_FORMAT; - } - key->ed25519_pk = pk; - return 0; + UNUSED(pkalg); + return sshbuf_read_pub_ed25519(buf, key); } static int -ssh_ed25519_deserialize_private(const char *ktype, struct sshbuf *b, +ssh_ed25519_deserialize_private(const char *pkalg, struct sshbuf *buf, struct sshkey *key) { int r; - size_t sklen = 0; - u_char *ed25519_sk = NULL; - if ((r = ssh_ed25519_deserialize_public(NULL, b, key)) != 0) - goto out; - if ((r = sshbuf_get_string(b, &ed25519_sk, &sklen)) != 0) - goto out; - if (sklen != ED25519_SK_SZ) { - r = SSH_ERR_INVALID_FORMAT; - goto out; - } - key->ed25519_sk = ed25519_sk; - ed25519_sk = NULL; /* transferred */ - /* success */ - r = 0; - out: - freezero(ed25519_sk, sklen); - return r; + UNUSED(pkalg); + /* NOTE !cert */ + if ((r = sshbuf_read_pub_ed25519(buf, key)) != 0) + return r; + return sshbuf_read_priv_ed25519(buf, key); } static int -ssh_ed25519_sign(struct sshkey *key, - u_char **sigp, size_t *lenp, - const u_char *data, size_t datalen, - const char *alg, const char *sk_provider, const char *sk_pin, u_int compat) +ssh_ed25519_sign(const ssh_sign_ctx *ctx, u_char **sigp, size_t *lenp, + const u_char *data, size_t datalen) { + const struct sshkey *key = ctx->key; u_char *sig = NULL; - size_t slen = 0, len; + size_t slen = 0; unsigned long long smlen; - int r, ret; - struct sshbuf *b = NULL; + int r; if (lenp != NULL) *lenp = 0; @@ -168,33 +272,16 @@ if ((sig = malloc(slen)) == NULL) return SSH_ERR_ALLOC_FAIL; - if ((ret = crypto_sign_ed25519(sig, &smlen, data, datalen, - key->ed25519_sk)) != 0 || smlen <= datalen) { + if (crypto_sign_ed25519(sig, &smlen, data, datalen, + key->ed25519_sk) != 0 || smlen <= datalen) { r = SSH_ERR_INVALID_ARGUMENT; /* XXX better error? */ goto out; } - /* encode signature */ - if ((b = sshbuf_new()) == NULL) { - r = SSH_ERR_ALLOC_FAIL; - goto out; - } - if ((r = sshbuf_put_cstring(b, "ssh-ed25519")) != 0 || - (r = sshbuf_put_string(b, sig, smlen - datalen)) != 0) - goto out; - len = sshbuf_len(b); - if (sigp != NULL) { - if ((*sigp = malloc(len)) == NULL) { - r = SSH_ERR_ALLOC_FAIL; - goto out; - } - memcpy(*sigp, sshbuf_ptr(b), len); - } - if (lenp != NULL) - *lenp = len; - /* success */ - r = 0; + + r = ssh_encode_signature(sigp, lenp, + "ssh-ed25519", sig, smlen - datalen); + out: - sshbuf_free(b); if (sig != NULL) freezero(sig, slen); @@ -202,11 +289,11 @@ } static int -ssh_ed25519_verify(const struct sshkey *key, +ssh_ed25519_verify(const ssh_verify_ctx *ctx, const u_char *sig, size_t siglen, - const u_char *data, size_t dlen, const char *alg, u_int compat, - struct sshkey_sig_details **detailsp) + const u_char *data, size_t dlen) { + const struct sshkey *key = ctx->key; struct sshbuf *b = NULL; char *ktype = NULL; const u_char *sigblob; @@ -272,20 +359,20 @@ return r; } -/* NB. not static; used by ED25519-SK */ -const struct sshkey_impl_funcs sshkey_ed25519_funcs = { - /* .size = */ NULL, - /* .alloc = */ NULL, +static const struct sshkey_impl_funcs sshkey_ed25519_funcs = { + /* .size = */ ssh_ed25519_size, + /* .alloc = NULL, */ /* .cleanup = */ ssh_ed25519_cleanup, /* .equal = */ ssh_ed25519_equal, - /* .ssh_serialize_public = */ ssh_ed25519_serialize_public, - /* .ssh_deserialize_public = */ ssh_ed25519_deserialize_public, - /* .ssh_serialize_private = */ ssh_ed25519_serialize_private, - /* .ssh_deserialize_private = */ ssh_ed25519_deserialize_private, + /* .serialize_public = */ ssh_ed25519_serialize_public, + /* .deserialize_public = */ ssh_ed25519_deserialize_public, + /* .serialize_private = */ ssh_ed25519_serialize_private, + /* .deserialize_private = */ ssh_ed25519_deserialize_private, /* .generate = */ ssh_ed25519_generate, + /* .move_public = */ ssh_ed25519_move_public, /* .copy_public = */ ssh_ed25519_copy_public, /* .sign = */ ssh_ed25519_sign, - /* .verify = */ ssh_ed25519_verify, + /* .verify = */ ssh_ed25519_verify }; const struct sshkey_impl sshkey_ed25519_impl = { @@ -297,7 +384,7 @@ /* .cert = */ 0, /* .sigonly = */ 0, /* .keybits = */ 256, - /* .funcs = */ &sshkey_ed25519_funcs, + /* .funcs = */ &sshkey_ed25519_funcs }; const struct sshkey_impl sshkey_ed25519_cert_impl = { @@ -309,5 +396,5 @@ /* .cert = */ 1, /* .sigonly = */ 0, /* .keybits = */ 256, - /* .funcs = */ &sshkey_ed25519_funcs, + /* .funcs = */ &sshkey_ed25519_funcs }; diff -ruN openssh-9.4p1/ssh-ed25519-sk.c openssh-9.4p1+x509-14.2.1/ssh-ed25519-sk.c --- openssh-9.4p1/ssh-ed25519-sk.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/ssh-ed25519-sk.c 1970-01-01 02:00:00.000000000 +0200 @@ -1,288 +0,0 @@ -/* $OpenBSD: ssh-ed25519-sk.c,v 1.15 2022/10/28 00:44:44 djm Exp $ */ -/* - * Copyright (c) 2019 Markus Friedl. All rights reserved. - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -/* #define DEBUG_SK 1 */ - -#include "includes.h" - -#define SSHKEY_INTERNAL -#include -#include - -#include "crypto_api.h" - -#include -#include - -#include "log.h" -#include "sshbuf.h" -#include "sshkey.h" -#include "ssherr.h" -#include "ssh.h" -#include "digest.h" - -/* Reuse some ED25519 internals */ -extern struct sshkey_impl_funcs sshkey_ed25519_funcs; - -static void -ssh_ed25519_sk_cleanup(struct sshkey *k) -{ - sshkey_sk_cleanup(k); - sshkey_ed25519_funcs.cleanup(k); -} - -static int -ssh_ed25519_sk_equal(const struct sshkey *a, const struct sshkey *b) -{ - if (!sshkey_sk_fields_equal(a, b)) - return 0; - if (!sshkey_ed25519_funcs.equal(a, b)) - return 0; - return 1; -} - -static int -ssh_ed25519_sk_serialize_public(const struct sshkey *key, struct sshbuf *b, - enum sshkey_serialize_rep opts) -{ - int r; - - if ((r = sshkey_ed25519_funcs.serialize_public(key, b, opts)) != 0) - return r; - if ((r = sshkey_serialize_sk(key, b)) != 0) - return r; - - return 0; -} - -static int -ssh_ed25519_sk_serialize_private(const struct sshkey *key, struct sshbuf *b, - enum sshkey_serialize_rep opts) -{ - int r; - - if ((r = sshkey_ed25519_funcs.serialize_public(key, b, opts)) != 0) - return r; - if ((r = sshkey_serialize_private_sk(key, b)) != 0) - return r; - - return 0; -} - -static int -ssh_ed25519_sk_copy_public(const struct sshkey *from, struct sshkey *to) -{ - int r; - - if ((r = sshkey_ed25519_funcs.copy_public(from, to)) != 0) - return r; - if ((r = sshkey_copy_public_sk(from, to)) != 0) - return r; - return 0; -} - -static int -ssh_ed25519_sk_deserialize_public(const char *ktype, struct sshbuf *b, - struct sshkey *key) -{ - int r; - - if ((r = sshkey_ed25519_funcs.deserialize_public(ktype, b, key)) != 0) - return r; - if ((r = sshkey_deserialize_sk(b, key)) != 0) - return r; - return 0; -} - -static int -ssh_ed25519_sk_deserialize_private(const char *ktype, struct sshbuf *b, - struct sshkey *key) -{ - int r; - - if ((r = sshkey_ed25519_funcs.deserialize_public(ktype, b, key)) != 0) - return r; - if ((r = sshkey_private_deserialize_sk(b, key)) != 0) - return r; - return 0; -} - -static int -ssh_ed25519_sk_verify(const struct sshkey *key, - const u_char *sig, size_t siglen, - const u_char *data, size_t dlen, const char *alg, u_int compat, - struct sshkey_sig_details **detailsp) -{ - struct sshbuf *b = NULL; - struct sshbuf *encoded = NULL; - char *ktype = NULL; - const u_char *sigblob; - const u_char *sm; - u_char *m = NULL; - u_char apphash[32]; - u_char msghash[32]; - u_char sig_flags; - u_int sig_counter; - size_t len; - unsigned long long smlen = 0, mlen = 0; - int r = SSH_ERR_INTERNAL_ERROR; - int ret; - struct sshkey_sig_details *details = NULL; - - if (detailsp != NULL) - *detailsp = NULL; - - if (key == NULL || - sshkey_type_plain(key->type) != KEY_ED25519_SK || - key->ed25519_pk == NULL || - sig == NULL || siglen == 0) - return SSH_ERR_INVALID_ARGUMENT; - - if ((b = sshbuf_from(sig, siglen)) == NULL) - return SSH_ERR_ALLOC_FAIL; - if (sshbuf_get_cstring(b, &ktype, NULL) != 0 || - sshbuf_get_string_direct(b, &sigblob, &len) != 0 || - sshbuf_get_u8(b, &sig_flags) != 0 || - sshbuf_get_u32(b, &sig_counter) != 0) { - r = SSH_ERR_INVALID_FORMAT; - goto out; - } -#ifdef DEBUG_SK - fprintf(stderr, "%s: data:\n", __func__); - /* sshbuf_dump_data(data, datalen, stderr); */ - fprintf(stderr, "%s: sigblob:\n", __func__); - sshbuf_dump_data(sigblob, len, stderr); - fprintf(stderr, "%s: sig_flags = 0x%02x, sig_counter = %u\n", - __func__, sig_flags, sig_counter); -#endif - if (strcmp(sshkey_ssh_name_plain(key), ktype) != 0) { - r = SSH_ERR_KEY_TYPE_MISMATCH; - goto out; - } - if (sshbuf_len(b) != 0) { - r = SSH_ERR_UNEXPECTED_TRAILING_DATA; - goto out; - } - if (len > crypto_sign_ed25519_BYTES) { - r = SSH_ERR_INVALID_FORMAT; - goto out; - } - if (ssh_digest_memory(SSH_DIGEST_SHA256, key->sk_application, - strlen(key->sk_application), apphash, sizeof(apphash)) != 0 || - ssh_digest_memory(SSH_DIGEST_SHA256, data, dlen, - msghash, sizeof(msghash)) != 0) { - r = SSH_ERR_INVALID_ARGUMENT; - goto out; - } -#ifdef DEBUG_SK - fprintf(stderr, "%s: hashed application:\n", __func__); - sshbuf_dump_data(apphash, sizeof(apphash), stderr); - fprintf(stderr, "%s: hashed message:\n", __func__); - sshbuf_dump_data(msghash, sizeof(msghash), stderr); -#endif - if ((details = calloc(1, sizeof(*details))) == NULL) { - r = SSH_ERR_ALLOC_FAIL; - goto out; - } - details->sk_counter = sig_counter; - details->sk_flags = sig_flags; - if ((encoded = sshbuf_new()) == NULL) { - r = SSH_ERR_ALLOC_FAIL; - goto out; - } - if (sshbuf_put(encoded, sigblob, len) != 0 || - sshbuf_put(encoded, apphash, sizeof(apphash)) != 0 || - sshbuf_put_u8(encoded, sig_flags) != 0 || - sshbuf_put_u32(encoded, sig_counter) != 0 || - sshbuf_put(encoded, msghash, sizeof(msghash)) != 0) { - r = SSH_ERR_ALLOC_FAIL; - goto out; - } -#ifdef DEBUG_SK - fprintf(stderr, "%s: signed buf:\n", __func__); - sshbuf_dump(encoded, stderr); -#endif - sm = sshbuf_ptr(encoded); - smlen = sshbuf_len(encoded); - mlen = smlen; - if ((m = malloc(smlen)) == NULL) { - r = SSH_ERR_ALLOC_FAIL; - goto out; - } - if ((ret = crypto_sign_ed25519_open(m, &mlen, sm, smlen, - key->ed25519_pk)) != 0) { - debug2_f("crypto_sign_ed25519_open failed: %d", ret); - } - if (ret != 0 || mlen != smlen - len) { - r = SSH_ERR_SIGNATURE_INVALID; - goto out; - } - /* XXX compare 'm' and 'sm + len' ? */ - /* success */ - r = 0; - if (detailsp != NULL) { - *detailsp = details; - details = NULL; - } - out: - if (m != NULL) - freezero(m, smlen); /* NB mlen may be invalid if r != 0 */ - sshkey_sig_details_free(details); - sshbuf_free(b); - sshbuf_free(encoded); - free(ktype); - return r; -} - -static const struct sshkey_impl_funcs sshkey_ed25519_sk_funcs = { - /* .size = */ NULL, - /* .alloc = */ NULL, - /* .cleanup = */ ssh_ed25519_sk_cleanup, - /* .equal = */ ssh_ed25519_sk_equal, - /* .ssh_serialize_public = */ ssh_ed25519_sk_serialize_public, - /* .ssh_deserialize_public = */ ssh_ed25519_sk_deserialize_public, - /* .ssh_serialize_private = */ ssh_ed25519_sk_serialize_private, - /* .ssh_deserialize_private = */ ssh_ed25519_sk_deserialize_private, - /* .generate = */ NULL, - /* .copy_public = */ ssh_ed25519_sk_copy_public, - /* .sign = */ NULL, - /* .verify = */ ssh_ed25519_sk_verify, -}; - -const struct sshkey_impl sshkey_ed25519_sk_impl = { - /* .name = */ "sk-ssh-ed25519@openssh.com", - /* .shortname = */ "ED25519-SK", - /* .sigalg = */ NULL, - /* .type = */ KEY_ED25519_SK, - /* .nid = */ 0, - /* .cert = */ 0, - /* .sigonly = */ 0, - /* .keybits = */ 256, - /* .funcs = */ &sshkey_ed25519_sk_funcs, -}; - -const struct sshkey_impl sshkey_ed25519_sk_cert_impl = { - /* .name = */ "sk-ssh-ed25519-cert-v01@openssh.com", - /* .shortname = */ "ED25519-SK-CERT", - /* .sigalg = */ NULL, - /* .type = */ KEY_ED25519_SK_CERT, - /* .nid = */ 0, - /* .cert = */ 1, - /* .sigonly = */ 0, - /* .keybits = */ 256, - /* .funcs = */ &sshkey_ed25519_sk_funcs, -}; diff -ruN openssh-9.4p1/ssh_engine.0 openssh-9.4p1+x509-14.2.1/ssh_engine.0 --- openssh-9.4p1/ssh_engine.0 1970-01-01 02:00:00.000000000 +0200 +++ openssh-9.4p1+x509-14.2.1/ssh_engine.0 2023-08-20 10:07:00.000000000 +0300 @@ -0,0 +1,64 @@ +SSH_ENGINE(5) BSD File Formats Manual SSH_ENGINE(5) + +NAME + ssh_engine -- SecSH engine configuration file + +SYNOPSIS + ~/.ssh/engine + +DESCRIPTION + ssh(1) obtains additional openssl(1) engine post initialization configu- + ration from the following source: + + 1. user's configuration file (~/.ssh/engine) + + The configuration files contain sections separated by "Engine" specifica- + tion, and each section is applied only for engine that match name given + in specification. Each engine command is executed immediately after + parsing of line. + + The configuration file has the following format: + + Empty lines and lines starting with '#' are comments. Otherwise a line + is of the format "command argument". Commands may be separated by white- + space or optional whitespace and exactly one '='. Argument may option- + ally be enclosed in double quotes (") in order to represent command argu- + ment containing spaces. + + Engine Restricts the following declarations (up to the next Engine key- + word) to be only for engine that match name given after the key- + word + + [Command] + Specific to engine 'control commands'. Use openssl(1) engine -vv + command to list supported control commands with desctription. + +FILES + ~/.ssh/engine + This is the per-user openssl(1) engine configuration file. The + format of this file is described above. This file is used by the + SSH client. Because of the potential for abuse, this file must + have strict permissions: read/write for the user, and not acces- + sible by others. + +EXAMPLES + An example SecSH engine configuration file: + + # Comments allowed at start of line + Engine e_nss + CONFIG_DIR /home/sample/.mozilla/firefox/xxxxxxxx.default/ + # Above command specifies the NSS config directory. + # Refer to mozilla.org documentation how to find you profile directory. + +SEE ALSO + ssh(1) + +AUTHORS + PKIX-SSH is a derivative of the original and free ssh 1.2.12 release by + Tatu Ylonen. Aaron Campbell, Bob Beck, Markus Friedl, Niels Provos, Theo + de Raadt and Dug Song removed many bugs, re-added newer features and cre- + ated OpenSSH. Markus Friedl contributed the support for SSH protocol + versions 1.5 and 2.0. Roumen Petrov contributed support for X.509 cer- + tificates. + +BSD 12 April 2018 BSD diff -ruN openssh-9.4p1/ssh_engine.5 openssh-9.4p1+x509-14.2.1/ssh_engine.5 --- openssh-9.4p1/ssh_engine.5 1970-01-01 02:00:00.000000000 +0200 +++ openssh-9.4p1+x509-14.2.1/ssh_engine.5 2023-08-20 10:07:00.000000000 +0300 @@ -0,0 +1,120 @@ +.\" +.\" Author: Roumen Petrov +.\" Copyright (c) 2011-2018 Roumen Petrov, Sofia, Bulgaria +.\" All rights reserved +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +.\" +.\" Implement .Dd with the Mdocdate RCS keyword +.rn Dd xD +.de Dd +.ie \\$1$Mdocdate: \{\ +. xD \\$3 \\$2 \\$4 +.\} +.el .xD \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 +.. +.Dd $Mdocdate: April 12 2018 $ +.Dt SSH_ENGINE 5 +.Os +.Sh NAME +.Nm ssh_engine +.Nd SecSH engine configuration file +.Sh SYNOPSIS +.Nm ~/.ssh/engine +.Sh DESCRIPTION +.Xr ssh 1 +obtains additional +.Xr openssl 1 +engine post initialization configuration from +the following source: +.Pp +.Bl -enum -offset indent -compact +.It +user's configuration file +.Pq Pa ~/.ssh/engine +.El +.Pp +The configuration files contain sections separated by +.Dq Engine +specification, and each section is applied only for +engine that match name given in specification. +Each engine command is executed immediately after +parsing of line. +.Pp +The configuration file has the following format: +.Pp +Empty lines and lines starting with +.Ql # +are comments. +Otherwise a line is of the format +.Dq command argument . +Commands may be separated by whitespace or +optional whitespace and exactly one +.Ql = . +Argument may optionally be enclosed in double quotes +.Pq \&" +in order to represent command argument containing spaces. +.Pp +.Bl -tag -width Ds +.It Cm Engine +Restricts the following declarations (up to the next +.Cm Engine +keyword) to be only for engine that match name given after the keyword +.It Cm [Command] +Specific to engine +.Sq control commands . +Use +.Xr openssl 1 +.Va engine -vv +command to list supported control commands with desctription. +.El +.Sh FILES +.Bl -tag -width Ds +.It Pa ~/.ssh/engine +This is the per-user +.Xr openssl 1 +engine configuration file. +The format of this file is described above. +This file is used by the SSH client. +Because of the potential for abuse, this file must have strict permissions: +read/write for the user, and not accessible by others. +.El +.Sh EXAMPLES +An example SecSH engine configuration file: +.Bd -literal -offset 3n +# Comments allowed at start of line +Engine e_nss +CONFIG_DIR /home/sample/.mozilla/firefox/xxxxxxxx.default/ +# Above command specifies the NSS config directory. +# Refer to mozilla.org documentation how to find you profile directory. +.Ed +.Sh SEE ALSO +.Xr ssh 1 +.Sh AUTHORS +PKIX-SSH is a derivative of the original and free +ssh 1.2.12 release by Tatu Ylonen. +Aaron Campbell, Bob Beck, Markus Friedl, Niels Provos, +Theo de Raadt and Dug Song +removed many bugs, re-added newer features and +created OpenSSH. +Markus Friedl contributed the support for SSH +protocol versions 1.5 and 2.0. +Roumen Petrov contributed support for X.509 certificates. diff -ruN openssh-9.4p1/ssherr.c openssh-9.4p1+x509-14.2.1/ssherr.c --- openssh-9.4p1/ssherr.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/ssherr.c 2023-08-20 10:07:01.000000000 +0300 @@ -141,10 +141,6 @@ return "number is too large"; case SSH_ERR_SIGN_ALG_UNSUPPORTED: return "signature algorithm not supported"; - case SSH_ERR_FEATURE_UNSUPPORTED: - return "requested feature not supported"; - case SSH_ERR_DEVICE_NOT_FOUND: - return "device not found"; default: return "unknown error"; } diff -ruN openssh-9.4p1/ssherr.h openssh-9.4p1+x509-14.2.1/ssherr.h --- openssh-9.4p1/ssherr.h 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/ssherr.h 2023-08-20 10:07:00.000000000 +0300 @@ -81,7 +81,6 @@ #define SSH_ERR_NUMBER_TOO_LARGE -57 #define SSH_ERR_SIGN_ALG_UNSUPPORTED -58 #define SSH_ERR_FEATURE_UNSUPPORTED -59 -#define SSH_ERR_DEVICE_NOT_FOUND -60 /* Translate a numeric error code to a human-readable error string */ const char *ssh_err(int n); diff -ruN openssh-9.4p1/ssh.h openssh-9.4p1+x509-14.2.1/ssh.h --- openssh-9.4p1/ssh.h 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/ssh.h 2023-08-20 10:07:00.000000000 +0300 @@ -70,7 +70,13 @@ /* * Environment variable to control whether or not askpass is used. */ -#define SSH_ASKPASS_REQUIRE_ENV "SSH_ASKPASS_REQUIRE" +#define SSH_ASKPASS_REQUIRE_ENV "SSH_ASKPASS_REQUIRE" + +/* + * Environment variable for overwriting the default location of engine + * configuration file + */ +#define SSH_ENGINE_CONF_ENV "SSH_ENGINE_CONF" /* * Force host key length and server key length to differ by at least this diff -ruN openssh-9.4p1/sshkey.c openssh-9.4p1+x509-14.2.1/sshkey.c --- openssh-9.4p1/sshkey.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/sshkey.c 2023-08-20 10:07:01.000000000 +0300 @@ -3,6 +3,7 @@ * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. * Copyright (c) 2008 Alexander von Gernler. All rights reserved. * Copyright (c) 2010,2011 Damien Miller. All rights reserved. + * Copyright (c) 2002-2022 Roumen Petrov. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -34,6 +35,7 @@ #include #include #include +#include "evp-compat.h" #endif #include "crypto_api.h" @@ -52,20 +54,22 @@ #include "ssherr.h" #include "misc.h" #include "sshbuf.h" +#include "xmalloc.h" #include "cipher.h" #include "digest.h" #define SSHKEY_INTERNAL #include "sshkey.h" +#include "ssh-x509.h" +#include "ssh-xkalg.h" +#include "compat.h" #include "match.h" -#include "ssh-sk.h" +#include "log.h" #ifdef WITH_XMSS #include "sshkey-xmss.h" #include "xmss_fast.h" #endif -#include "openbsd-compat/openssl-compat.h" - /* openssh private key file format */ #define MARK_BEGIN "-----BEGIN OPENSSH PRIVATE KEY-----\n" #define MARK_END "-----END OPENSSH PRIVATE KEY-----\n" @@ -80,6 +84,7 @@ /* Version identification string for SSH v1 identity files. */ #define LEGACY_BEGIN "SSH PRIVATE KEY FILE FORMAT 1.1\n" +#ifdef USE_SSHKEY_SHIELDING /* * Constants relating to "shielding" support; protection of keys expected * to remain in memory for long durations @@ -87,6 +92,7 @@ #define SSHKEY_SHIELD_PREKEY_LEN (16 * 1024) #define SSHKEY_SHIELD_CIPHER "aes256-ctr" /* XXX want AES-EME* */ #define SSHKEY_SHIELD_PREKEY_HASH SSH_DIGEST_SHA512 +#endif /*def USE_SSHKEY_SHIELDING*/ int sshkey_private_serialize_opt(struct sshkey *key, struct sshbuf *buf, enum sshkey_serialize_rep); @@ -96,15 +102,8 @@ /* Supported key types */ extern const struct sshkey_impl sshkey_ed25519_impl; extern const struct sshkey_impl sshkey_ed25519_cert_impl; -extern const struct sshkey_impl sshkey_ed25519_sk_impl; -extern const struct sshkey_impl sshkey_ed25519_sk_cert_impl; #ifdef WITH_OPENSSL # ifdef OPENSSL_HAS_ECC -# ifdef ENABLE_SK -extern const struct sshkey_impl sshkey_ecdsa_sk_impl; -extern const struct sshkey_impl sshkey_ecdsa_sk_cert_impl; -extern const struct sshkey_impl sshkey_ecdsa_sk_webauthn_impl; -# endif /* ENABLE_SK */ extern const struct sshkey_impl sshkey_ecdsa_nistp256_impl; extern const struct sshkey_impl sshkey_ecdsa_nistp256_cert_impl; extern const struct sshkey_impl sshkey_ecdsa_nistp384_impl; @@ -116,25 +115,23 @@ # endif /* OPENSSL_HAS_ECC */ extern const struct sshkey_impl sshkey_rsa_impl; extern const struct sshkey_impl sshkey_rsa_cert_impl; +#ifdef HAVE_EVP_SHA256 extern const struct sshkey_impl sshkey_rsa_sha256_impl; extern const struct sshkey_impl sshkey_rsa_sha256_cert_impl; extern const struct sshkey_impl sshkey_rsa_sha512_impl; extern const struct sshkey_impl sshkey_rsa_sha512_cert_impl; +#endif /*def HAVE_EVP_SHA256*/ extern const struct sshkey_impl sshkey_dss_impl; extern const struct sshkey_impl sshkey_dsa_cert_impl; #endif /* WITH_OPENSSL */ #ifdef WITH_XMSS extern const struct sshkey_impl sshkey_xmss_impl; extern const struct sshkey_impl sshkey_xmss_cert_impl; -#endif +#endif /* WITH_XMSS */ -const struct sshkey_impl * const keyimpls[] = { +static const struct sshkey_impl * const keyimpls[] = { &sshkey_ed25519_impl, &sshkey_ed25519_cert_impl, -#ifdef ENABLE_SK - &sshkey_ed25519_sk_impl, - &sshkey_ed25519_sk_cert_impl, -#endif #ifdef WITH_OPENSSL # ifdef OPENSSL_HAS_ECC &sshkey_ecdsa_nistp256_impl, @@ -145,36 +142,34 @@ &sshkey_ecdsa_nistp521_impl, &sshkey_ecdsa_nistp521_cert_impl, # endif /* OPENSSL_HAS_NISTP521 */ -# ifdef ENABLE_SK - &sshkey_ecdsa_sk_impl, - &sshkey_ecdsa_sk_cert_impl, - &sshkey_ecdsa_sk_webauthn_impl, -# endif /* ENABLE_SK */ # endif /* OPENSSL_HAS_ECC */ - &sshkey_dss_impl, - &sshkey_dsa_cert_impl, &sshkey_rsa_impl, &sshkey_rsa_cert_impl, +#ifdef HAVE_EVP_SHA256 &sshkey_rsa_sha256_impl, &sshkey_rsa_sha256_cert_impl, &sshkey_rsa_sha512_impl, &sshkey_rsa_sha512_cert_impl, +#endif /*def HAVE_EVP_SHA256*/ + &sshkey_dss_impl, + &sshkey_dsa_cert_impl, #endif /* WITH_OPENSSL */ #ifdef WITH_XMSS &sshkey_xmss_impl, &sshkey_xmss_cert_impl, -#endif +#endif /* WITH_XMSS */ NULL }; + static const struct sshkey_impl * sshkey_impl_from_type(int type) { - int i; + const struct sshkey_impl *const* p; - for (i = 0; keyimpls[i] != NULL; i++) { - if (keyimpls[i]->type == type) - return keyimpls[i]; + for (p = keyimpls; *p != NULL; p++) { + if ((*p)->type == type) + return *p; } return NULL; } @@ -182,12 +177,12 @@ static const struct sshkey_impl * sshkey_impl_from_type_nid(int type, int nid) { - int i; + const struct sshkey_impl *const* p; - for (i = 0; keyimpls[i] != NULL; i++) { - if (keyimpls[i]->type == type && - (keyimpls[i]->nid == 0 || keyimpls[i]->nid == nid)) - return keyimpls[i]; + for (p = keyimpls; *p != NULL; p++) { + if ((*p)->type == type && + ((*p)->nid == 0 || (*p)->nid == nid)) + return *p; } return NULL; } @@ -195,44 +190,59 @@ static const struct sshkey_impl * sshkey_impl_from_key(const struct sshkey *k) { - if (k == NULL) - return NULL; + if (k == NULL) return NULL; + return sshkey_impl_from_type_nid(k->type, k->ecdsa_nid); } const char * sshkey_type(const struct sshkey *k) { - const struct sshkey_impl *impl; + if (sshkey_is_x509(k)) { + switch (sshkey_type_plain(k->type)) { + case KEY_RSA: + return k->pk ? "RSA+cert" : "X509(rsa)"; + case KEY_ECDSA: + return k->pk ? "ECDSA+cert" : "X509(ecdsa)"; + case KEY_DSA: + return k->pk ? "DSA+cert" : "X509(dsa)"; + case KEY_ED25519: + return k->pk ? "ED25519+cert" : "X509(ed25519)"; + default: + break; + } + } - if ((impl = sshkey_impl_from_key(k)) == NULL) - return "unknown"; - return impl->shortname; +{ + const struct sshkey_impl *impl = sshkey_impl_from_key(k); + + return (impl != NULL) ? impl->shortname : "unknown"; +} } static const char * sshkey_ssh_name_from_type_nid(int type, int nid) { - const struct sshkey_impl *impl; + const struct sshkey_impl *impl = sshkey_impl_from_type_nid(type, nid); - if ((impl = sshkey_impl_from_type_nid(type, nid)) == NULL) - return "ssh-unknown"; - return impl->name; + return (impl != NULL) ? impl->name : "ssh-unknown"; } int sshkey_type_is_cert(int type) { - const struct sshkey_impl *impl; + const struct sshkey_impl *impl = sshkey_impl_from_type(type); - if ((impl = sshkey_impl_from_type(type)) == NULL) - return 0; - return impl->cert; + return (impl != NULL) ? impl->cert : 0; } const char * sshkey_ssh_name(const struct sshkey *k) { +{ + const char* p = ssh_x509key_name(k); + if (p != NULL) return p; +} return sshkey_ssh_name_from_type_nid(k->type, k->ecdsa_nid); } @@ -246,16 +256,20 @@ int sshkey_type_from_name(const char *name) { - int i; - const struct sshkey_impl *impl; +{ + int k = ssh_x509key_type(name); + if (k != KEY_UNSPEC) return k; +} +{ + const struct sshkey_impl *const* p; - for (i = 0; keyimpls[i] != NULL; i++) { - impl = keyimpls[i]; + for (p = keyimpls; *p != NULL; p++) { /* Only allow shortname matches for plain key types */ - if ((impl->name != NULL && strcmp(name, impl->name) == 0) || - (!impl->cert && strcasecmp(impl->shortname, name) == 0)) - return impl->type; + if ((strcmp((*p)->name, name) == 0) || + (!(*p)->cert && strcasecmp((*p)->shortname, name) == 0)) + return (*p)->type; } +} return KEY_UNSPEC; } @@ -265,86 +279,124 @@ switch (type) { case KEY_ECDSA: case KEY_ECDSA_CERT: - case KEY_ECDSA_SK: - case KEY_ECDSA_SK_CERT: return 1; } return 0; } +void +sshkey_types_from_name(const char *name, int *type, int *subtype) { + + if (type == NULL || subtype == NULL) { + fatal_f("NULL arguments"); + return; /* unreachible code */ + } + + *type = sshkey_type_from_name((char*)name); + + if (key_type_is_ecdsa_variant(*type)) + *subtype = sshkey_ecdsa_nid_from_name(name); + else + *subtype = -1; +} + int sshkey_ecdsa_nid_from_name(const char *name) { - int i; + if (strncmp(name, "x509v3-ecdsa-", 13) == 0) { + return sshkey_ecdsa_nid_from_name(name+7); + } + +{ + const struct sshkey_impl *const* p; - for (i = 0; keyimpls[i] != NULL; i++) { - if (!key_type_is_ecdsa_variant(keyimpls[i]->type)) + for (p = keyimpls; *p != NULL; p++) { + if (!key_type_is_ecdsa_variant((*p)->type)) continue; - if (keyimpls[i]->name != NULL && - strcmp(name, keyimpls[i]->name) == 0) - return keyimpls[i]->nid; + if (strcmp((*p)->name, name) == 0) + return (*p)->nid; } +} return -1; } -int -sshkey_match_keyname_to_sigalgs(const char *keyname, const char *sigalgs) +char * +sshkey_alg_list(int certs_only, int plain_only, int include_sigonly, char sep) { - int ktype; + char *ret = NULL; + size_t rlen = 0; - if (sigalgs == NULL || *sigalgs == '\0' || - (ktype = sshkey_type_from_name(keyname)) == KEY_UNSPEC) - return 0; - else if (ktype == KEY_RSA) { - return match_pattern_list("ssh-rsa", sigalgs, 0) == 1 || - match_pattern_list("rsa-sha2-256", sigalgs, 0) == 1 || - match_pattern_list("rsa-sha2-512", sigalgs, 0) == 1; - } else if (ktype == KEY_RSA_CERT) { - return match_pattern_list("ssh-rsa-cert-v01@openssh.com", - sigalgs, 0) == 1 || - match_pattern_list("rsa-sha2-256-cert-v01@openssh.com", - sigalgs, 0) == 1 || - match_pattern_list("rsa-sha2-512-cert-v01@openssh.com", - sigalgs, 0) == 1; - } else - return match_pattern_list(keyname, sigalgs, 0) == 1; -} + if (!certs_only || plain_only) { + struct sshbuf *b; -char * -sshkey_alg_list(int certs_only, int plain_only, int include_sigonly, char sep) + fill_default_xkalg(); + if ((b = sshbuf_new()) == NULL) + fatal_f("sshbuf_new failed"); + { char sep_s[2] = { sep, '\0' }; + ssh_xkalg_listall(b, sep_s); + } + ret = xstrdup(sshbuf_ptr(b)); + rlen = sshbuf_len(b); + sshbuf_free(b); + } { - char *tmp, *ret = NULL; - size_t i, nlen, rlen = 0; - const struct sshkey_impl *impl; + const struct sshkey_impl *const* p; - for (i = 0; keyimpls[i] != NULL; i++) { - impl = keyimpls[i]; - if (impl->name == NULL) - continue; - if (!include_sigonly && impl->sigonly) + for (p = keyimpls; *p != NULL; p++) { + size_t nlen; + + if (!include_sigonly && (*p)->sigonly) continue; - if ((certs_only && !impl->cert) || (plain_only && impl->cert)) + if ((certs_only && !(*p)->cert) || (plain_only && (*p)->cert)) continue; if (ret != NULL) ret[rlen++] = sep; - nlen = strlen(impl->name); - if ((tmp = realloc(ret, rlen + nlen + 2)) == NULL) { + nlen = strlen((*p)->name); + { char *tmp = realloc(ret, rlen + nlen + 2); + if (tmp == NULL) { free(ret); return NULL; } ret = tmp; - memcpy(ret + rlen, impl->name, nlen + 1); + } + memcpy(ret + rlen, (*p)->name, nlen + 1); rlen += nlen; } +} return ret; } int +sshkey_algind(const char **name, u_int filter, int loc) { + int k, n; + int plain = (filter & SSHKEY_ALG_PLAINKEY) != 0; + int cert = (filter & SSHKEY_ALG_CUSTCERT) != 0; + + k = (loc < 0) ? 0 : (loc + 1); + n = sizeof(keyimpls) / sizeof(keyimpls[0]); + + for (; k < n; k++) { + const struct sshkey_impl *p = keyimpls[k]; + if (p == NULL) continue; + if (p->cert) { + if (!cert) continue; + } else { + if (!plain) continue; + } + + if (name != NULL) + *name = p->name; + + return k; + } + return -1; +} + +int sshkey_names_valid2(const char *names, int allow_wildcard, int plain_only) { char *s, *cp, *p; - const struct sshkey_impl *impl; - int i, type; + int type; if (names == NULL || strcmp(names, "") == 0) return 0; @@ -360,17 +412,35 @@ * If any has a positive or negative match then * the component is accepted. */ - impl = NULL; - for (i = 0; keyimpls[i] != NULL; i++) { + { + const SSHX509KeyAlgs *xkalg; + int loc; + for ( + loc = ssh_xkalg_ind(&xkalg, -1); + loc >= 0; + loc = ssh_xkalg_ind(&xkalg, loc) + ) { + if (match_pattern_list( + xkalg->name, p, 0) == 1) { + break; + } + } + if (loc >= 0) + continue; + } + { + const struct sshkey_impl *const* q; + + for (q = keyimpls; *q != NULL; q++) { if (match_pattern_list( - keyimpls[i]->name, p, 0) != 0) { - impl = keyimpls[i]; + (*q)->name, p, 0) == 1) { break; } } - if (impl != NULL) + if (q != NULL) continue; } + } free(s); return 0; } else if (plain_only && sshkey_type_is_cert(type)) { @@ -385,10 +455,10 @@ u_int sshkey_size(const struct sshkey *k) { - const struct sshkey_impl *impl; + const struct sshkey_impl *impl = sshkey_impl_from_key(k); + + if (impl == NULL) return 0; - if ((impl = sshkey_impl_from_key(k)) == NULL) - return 0; if (impl->funcs->size != NULL) return impl->funcs->size(k); return impl->keybits; @@ -413,21 +483,8 @@ return sshkey_type_is_cert(k->type); } -int -sshkey_is_sk(const struct sshkey *k) -{ - if (k == NULL) - return 0; - switch (sshkey_type_plain(k->type)) { - case KEY_ECDSA_SK: - case KEY_ED25519_SK: - return 1; - default: - return 0; - } -} - /* Return the cert-less equivalent to a certified key type */ +/* Also for X.509 certificate return base key type */ int sshkey_type_plain(int type) { @@ -438,12 +495,8 @@ return KEY_DSA; case KEY_ECDSA_CERT: return KEY_ECDSA; - case KEY_ECDSA_SK_CERT: - return KEY_ECDSA_SK; case KEY_ED25519_CERT: return KEY_ED25519; - case KEY_ED25519_SK_CERT: - return KEY_ED25519_SK; case KEY_XMSS_CERT: return KEY_XMSS; default: @@ -456,26 +509,29 @@ sshkey_type_certified(int type) { switch (type) { +#ifdef WITH_OPENSSL case KEY_RSA: return KEY_RSA_CERT; case KEY_DSA: return KEY_DSA_CERT; +# ifdef OPENSSL_HAS_ECC case KEY_ECDSA: return KEY_ECDSA_CERT; - case KEY_ECDSA_SK: - return KEY_ECDSA_SK_CERT; +# endif /* OPENSSL_HAS_ECC */ +#endif /* WITH_OPENSSL */ case KEY_ED25519: return KEY_ED25519_CERT; - case KEY_ED25519_SK: - return KEY_ED25519_SK_CERT; +#ifdef WITH_XMSS case KEY_XMSS: return KEY_XMSS_CERT; +#endif /* WITH_XMSS */ default: return -1; } } #ifdef WITH_OPENSSL +#ifdef OPENSSL_HAS_ECC /* XXX: these are really begging for a table-driven approach */ int sshkey_curve_name_to_nid(const char *name) @@ -559,6 +615,14 @@ else return SSH_DIGEST_SHA512; } + +#else /*ndef OPENSSL_HAS_ECC*/ + +int sshkey_curve_name_to_nid(const char *name) { (void)name; return -1; } +u_int sshkey_curve_nid_to_bits(int nid) { (void)nid; return 0; } +int sshkey_ecdsa_bits_to_nid(int bits) { (void)bits; return -1; } + +#endif /*ndef OPENSSL_HAS_ECC*/ #endif /* WITH_OPENSSL */ static void @@ -606,21 +670,30 @@ struct sshkey *k; const struct sshkey_impl *impl = NULL; - if (type != KEY_UNSPEC && - (impl = sshkey_impl_from_type(type)) == NULL) - return NULL; + if (type != KEY_UNSPEC) { + impl = sshkey_impl_from_type(type); + if (impl == NULL) return NULL; + } - /* All non-certificate types may act as CAs */ if ((k = calloc(1, sizeof(*k))) == NULL) return NULL; k->type = type; + k->pk = NULL; k->ecdsa_nid = -1; + k->x509_data = NULL; + k->cert = NULL; + k->ed25519_sk = NULL; + k->ed25519_pk = NULL; + k->xmss_sk = NULL; + k->xmss_pk = NULL; +#if 0 /* reserved */ if (impl != NULL && impl->funcs->alloc != NULL) { if (impl->funcs->alloc(k) != 0) { free(k); return NULL; } } +#endif if (sshkey_is_cert(k)) { if ((k->cert = cert_new()) == NULL) { sshkey_free(k); @@ -631,37 +704,27 @@ return k; } -/* Frees common FIDO fields */ void -sshkey_sk_cleanup(struct sshkey *k) -{ - free(k->sk_application); - sshbuf_free(k->sk_key_handle); - sshbuf_free(k->sk_reserved); - k->sk_application = NULL; - k->sk_key_handle = k->sk_reserved = NULL; -} - -static void -sshkey_free_contents(struct sshkey *k) +sshkey_free(struct sshkey *k) { - const struct sshkey_impl *impl; - if (k == NULL) return; - if ((impl = sshkey_impl_from_type(k->type)) != NULL && - impl->funcs->cleanup != NULL) +{ const struct sshkey_impl *impl = (k->type != KEY_UNSPEC) + ? sshkey_impl_from_type(k->type) + : NULL; + if (impl != NULL && impl->funcs->cleanup != NULL) impl->funcs->cleanup(k); +} + if (k->x509_data != NULL) { + SSH_X509_free(k->x509_data); + k->x509_data = NULL; + } if (sshkey_is_cert(k)) cert_free(k->cert); +#ifdef USE_SSHKEY_SHIELDING freezero(k->shielded_private, k->shielded_len); freezero(k->shield_prekey, k->shield_prekey_len); -} - -void -sshkey_free(struct sshkey *k) -{ - sshkey_free_contents(k); +#endif /*def USE_SSHKEY_SHIELDING*/ freezero(k, sizeof(*k)); } @@ -680,17 +743,6 @@ return 1; } -/* Compares FIDO-specific pubkey fields only */ -int -sshkey_sk_fields_equal(const struct sshkey *a, const struct sshkey *b) -{ - if (a->sk_application == NULL || b->sk_application == NULL) - return 0; - if (strcmp(a->sk_application, b->sk_application) != 0) - return 0; - return 1; -} - /* * Compare public portions of key only, allowing comparisons between * certificates and plain keys too. @@ -703,6 +755,16 @@ if (a == NULL || b == NULL || sshkey_type_plain(a->type) != sshkey_type_plain(b->type)) return 0; + + if (sshkey_is_x509(a) && sshkey_is_x509(b)) + return ssh_x509_equal(a, b) == 0; +/* +#else + Either public key or X.509 certificate must present. In latter + case public key is extracted from X.509 certificate and stored + into 'key'(rsa,dsa,..) member of key structure. +*/ + if ((impl = sshkey_impl_from_type(a->type)) == NULL) return 0; return impl->funcs->equal(a, b); @@ -720,31 +782,33 @@ return sshkey_equal_public(a, b); } - -/* Serialise common FIDO key parts */ -int -sshkey_serialize_sk(const struct sshkey *key, struct sshbuf *b) -{ - int r; - - if ((r = sshbuf_put_cstring(b, key->sk_application)) != 0) - return r; - - return 0; +int/*bool*/ +sshkey_match_pkalg(struct sshkey *key, const char* pkalg) { + int keytype, subtype; + + if (key == NULL) return 0; + if (pkalg == NULL) return 0; + + sshkey_types_from_name(pkalg, &keytype, &subtype); + return ( + (keytype == key->type) && + (subtype == key->ecdsa_nid) + ); } static int to_blob_buf(const struct sshkey *key, struct sshbuf *b, int force_plain, enum sshkey_serialize_rep opts) { - int type, ret = SSH_ERR_INTERNAL_ERROR; - const char *typename; + int type, ret; const struct sshkey_impl *impl; if (key == NULL) return SSH_ERR_INVALID_ARGUMENT; type = force_plain ? sshkey_type_plain(key->type) : key->type; + if ((impl = sshkey_impl_from_type(type)) == NULL) + return SSH_ERR_KEY_TYPE_UNKNOWN; if (sshkey_type_is_cert(type)) { if (key->cert == NULL) @@ -756,12 +820,12 @@ return ret; return 0; } - if ((impl = sshkey_impl_from_type(type)) == NULL) - return SSH_ERR_KEY_TYPE_UNKNOWN; +{ const char *typename; typename = sshkey_ssh_name_from_type_nid(type, key->ecdsa_nid); if ((ret = sshbuf_put_cstring(b, typename)) != 0) return ret; +} return impl->funcs->serialize_public(key, b, opts); } @@ -787,6 +851,7 @@ return r; } +#if 1 /* used in unit tests only */ int sshkey_puts(const struct sshkey *key, struct sshbuf *b) { @@ -798,6 +863,7 @@ { return to_blob_buf(key, b, 1, SSHKEY_SERIALIZE_DEFAULT); } +#endif static int to_blob(const struct sshkey *key, u_char **blobp, size_t *lenp, int force_plain, @@ -837,11 +903,13 @@ return to_blob(key, blobp, lenp, 0, SSHKEY_SERIALIZE_DEFAULT); } +#if 0 /* unused */ int sshkey_plain_to_blob(const struct sshkey *key, u_char **blobp, size_t *lenp) { return to_blob(key, blobp, lenp, 1, SSHKEY_SERIALIZE_DEFAULT); } +#endif int sshkey_fingerprint_raw(const struct sshkey *k, int dgst_alg, @@ -855,6 +923,11 @@ *retp = NULL; if (lenp != NULL) *lenp = 0; +#ifdef OPENSSL_FIPS + /* avoid digest like md5 if FIPS mode is activated */ + if (ssh_digest_alg_name(dgst_alg) == NULL) + dgst_alg = SSH_DIGEST_SHA256; +#endif if (ssh_digest_bytes(dgst_alg) == 0) { r = SSH_ERR_INVALID_ARGUMENT; goto out; @@ -1071,8 +1144,7 @@ /* output upper border */ p = retval; *p++ = '+'; - for (i = 0; i < (FLDSIZE_X - tlen) / 2; i++) - *p++ = '-'; + i = 0; memcpy(p, title, tlen); p += tlen; for (i += tlen; i < FLDSIZE_X; i++) @@ -1091,12 +1163,17 @@ /* output lower border */ *p++ = '+'; - for (i = 0; i < (FLDSIZE_X - hlen) / 2; i++) - *p++ = '-'; + i = 0; memcpy(p, hash, hlen); p += hlen; for (i += hlen; i < FLDSIZE_X; i++) *p++ = '-'; +#ifdef OPENSSL_FIPS + if (FIPS_mode()) { + /* width is enough to write over text*/ + strcpy(p - 6, "[FIPS]"); + } +#endif *p++ = '+'; return retval; @@ -1110,6 +1187,11 @@ u_char *dgst_raw; size_t dgst_raw_len; +#ifdef OPENSSL_FIPS + /* avoid digest like md5 if FIPS mode is activated */ + if (ssh_digest_alg_name(dgst_alg) == NULL) + dgst_alg = SSH_DIGEST_SHA256; +#endif if (sshkey_fingerprint_raw(k, dgst_alg, &dgst_raw, &dgst_raw_len) != 0) return NULL; switch (dgst_rep) { @@ -1145,31 +1227,18 @@ return retval; } -static int -peek_type_nid(const char *s, size_t l, int *nid) +/* XXX this can now be made const char * */ +int +sshkey_read(struct sshkey *ret, char **cpp) { - const struct sshkey_impl *impl; - int i; - - for (i = 0; keyimpls[i] != NULL; i++) { - impl = keyimpls[i]; - if (impl->name == NULL || strlen(impl->name) != l) - continue; - if (memcmp(s, impl->name, l) == 0) { - *nid = -1; - if (key_type_is_ecdsa_variant(impl->type)) - *nid = impl->nid; - return impl->type; - } - } - return KEY_UNSPEC; + return sshkey_read_pkalg(ret, cpp, NULL); } -/* XXX this can now be made const char * */ int -sshkey_read(struct sshkey *ret, char **cpp) +sshkey_read_pkalg(struct sshkey *ret, char **cpp, char **pkalg) { struct sshkey *k; + char pkname[64]; char *cp, *blobcopy; size_t space; int r, type, curve_nid = -1; @@ -1177,24 +1246,60 @@ if (ret == NULL) return SSH_ERR_INVALID_ARGUMENT; - if (ret->type != KEY_UNSPEC && sshkey_impl_from_type(ret->type) == NULL) + + /* caller is responsible to free memory allocated for pkalg */ + if (pkalg) *pkalg = NULL; + + switch (ret->type) { + case KEY_UNSPEC: + case KEY_RSA: + case KEY_DSA: + case KEY_ECDSA: + case KEY_ED25519: + case KEY_DSA_CERT: + case KEY_ECDSA_CERT: + case KEY_RSA_CERT: + case KEY_ED25519_CERT: +#ifdef WITH_XMSS + case KEY_XMSS: + case KEY_XMSS_CERT: +#endif /* WITH_XMSS */ + break; /* ok */ + default: return SSH_ERR_INVALID_ARGUMENT; + } /* Decode type */ cp = *cpp; space = strcspn(cp, " \t"); if (space == strlen(cp)) return SSH_ERR_INVALID_FORMAT; - if ((type = peek_type_nid(cp, space, &curve_nid)) == KEY_UNSPEC) + if ((space < 1) || (space >= sizeof(pkname))) return SSH_ERR_INVALID_FORMAT; - /* skip whitespace */ - for (cp += space; *cp == ' ' || *cp == '\t'; cp++) - ; - if (*cp == '\0') + strncpy(pkname, cp, space); + pkname[space] = '\0'; + + sshkey_types_from_name(pkname, &type, &curve_nid); + if (type == KEY_UNSPEC) return SSH_ERR_INVALID_FORMAT; if (ret->type != KEY_UNSPEC && ret->type != type) return SSH_ERR_KEY_TYPE_MISMATCH; + + /* skip whitespace */ + cp += space; + cp += strspn(cp, " \t"); + if (*cp == '\0') + return SSH_ERR_INVALID_FORMAT; + +{ char *ep; + k = X509key_from_subject(pkname, cp, &ep); + if (k != NULL) { + cp = ep; + goto noblob; + } +} + if ((blob = sshbuf_new()) == NULL) return SSH_ERR_ALLOC_FAIL; @@ -1210,36 +1315,64 @@ return r; } free(blobcopy); - if ((r = sshkey_fromb(blob, &k)) != 0) { + r = parse_key_from_blob(sshbuf_ptr(blob), sshbuf_len(blob), &k, NULL); + if (r != 0) { sshbuf_free(blob); return r; } sshbuf_free(blob); - /* skip whitespace and leave cp at start of comment */ - for (cp += space; *cp == ' ' || *cp == '\t'; cp++) - ; - /* ensure type of blob matches type at start of line */ if (k->type != type) { sshkey_free(k); return SSH_ERR_KEY_TYPE_MISMATCH; } - if (key_type_is_ecdsa_variant(type) && curve_nid != k->ecdsa_nid) { + if (sshkey_type_plain(type) == KEY_ECDSA && curve_nid != k->ecdsa_nid) { sshkey_free(k); return SSH_ERR_EC_CURVE_MISMATCH; } +noblob: + /* skip whitespace and leave cp at start of comment */ + cp += space; + cp += strspn(cp, " \t");; + /* Fill in ret from parsed key */ - sshkey_free_contents(ret); - *ret = *k; - freezero(k, sizeof(*k)); + ret->type = type; + if (sshkey_is_cert(ret)) { + if (!sshkey_is_cert(k)) { + sshkey_free(k); + return SSH_ERR_EXPECTED_CERT; + } + if (ret->cert != NULL) + cert_free(ret->cert); + ret->cert = k->cert; + k->cert = NULL; + } +{ const struct sshkey_impl *impl = sshkey_impl_from_type( + sshkey_type_plain(ret->type)); + if (impl == NULL) { + sshkey_free(k); + return SSH_ERR_INTERNAL_ERROR; + } + impl->funcs->move_public(k, ret); +} + /* Test with loaded key, as for X.509 certificates + we consider keys as equivalent if base type match + */ + if (sshkey_is_x509(k)) + x509key_move_identity(k, ret); + + sshkey_free(k); /* success */ *cpp = cp; + if (pkalg) + *pkalg = xstrdup(pkname); /*fatal on error*/ return 0; } + int sshkey_to_base64(const struct sshkey *key, char **b64p) { @@ -1275,6 +1408,9 @@ int r = SSH_ERR_INTERNAL_ERROR; char *uu = NULL; + if (sshkey_is_x509(key)) + return x509key_write(key, b); + if ((r = sshkey_to_base64(key, &uu)) != 0) goto out; if ((r = sshbuf_putf(b, "%s %s", @@ -1323,89 +1459,21 @@ } int -sshkey_check_rsa_length(const struct sshkey *k, int min_size) -{ -#ifdef WITH_OPENSSL - const BIGNUM *rsa_n; - int nbits; - - if (k == NULL || k->rsa == NULL || - (k->type != KEY_RSA && k->type != KEY_RSA_CERT)) - return 0; - RSA_get0_key(k->rsa, &rsa_n, NULL, NULL); - nbits = BN_num_bits(rsa_n); - if (nbits < SSH_RSA_MINIMUM_MODULUS_SIZE || - (min_size > 0 && nbits < min_size)) - return SSH_ERR_KEY_LENGTH; -#endif /* WITH_OPENSSL */ - return 0; -} - -#ifdef WITH_OPENSSL -# ifdef OPENSSL_HAS_ECC -int -sshkey_ecdsa_key_to_nid(EC_KEY *k) -{ - EC_GROUP *eg; - int nids[] = { - NID_X9_62_prime256v1, - NID_secp384r1, -# ifdef OPENSSL_HAS_NISTP521 - NID_secp521r1, -# endif /* OPENSSL_HAS_NISTP521 */ - -1 - }; - int nid; - u_int i; - const EC_GROUP *g = EC_KEY_get0_group(k); - - /* - * The group may be stored in a ASN.1 encoded private key in one of two - * ways: as a "named group", which is reconstituted by ASN.1 object ID - * or explicit group parameters encoded into the key blob. Only the - * "named group" case sets the group NID for us, but we can figure - * it out for the other case by comparing against all the groups that - * are supported. - */ - if ((nid = EC_GROUP_get_curve_name(g)) > 0) - return nid; - for (i = 0; nids[i] != -1; i++) { - if ((eg = EC_GROUP_new_by_curve_name(nids[i])) == NULL) - return -1; - if (EC_GROUP_cmp(g, eg, NULL) == 0) - break; - EC_GROUP_free(eg); - } - if (nids[i] != -1) { - /* Use the group with the NID attached */ - EC_GROUP_set_asn1_flag(eg, OPENSSL_EC_NAMED_CURVE); - if (EC_KEY_set_group(k, eg) != 1) { - EC_GROUP_free(eg); - return -1; - } - } - return nids[i]; -} -# endif /* OPENSSL_HAS_ECC */ -#endif /* WITH_OPENSSL */ - -int sshkey_generate(int type, u_int bits, struct sshkey **keyp) { struct sshkey *k; int ret = SSH_ERR_INTERNAL_ERROR; const struct sshkey_impl *impl; - if (keyp == NULL || sshkey_type_is_cert(type)) + if (keyp == NULL || type != sshkey_type_plain(type)) return SSH_ERR_INVALID_ARGUMENT; *keyp = NULL; if ((impl = sshkey_impl_from_type(type)) == NULL) return SSH_ERR_KEY_TYPE_UNKNOWN; if (impl->funcs->generate == NULL) return SSH_ERR_FEATURE_UNSUPPORTED; - if ((k = sshkey_new(KEY_UNSPEC)) == NULL) + if ((k = sshkey_new(type)) == NULL) return SSH_ERR_ALLOC_FAIL; - k->type = type; if ((ret = impl->funcs->generate(k, bits)) != 0) { sshkey_free(k); return ret; @@ -1486,32 +1554,24 @@ } int -sshkey_copy_public_sk(const struct sshkey *from, struct sshkey *to) -{ - /* Append security-key application string */ - if ((to->sk_application = strdup(from->sk_application)) == NULL) - return SSH_ERR_ALLOC_FAIL; - return 0; -} - -int sshkey_from_private(const struct sshkey *k, struct sshkey **pkp) { - struct sshkey *n = NULL; - int r = SSH_ERR_INTERNAL_ERROR; + struct sshkey *n; + int r; const struct sshkey_impl *impl; *pkp = NULL; if ((impl = sshkey_impl_from_key(k)) == NULL) return SSH_ERR_KEY_TYPE_UNKNOWN; - if ((n = sshkey_new(k->type)) == NULL) { - r = SSH_ERR_ALLOC_FAIL; - goto out; - } + if ((n = sshkey_new(k->type)) == NULL) + return SSH_ERR_ALLOC_FAIL; if ((r = impl->funcs->copy_public(k, n)) != 0) goto out; if (sshkey_is_cert(k) && (r = sshkey_cert_copy(k, n)) != 0) goto out; + + x509key_copy_identity(k, n); + /* success */ *pkp = n; n = NULL; @@ -1521,6 +1581,32 @@ return r; } +/* Check deterministic padding after private key */ +static int +private2_check_padding(struct sshbuf *decrypted) +{ + u_char pad; + size_t i; + int r; + + i = 0; + while (sshbuf_len(decrypted)) { + if ((r = sshbuf_get_u8(decrypted, &pad)) != 0) + goto out; + if (pad != (++i & 0xff)) { + r = SSH_ERR_INVALID_FORMAT; + goto out; + } + } + /* success */ + r = 0; + out: + explicit_bzero(&pad, sizeof(pad)); + explicit_bzero(&i, sizeof(i)); + return r; +} + +#ifdef USE_SSHKEY_SHIELDING int sshkey_is_shielded(struct sshkey *k) { @@ -1621,9 +1707,6 @@ enc = prekey = NULL; /* transferred */ enclen = 0; - /* preserve key fields that are required for correct operation */ - k->sk_flags = kswap->sk_flags; - /* success */ r = 0; @@ -1639,31 +1722,6 @@ return r; } -/* Check deterministic padding after private key */ -static int -private2_check_padding(struct sshbuf *decrypted) -{ - u_char pad; - size_t i; - int r; - - i = 0; - while (sshbuf_len(decrypted)) { - if ((r = sshbuf_get_u8(decrypted, &pad)) != 0) - goto out; - if (pad != (++i & 0xff)) { - r = SSH_ERR_INVALID_FORMAT; - goto out; - } - } - /* success */ - r = 0; - out: - explicit_bzero(&pad, sizeof(pad)); - explicit_bzero(&i, sizeof(i)); - return r; -} - int sshkey_unshield_private(struct sshkey *k) { @@ -1752,6 +1810,7 @@ sshbuf_free(prvbuf); return r; } +#endif /*def USE_SSHKEY_SHIELDING*/ static int cert_parse(struct sshbuf *b, struct sshkey *key, struct sshbuf *certbuf) @@ -1861,11 +1920,14 @@ ret = SSH_ERR_KEY_CERT_INVALID_SIGN_KEY; goto out; } - if ((ret = sshkey_verify(key->cert->signature_key, sig, slen, - sshbuf_ptr(key->cert->certblob), signed_len, NULL, 0, NULL)) != 0) +{ ssh_compat ctx_compat = { 0, 0 }; + ssh_verify_ctx ctx = { NULL, key->cert->signature_key, &ctx_compat }; + + if ((ret = sshkey_verify(&ctx, sig, slen, + sshbuf_ptr(key->cert->certblob), signed_len)) != 0) goto out; - if ((ret = sshkey_get_sigtype(sig, slen, - &key->cert->signature_type)) != 0) +} + if ((ret = sshkey_sigtype(sig, slen, &key->cert->signature_type)) != 0) goto out; /* Success */ @@ -1879,15 +1941,25 @@ return ret; } + int -sshkey_deserialize_sk(struct sshbuf *b, struct sshkey *key) +sshkey_check_length(const struct sshkey *k) { - /* Parse additional security-key application string */ - if (sshbuf_get_cstring(b, &key->sk_application, NULL) != 0) - return SSH_ERR_INVALID_FORMAT; +#ifdef WITH_OPENSSL + /* NOTE RSA/DSA keys validates only length */ + switch(sshkey_type_plain(k->type)) { + case KEY_RSA: + return sshkey_validate_public_rsa(k); + case KEY_DSA: + return sshkey_validate_public_dsa(k); + } +#else + UNUSED(k); +#endif return 0; } + static int sshkey_from_blob_internal(struct sshbuf *b, struct sshkey **keyp, int allow_cert) @@ -1896,13 +1968,13 @@ char *ktype = NULL; struct sshkey *key = NULL; struct sshbuf *copy; - const struct sshkey_impl *impl; #ifdef DEBUG_PK /* XXX */ sshbuf_dump(b, stderr); #endif if (keyp != NULL) *keyp = NULL; + if ((copy = sshbuf_fromb(b)) == NULL) { ret = SSH_ERR_ALLOC_FAIL; goto out; @@ -1913,29 +1985,31 @@ } type = sshkey_type_from_name(ktype); + debug3_f("ktype=%.100s", ktype); if (!allow_cert && sshkey_type_is_cert(type)) { ret = SSH_ERR_KEY_CERT_INVALID_SIGN_KEY; goto out; } - if ((impl = sshkey_impl_from_type(type)) == NULL) { - ret = SSH_ERR_KEY_TYPE_UNKNOWN; - goto out; - } if ((key = sshkey_new(type)) == NULL) { ret = SSH_ERR_ALLOC_FAIL; goto out; } + /* skip nonce that preceeds all custom certificates */ if (sshkey_type_is_cert(type)) { - /* Skip nonce that preceeds all certificates */ if (sshbuf_get_string_direct(b, NULL, NULL) != 0) { ret = SSH_ERR_INVALID_FORMAT; goto out; } } - if ((ret = impl->funcs->deserialize_public(ktype, b, key)) != 0) +{ const struct sshkey_impl *impl = sshkey_impl_from_type(type); + if (impl == NULL) { + ret = SSH_ERR_KEY_TYPE_UNKNOWN; goto out; - - /* Parse certificate potion */ + } + ret = impl->funcs->deserialize_public(ktype, b, key); + if (ret != SSH_ERR_SUCCESS) goto out; +} + /* parse custom certificate portion */ if (sshkey_is_cert(key) && (ret = cert_parse(b, key, copy)) != 0) goto out; @@ -1988,7 +2062,7 @@ } int -sshkey_get_sigtype(const u_char *sig, size_t siglen, char **sigtypep) +sshkey_sigtype(const u_char *sig, size_t siglen, char **sigtypep) { int r; struct sshbuf *b = NULL; @@ -2036,22 +2110,20 @@ /* * Returns the expected signature algorithm for a given public key algorithm. */ -const char * +static const char * sshkey_sigalg_by_name(const char *name) { - const struct sshkey_impl *impl; - int i; + const struct sshkey_impl *const* p; - for (i = 0; keyimpls[i] != NULL; i++) { - impl = keyimpls[i]; - if (strcmp(impl->name, name) != 0) + for (p = keyimpls; *p != NULL; p++) { + if (strcmp((*p)->name, name) != 0) continue; - if (impl->sigalg != NULL) - return impl->sigalg; - if (!impl->cert) - return impl->name; + if ((*p)->sigalg != NULL) + return (*p)->sigalg; + if (!(*p)->cert) + return (*p)->name; return sshkey_ssh_name_from_type_nid( - sshkey_type_plain(impl->type), impl->nid); + sshkey_type_plain((*p)->type), (*p)->nid); } return NULL; } @@ -2072,7 +2144,7 @@ return 0; if ((expected_alg = sshkey_sigalg_by_name(requested_alg)) == NULL) return SSH_ERR_INVALID_ARGUMENT; - if ((r = sshkey_get_sigtype(sig, siglen, &sigtype)) != 0) + if ((r = sshkey_sigtype(sig, siglen, &sigtype)) != 0) return r; r = strcmp(expected_alg, sigtype) == 0; free(sigtype); @@ -2080,38 +2152,65 @@ } int -sshkey_sign(struct sshkey *key, +ssh_encode_signature(u_char **sigp, size_t *lenp, + const u_char *signame, const u_char *sigret, size_t siglen +) { + int r; + struct sshbuf *buf; + + debug3_f("signame=%s", signame); + + buf = sshbuf_new(); + if (buf == NULL) + return SSH_ERR_ALLOC_FAIL; + + r = sshbuf_put_cstring(buf, signame); + if (r != 0) goto done; + + r = sshbuf_put_string(buf, sigret, siglen); + if (r != 0) goto done; + +{ size_t len = sshbuf_len(buf); + if (sigp != NULL) { + *sigp = xmalloc(len); /*fatal on error*/ + memcpy(*sigp, sshbuf_ptr(buf), len); + } + if (lenp != NULL) + *lenp = len; +} + +done: + sshbuf_free(buf); + + return r; +} + +int +sshkey_sign(const ssh_sign_ctx *ctx, u_char **sigp, size_t *lenp, - const u_char *data, size_t datalen, - const char *alg, const char *sk_provider, const char *sk_pin, u_int compat) + const u_char *data, size_t dlen) { - int was_shielded = sshkey_is_shielded(key); - int r2, r = SSH_ERR_INTERNAL_ERROR; + struct sshkey *key = ctx->key; + int was_shielded; + int r; const struct sshkey_impl *impl; if (sigp != NULL) *sigp = NULL; if (lenp != NULL) *lenp = 0; - if (datalen > SSH_KEY_MAX_SIGN_DATA_SIZE) + if (dlen > SSH_KEY_MAX_SIGN_DATA_SIZE) return SSH_ERR_INVALID_ARGUMENT; if ((impl = sshkey_impl_from_key(key)) == NULL) return SSH_ERR_KEY_TYPE_UNKNOWN; + was_shielded = sshkey_is_shielded(key); if ((r = sshkey_unshield_private(key)) != 0) return r; - if (sshkey_is_sk(key)) { - r = sshsk_sign(sk_provider, key, sigp, lenp, data, - datalen, compat, sk_pin); - } else { - if (impl->funcs->sign == NULL) - r = SSH_ERR_SIGN_ALG_UNSUPPORTED; - else { - r = impl->funcs->sign(key, sigp, lenp, data, datalen, - alg, sk_provider, sk_pin, compat); - } + r = impl->funcs->sign(ctx, sigp, lenp, data, dlen); + if (was_shielded) { + int r2 = sshkey_shield_private(key); + if (r == 0) r = r2; } - if (was_shielded && (r2 = sshkey_shield_private(key)) != 0) - return r2; return r; } @@ -2120,21 +2219,18 @@ * If "alg" specified, then the signature must use that algorithm. */ int -sshkey_verify(const struct sshkey *key, +sshkey_verify(const ssh_verify_ctx *ctx, const u_char *sig, size_t siglen, - const u_char *data, size_t dlen, const char *alg, u_int compat, - struct sshkey_sig_details **detailsp) + const u_char *data, size_t dlen) { + struct sshkey *key = ctx->key; const struct sshkey_impl *impl; - if (detailsp != NULL) - *detailsp = NULL; if (siglen == 0 || dlen > SSH_KEY_MAX_SIGN_DATA_SIZE) return SSH_ERR_INVALID_ARGUMENT; if ((impl = sshkey_impl_from_key(key)) == NULL) return SSH_ERR_KEY_TYPE_UNKNOWN; - return impl->funcs->verify(key, sig, siglen, data, dlen, - alg, compat, detailsp); + return impl->funcs->verify(ctx, sig, siglen, data, dlen); } /* Convert a plain key to their _CERT equivalent */ @@ -2185,7 +2281,7 @@ if (!sshkey_type_is_valid_ca(ca->type)) return SSH_ERR_KEY_CERT_INVALID_SIGN_KEY; if ((impl = sshkey_impl_from_key(k)) == NULL) - return SSH_ERR_INTERNAL_ERROR; + return SSH_ERR_INVALID_ARGUMENT; /* * If no alg specified as argument but a signature_type was set, @@ -2202,7 +2298,11 @@ * using a RSA key, then default to a good signature algorithm. */ if (alg == NULL && ca->type == KEY_RSA) - alg = "rsa-sha2-512"; +#ifdef HAVE_EVP_SHA256 + alg = "rsa-sha2-256"; +#else + alg = "ssh-rsa"; +#endif if ((ret = sshkey_to_blob(ca, &ca_blob, &ca_len)) != 0) return SSH_ERR_KEY_CERT_INVALID_SIGN_KEY; @@ -2251,7 +2351,7 @@ sshbuf_len(cert), alg, sk_provider, sk_pin, 0, signer_ctx)) != 0) goto out; /* Check and update signature_type against what was actually used */ - if ((ret = sshkey_get_sigtype(sig_blob, sig_len, &sigtype)) != 0) + if ((ret = sshkey_sigtype(sig_blob, sig_len, &sigtype)) != 0) goto out; if (alg != NULL && strcmp(alg, sigtype) != 0) { ret = SSH_ERR_SIGN_ALG_UNSUPPORTED; @@ -2275,16 +2375,18 @@ return ret; } -static int +static int /* TODO: use ssh_sign_ctx */ default_key_sign(struct sshkey *key, u_char **sigp, size_t *lenp, const u_char *data, size_t datalen, const char *alg, const char *sk_provider, const char *sk_pin, - u_int compat, void *ctx) + u_int compat, void *reserved) { - if (ctx != NULL) + ssh_compat ctx_compat = { compat, 0 }; + ssh_sign_ctx ctx = { alg, key, &ctx_compat, sk_provider, sk_pin }; + + if (reserved != NULL) return SSH_ERR_INVALID_ARGUMENT; - return sshkey_sign(key, sigp, lenp, data, datalen, alg, - sk_provider, sk_pin, compat); + return sshkey_sign(&ctx, sigp, lenp, data, datalen); } int @@ -2418,49 +2520,49 @@ return strlcpy(s, ret, l); } -/* Common serialization for FIDO private keys */ -int -sshkey_serialize_private_sk(const struct sshkey *key, struct sshbuf *b) -{ - int r; - - if ((r = sshbuf_put_cstring(b, key->sk_application)) != 0 || - (r = sshbuf_put_u8(b, key->sk_flags)) != 0 || - (r = sshbuf_put_stringb(b, key->sk_key_handle)) != 0 || - (r = sshbuf_put_stringb(b, key->sk_reserved)) != 0) - return r; - - return 0; -} - int sshkey_private_serialize_opt(struct sshkey *key, struct sshbuf *buf, enum sshkey_serialize_rep opts) { - int r = SSH_ERR_INTERNAL_ERROR; - int was_shielded = sshkey_is_shielded(key); - struct sshbuf *b = NULL; const struct sshkey_impl *impl; + const char *pkalg = NULL; + int r; + int was_shielded; + struct sshbuf *b; - if ((impl = sshkey_impl_from_key(key)) == NULL) - return SSH_ERR_INTERNAL_ERROR; - if ((r = sshkey_unshield_private(key)) != 0) - return r; + impl = sshkey_impl_from_key(key); + if (impl == NULL) + return SSH_ERR_INVALID_ARGUMENT; + if (sshkey_type_is_cert(key->type)) { + if (key->cert == NULL || + sshbuf_len(key->cert->certblob) == 0) + return SSH_ERR_INVALID_ARGUMENT; + } +#ifdef WITH_XMSS + if (sshkey_type_plain(key->type) == KEY_XMSS) { + if (key->xmss_name == NULL) + return SSH_ERR_INVALID_ARGUMENT; + } +#endif /* WITH_XMSS */ if ((b = sshbuf_new()) == NULL) return SSH_ERR_ALLOC_FAIL; - if ((r = sshbuf_put_cstring(b, sshkey_ssh_name(key))) != 0) + + was_shielded = sshkey_is_shielded(key); + if ((r = sshkey_unshield_private(key)) != 0) goto out; - if (sshkey_is_cert(key)) { - if (key->cert == NULL || - sshbuf_len(key->cert->certblob) == 0) { - r = SSH_ERR_INVALID_ARGUMENT; - goto out; - } - if ((r = sshbuf_put_stringb(b, key->cert->certblob)) != 0) - goto out; - } - if ((r = impl->funcs->serialize_private(key, b, opts)) != 0) + pkalg = sshkey_ssh_name(key); + if ((r = sshbuf_put_cstring(b, pkalg)) != 0) goto out; + if (sshkey_type_is_cert(key->type)) { + r = sshbuf_put_stringb(b, key->cert->certblob); + if (r != 0) goto out; + } + + r = impl->funcs->serialize_private(key, b, opts); + if (r != SSH_ERR_SUCCESS) goto out; + + r = X509key_encode_identity(pkalg, key, b); + if (r != SSH_ERR_SUCCESS) goto out; /* * success (but we still need to append the output to buf after @@ -2468,8 +2570,10 @@ */ r = 0; out: - if (was_shielded) - r = sshkey_shield_private(key); + if (was_shielded) { + int r2 = sshkey_shield_private(key); + if (r == 0) r = r2; + } if (r == 0) r = sshbuf_putb(buf, b); sshbuf_free(b); @@ -2484,31 +2588,10 @@ SSHKEY_SERIALIZE_DEFAULT); } -/* Shared deserialization of FIDO private key components */ -int -sshkey_private_deserialize_sk(struct sshbuf *buf, struct sshkey *k) -{ - int r; - - if ((k->sk_key_handle = sshbuf_new()) == NULL || - (k->sk_reserved = sshbuf_new()) == NULL) - return SSH_ERR_ALLOC_FAIL; - if ((r = sshbuf_get_cstring(buf, &k->sk_application, NULL)) != 0 || - (r = sshbuf_get_u8(buf, &k->sk_flags)) != 0 || - (r = sshbuf_get_stringb(buf, k->sk_key_handle)) != 0 || - (r = sshbuf_get_stringb(buf, k->sk_reserved)) != 0) - return r; - - return 0; -} - int sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp) { - const struct sshkey_impl *impl; char *tname = NULL; - char *expect_sk_application = NULL; - u_char *expect_ed25519_pk = NULL; struct sshkey *k = NULL; int type, r = SSH_ERR_INTERNAL_ERROR; @@ -2535,36 +2618,22 @@ r = SSH_ERR_KEY_CERT_MISMATCH; goto out; } - /* - * Several fields are redundant between certificate and - * private key body, we require these to match. - */ - expect_sk_application = k->sk_application; - expect_ed25519_pk = k->ed25519_pk; - k->sk_application = NULL; - k->ed25519_pk = NULL; - /* XXX xmss too or refactor */ } else { if ((k = sshkey_new(type)) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } } - if ((impl = sshkey_impl_from_type(type)) == NULL) { - r = SSH_ERR_INTERNAL_ERROR; - goto out; - } - if ((r = impl->funcs->deserialize_private(tname, buf, k)) != 0) - goto out; - - /* XXX xmss too or refactor */ - if ((expect_sk_application != NULL && (k->sk_application == NULL || - strcmp(expect_sk_application, k->sk_application) != 0)) || - (expect_ed25519_pk != NULL && (k->ed25519_pk == NULL || - memcmp(expect_ed25519_pk, k->ed25519_pk, ED25519_PK_SZ) != 0))) { - r = SSH_ERR_KEY_CERT_MISMATCH; +{ const struct sshkey_impl *impl = sshkey_impl_from_type(type); + if (impl == NULL) { + r = SSH_ERR_KEY_TYPE_UNKNOWN; goto out; } + r = impl->funcs->deserialize_private(tname, buf, k); + if (r != SSH_ERR_SUCCESS) goto out; +} + r = X509key_decode_identity(tname, buf, k); + if (r != SSH_ERR_SUCCESS) goto out; /* success */ r = 0; if (kp != NULL) { @@ -2574,171 +2643,9 @@ out: free(tname); sshkey_free(k); - free(expect_sk_application); - free(expect_ed25519_pk); return r; } -#if defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC) -int -sshkey_ec_validate_public(const EC_GROUP *group, const EC_POINT *public) -{ - EC_POINT *nq = NULL; - BIGNUM *order = NULL, *x = NULL, *y = NULL, *tmp = NULL; - int ret = SSH_ERR_KEY_INVALID_EC_VALUE; - - /* - * NB. This assumes OpenSSL has already verified that the public - * point lies on the curve. This is done by EC_POINT_oct2point() - * implicitly calling EC_POINT_is_on_curve(). If this code is ever - * reachable with public points not unmarshalled using - * EC_POINT_oct2point then the caller will need to explicitly check. - */ - - /* - * We shouldn't ever hit this case because bignum_get_ecpoint() - * refuses to load GF2m points. - */ - if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) != - NID_X9_62_prime_field) - goto out; - - /* Q != infinity */ - if (EC_POINT_is_at_infinity(group, public)) - goto out; - - if ((x = BN_new()) == NULL || - (y = BN_new()) == NULL || - (order = BN_new()) == NULL || - (tmp = BN_new()) == NULL) { - ret = SSH_ERR_ALLOC_FAIL; - goto out; - } - - /* log2(x) > log2(order)/2, log2(y) > log2(order)/2 */ - if (EC_GROUP_get_order(group, order, NULL) != 1 || - EC_POINT_get_affine_coordinates_GFp(group, public, - x, y, NULL) != 1) { - ret = SSH_ERR_LIBCRYPTO_ERROR; - goto out; - } - if (BN_num_bits(x) <= BN_num_bits(order) / 2 || - BN_num_bits(y) <= BN_num_bits(order) / 2) - goto out; - - /* nQ == infinity (n == order of subgroup) */ - if ((nq = EC_POINT_new(group)) == NULL) { - ret = SSH_ERR_ALLOC_FAIL; - goto out; - } - if (EC_POINT_mul(group, nq, NULL, public, order, NULL) != 1) { - ret = SSH_ERR_LIBCRYPTO_ERROR; - goto out; - } - if (EC_POINT_is_at_infinity(group, nq) != 1) - goto out; - - /* x < order - 1, y < order - 1 */ - if (!BN_sub(tmp, order, BN_value_one())) { - ret = SSH_ERR_LIBCRYPTO_ERROR; - goto out; - } - if (BN_cmp(x, tmp) >= 0 || BN_cmp(y, tmp) >= 0) - goto out; - ret = 0; - out: - BN_clear_free(x); - BN_clear_free(y); - BN_clear_free(order); - BN_clear_free(tmp); - EC_POINT_free(nq); - return ret; -} - -int -sshkey_ec_validate_private(const EC_KEY *key) -{ - BIGNUM *order = NULL, *tmp = NULL; - int ret = SSH_ERR_KEY_INVALID_EC_VALUE; - - if ((order = BN_new()) == NULL || (tmp = BN_new()) == NULL) { - ret = SSH_ERR_ALLOC_FAIL; - goto out; - } - - /* log2(private) > log2(order)/2 */ - if (EC_GROUP_get_order(EC_KEY_get0_group(key), order, NULL) != 1) { - ret = SSH_ERR_LIBCRYPTO_ERROR; - goto out; - } - if (BN_num_bits(EC_KEY_get0_private_key(key)) <= - BN_num_bits(order) / 2) - goto out; - - /* private < order - 1 */ - if (!BN_sub(tmp, order, BN_value_one())) { - ret = SSH_ERR_LIBCRYPTO_ERROR; - goto out; - } - if (BN_cmp(EC_KEY_get0_private_key(key), tmp) >= 0) - goto out; - ret = 0; - out: - BN_clear_free(order); - BN_clear_free(tmp); - return ret; -} - -void -sshkey_dump_ec_point(const EC_GROUP *group, const EC_POINT *point) -{ - BIGNUM *x = NULL, *y = NULL; - - if (point == NULL) { - fputs("point=(NULL)\n", stderr); - return; - } - if ((x = BN_new()) == NULL || (y = BN_new()) == NULL) { - fprintf(stderr, "%s: BN_new failed\n", __func__); - goto out; - } - if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) != - NID_X9_62_prime_field) { - fprintf(stderr, "%s: group is not a prime field\n", __func__); - goto out; - } - if (EC_POINT_get_affine_coordinates_GFp(group, point, - x, y, NULL) != 1) { - fprintf(stderr, "%s: EC_POINT_get_affine_coordinates_GFp\n", - __func__); - goto out; - } - fputs("x=", stderr); - BN_print_fp(stderr, x); - fputs("\ny=", stderr); - BN_print_fp(stderr, y); - fputs("\n", stderr); - out: - BN_clear_free(x); - BN_clear_free(y); -} - -void -sshkey_dump_ec_key(const EC_KEY *key) -{ - const BIGNUM *exponent; - - sshkey_dump_ec_point(EC_KEY_get0_group(key), - EC_KEY_get0_public_key(key)); - fputs("exponent=", stderr); - if ((exponent = EC_KEY_get0_private_key(key)) == NULL) - fputs("(NULL)", stderr); - else - BN_print_fp(stderr, EC_KEY_get0_private_key(key)); - fputs("\n", stderr); -} -#endif /* WITH_OPENSSL && OPENSSL_HAS_ECC */ - static int sshkey_private_to_blob2(struct sshkey *prv, struct sshbuf *blob, const char *passphrase, const char *comment, const char *ciphername, @@ -2843,7 +2750,7 @@ sshbuf_reset(blob); - /* assemble uuencoded key */ + /* assemble base64-encoded key */ if ((r = sshbuf_put(blob, MARK_BEGIN, MARK_BEGIN_LEN)) != 0 || (r = sshbuf_dtob64(encoded, blob, 1)) != 0 || (r = sshbuf_put(blob, MARK_END, MARK_END_LEN)) != 0) @@ -2921,7 +2828,7 @@ } /* decode base64 */ - if ((r = sshbuf_b64tod(decoded, (char *)sshbuf_ptr(encoded))) != 0) + if ((r = sshbuf_b64tod(decoded, sshbuf_mutable_ptr(encoded))) != 0) goto out; /* check magic */ @@ -3074,21 +2981,17 @@ free(ciphername); free(kdfname); sshkey_free(pubkey); - if (salt != NULL) { - explicit_bzero(salt, slen); - free(salt); - } - if (key != NULL) { - explicit_bzero(key, keylen + ivlen); - free(key); - } + if (salt != NULL) + freezero(salt, slen); + if (key != NULL) + freezero(key, keylen + ivlen); sshbuf_free(kdf); sshbuf_free(decrypted); return r; } static int -sshkey_parse_private2(struct sshbuf *blob, int type, const char *passphrase, +sshkey_parse_private2(struct sshbuf *blob, const char *passphrase, struct sshkey **keyp, char **commentp) { char *comment = NULL; @@ -3107,12 +3010,6 @@ &decrypted, &pubkey)) != 0) goto out; - if (type != KEY_UNSPEC && - sshkey_type_plain(type) != sshkey_type_plain(pubkey->type)) { - r = SSH_ERR_KEY_TYPE_MISMATCH; - goto out; - } - /* Load the private key and comment */ if ((r = sshkey_private_deserialize(decrypted, &k)) != 0 || (r = sshbuf_get_cstring(decrypted, &comment, NULL)) != 0) @@ -3148,7 +3045,7 @@ } static int -sshkey_parse_private2_pubkey(struct sshbuf *blob, int type, +sshkey_parse_private2_pubkey(struct sshbuf *blob, struct sshkey **keyp) { int r = SSH_ERR_INTERNAL_ERROR; @@ -3179,12 +3076,6 @@ if ((r = sshkey_froms(decoded, &pubkey)) != 0) goto out; - if (type != KEY_UNSPEC && - sshkey_type_plain(type) != sshkey_type_plain(pubkey->type)) { - r = SSH_ERR_KEY_TYPE_MISMATCH; - goto out; - } - /* success */ r = 0; if (keyp != NULL) { @@ -3198,78 +3089,29 @@ } #ifdef WITH_OPENSSL -/* convert SSH v2 key to PEM or PKCS#8 format */ static int -sshkey_private_to_blob_pem_pkcs8(struct sshkey *key, struct sshbuf *buf, - int format, const char *_passphrase, const char *comment) +sshkey_private_pem_to_blob(struct sshkey *key, struct sshbuf *buf, + const char *passphrase, int format) { int was_shielded = sshkey_is_shielded(key); - int success, r; - int blen, len = strlen(_passphrase); - u_char *passphrase = (len > 0) ? (u_char *)_passphrase : NULL; - const EVP_CIPHER *cipher = (len > 0) ? EVP_aes_128_cbc() : NULL; + int r; + int blen; char *bptr; - BIO *bio = NULL; + BIO *bio; struct sshbuf *blob; - EVP_PKEY *pkey = NULL; - if (len > 0 && len <= 4) - return SSH_ERR_PASSPHRASE_TOO_SHORT; if ((blob = sshbuf_new()) == NULL) return SSH_ERR_ALLOC_FAIL; if ((bio = BIO_new(BIO_s_mem())) == NULL) { - r = SSH_ERR_ALLOC_FAIL; - goto out; - } - if (format == SSHKEY_PRIVATE_PKCS8 && (pkey = EVP_PKEY_new()) == NULL) { - r = SSH_ERR_ALLOC_FAIL; - goto out; + sshbuf_free(blob); + return SSH_ERR_ALLOC_FAIL; } if ((r = sshkey_unshield_private(key)) != 0) goto out; - switch (key->type) { - case KEY_DSA: - if (format == SSHKEY_PRIVATE_PEM) { - success = PEM_write_bio_DSAPrivateKey(bio, key->dsa, - cipher, passphrase, len, NULL, NULL); - } else { - success = EVP_PKEY_set1_DSA(pkey, key->dsa); - } - break; -#ifdef OPENSSL_HAS_ECC - case KEY_ECDSA: - if (format == SSHKEY_PRIVATE_PEM) { - success = PEM_write_bio_ECPrivateKey(bio, key->ecdsa, - cipher, passphrase, len, NULL, NULL); - } else { - success = EVP_PKEY_set1_EC_KEY(pkey, key->ecdsa); - } - break; -#endif - case KEY_RSA: - if (format == SSHKEY_PRIVATE_PEM) { - success = PEM_write_bio_RSAPrivateKey(bio, key->rsa, - cipher, passphrase, len, NULL, NULL); - } else { - success = EVP_PKEY_set1_RSA(pkey, key->rsa); - } - break; - default: - success = 0; - break; - } - if (success == 0) { - r = SSH_ERR_LIBCRYPTO_ERROR; - goto out; - } - if (format == SSHKEY_PRIVATE_PKCS8) { - if ((success = PEM_write_bio_PrivateKey(bio, pkey, cipher, - passphrase, len, NULL, NULL)) == 0) { - r = SSH_ERR_LIBCRYPTO_ERROR; - goto out; - } - } + r = sshkey_private_to_bio(key, bio, passphrase, format); + if (r != 0) goto out; + if ((blen = BIO_get_mem_data(bio, &bptr)) <= 0) { r = SSH_ERR_INTERNAL_ERROR; goto out; @@ -3278,13 +3120,14 @@ goto out; r = 0; out: - if (was_shielded) - r = sshkey_shield_private(key); + if (was_shielded) { + int r2 = sshkey_shield_private(key); + if (r == 0) r = r2; + } if (r == 0) r = sshbuf_putb(buf, blob); - - EVP_PKEY_free(pkey); sshbuf_free(blob); + BIO_free(bio); return r; } @@ -3296,125 +3139,41 @@ const char *passphrase, const char *comment, int format, const char *openssh_format_cipher, int openssh_format_rounds) { + /* never use proprietary format for X.509 keys */ + if (sshkey_is_x509(key)) { + if (format == SSHKEY_PRIVATE_OPENSSH) + format = SSHKEY_PRIVATE_PKCS8; + } + switch (key->type) { +#ifdef OPENSSL_HAS_ED25519 + case KEY_ED25519: +#endif /*def OPENSSL_HAS_ED25519*/ #ifdef WITH_OPENSSL case KEY_DSA: case KEY_ECDSA: case KEY_RSA: - break; /* see below */ + if (format != SSHKEY_PRIVATE_OPENSSH) + return sshkey_private_pem_to_blob(key, blob, + passphrase, format); #endif /* WITH_OPENSSL */ + /* FALLTHROUGH */ +#ifndef OPENSSL_HAS_ED25519 case KEY_ED25519: - case KEY_ED25519_SK: +#endif /*ndef OPENSSL_HAS_ED25519*/ #ifdef WITH_XMSS case KEY_XMSS: #endif /* WITH_XMSS */ -#ifdef WITH_OPENSSL - case KEY_ECDSA_SK: -#endif /* WITH_OPENSSL */ return sshkey_private_to_blob2(key, blob, passphrase, comment, openssh_format_cipher, openssh_format_rounds); default: return SSH_ERR_KEY_TYPE_UNKNOWN; } - -#ifdef WITH_OPENSSL - switch (format) { - case SSHKEY_PRIVATE_OPENSSH: - return sshkey_private_to_blob2(key, blob, passphrase, - comment, openssh_format_cipher, openssh_format_rounds); - case SSHKEY_PRIVATE_PEM: - case SSHKEY_PRIVATE_PKCS8: - return sshkey_private_to_blob_pem_pkcs8(key, blob, - format, passphrase, comment); - default: - return SSH_ERR_INVALID_ARGUMENT; - } -#endif /* WITH_OPENSSL */ } #ifdef WITH_OPENSSL static int -translate_libcrypto_error(unsigned long pem_err) -{ - int pem_reason = ERR_GET_REASON(pem_err); - - switch (ERR_GET_LIB(pem_err)) { - case ERR_LIB_PEM: - switch (pem_reason) { - case PEM_R_BAD_PASSWORD_READ: -#ifdef PEM_R_PROBLEMS_GETTING_PASSWORD - case PEM_R_PROBLEMS_GETTING_PASSWORD: -#endif -#ifdef PEM_R_BAD_DECRYPT - case PEM_R_BAD_DECRYPT: -#endif - return SSH_ERR_KEY_WRONG_PASSPHRASE; - default: - return SSH_ERR_INVALID_FORMAT; - } - case ERR_LIB_EVP: - switch (pem_reason) { -#ifdef EVP_R_BAD_DECRYPT - case EVP_R_BAD_DECRYPT: - return SSH_ERR_KEY_WRONG_PASSPHRASE; -#endif -#ifdef EVP_R_BN_DECODE_ERROR - case EVP_R_BN_DECODE_ERROR: -#endif - case EVP_R_DECODE_ERROR: -#ifdef EVP_R_PRIVATE_KEY_DECODE_ERROR - case EVP_R_PRIVATE_KEY_DECODE_ERROR: -#endif - return SSH_ERR_INVALID_FORMAT; - default: - return SSH_ERR_LIBCRYPTO_ERROR; - } - case ERR_LIB_ASN1: - return SSH_ERR_INVALID_FORMAT; - } - return SSH_ERR_LIBCRYPTO_ERROR; -} - -static void -clear_libcrypto_errors(void) -{ - while (ERR_get_error() != 0) - ; -} - -/* - * Translate OpenSSL error codes to determine whether - * passphrase is required/incorrect. - */ -static int -convert_libcrypto_error(void) -{ - /* - * Some password errors are reported at the beginning - * of the error queue. - */ - if (translate_libcrypto_error(ERR_peek_error()) == - SSH_ERR_KEY_WRONG_PASSPHRASE) - return SSH_ERR_KEY_WRONG_PASSPHRASE; - return translate_libcrypto_error(ERR_peek_last_error()); -} - -static int -pem_passphrase_cb(char *buf, int size, int rwflag, void *u) -{ - char *p = (char *)u; - size_t len; - - if (p == NULL || (len = strlen(p)) == 0) - return -1; - if (size < 0 || len > (size_t)size) - return -1; - memcpy(buf, p, len); - return (int)len; -} - -static int -sshkey_parse_private_pem_fileblob(struct sshbuf *blob, int type, +sshkey_parse_private_pem_fileblob(struct sshbuf *blob, const char *passphrase, struct sshkey **keyp) { EVP_PKEY *pk = NULL; @@ -3425,84 +3184,33 @@ if (keyp != NULL) *keyp = NULL; - if ((bio = BIO_new(BIO_s_mem())) == NULL || sshbuf_len(blob) > INT_MAX) + debug3("read PEM private key begin"); + if (sshbuf_len(blob) == 0 || sshbuf_len(blob) > INT_MAX) + return SSH_ERR_INVALID_ARGUMENT; + bio = BIO_new_mem_buf(sshbuf_mutable_ptr(blob), sshbuf_len(blob)); + if (bio == NULL ) return SSH_ERR_ALLOC_FAIL; - if (BIO_write(bio, sshbuf_ptr(blob), sshbuf_len(blob)) != - (int)sshbuf_len(blob)) { - r = SSH_ERR_ALLOC_FAIL; - goto out; - } - clear_libcrypto_errors(); - if ((pk = PEM_read_bio_PrivateKey(bio, NULL, pem_passphrase_cb, + ERR_clear_error(); + if ((pk = PEM_read_bio_PrivateKey(bio, NULL, NULL, (char *)passphrase)) == NULL) { - /* - * libcrypto may return various ASN.1 errors when attempting - * to parse a key with an incorrect passphrase. - * Treat all format errors as "incorrect passphrase" if a - * passphrase was supplied. - */ - if (passphrase != NULL && *passphrase != '\0') - r = SSH_ERR_KEY_WRONG_PASSPHRASE; - else - r = convert_libcrypto_error(); + debug3("read PEM private key fail"); + do_log_crypto_errors(SYSLOG_LEVEL_DEBUG3); + r = SSH_ERR_KEY_WRONG_PASSPHRASE; goto out; } - if (EVP_PKEY_base_id(pk) == EVP_PKEY_RSA && - (type == KEY_UNSPEC || type == KEY_RSA)) { - if ((prv = sshkey_new(KEY_UNSPEC)) == NULL) { - r = SSH_ERR_ALLOC_FAIL; - goto out; - } - prv->rsa = EVP_PKEY_get1_RSA(pk); - prv->type = KEY_RSA; -#ifdef DEBUG_PK - RSA_print_fp(stderr, prv->rsa, 8); -#endif - if (RSA_blinding_on(prv->rsa, NULL) != 1) { - r = SSH_ERR_LIBCRYPTO_ERROR; - goto out; - } - if ((r = sshkey_check_rsa_length(prv, 0)) != 0) - goto out; - } else if (EVP_PKEY_base_id(pk) == EVP_PKEY_DSA && - (type == KEY_UNSPEC || type == KEY_DSA)) { - if ((prv = sshkey_new(KEY_UNSPEC)) == NULL) { - r = SSH_ERR_ALLOC_FAIL; - goto out; - } - prv->dsa = EVP_PKEY_get1_DSA(pk); - prv->type = KEY_DSA; -#ifdef DEBUG_PK - DSA_print_fp(stderr, prv->dsa, 8); -#endif -#ifdef OPENSSL_HAS_ECC - } else if (EVP_PKEY_base_id(pk) == EVP_PKEY_EC && - (type == KEY_UNSPEC || type == KEY_ECDSA)) { - if ((prv = sshkey_new(KEY_UNSPEC)) == NULL) { - r = SSH_ERR_ALLOC_FAIL; - goto out; - } - prv->ecdsa = EVP_PKEY_get1_EC_KEY(pk); - prv->type = KEY_ECDSA; - prv->ecdsa_nid = sshkey_ecdsa_key_to_nid(prv->ecdsa); - if (prv->ecdsa_nid == -1 || - sshkey_curve_nid_to_name(prv->ecdsa_nid) == NULL || - sshkey_ec_validate_public(EC_KEY_get0_group(prv->ecdsa), - EC_KEY_get0_public_key(prv->ecdsa)) != 0 || - sshkey_ec_validate_private(prv->ecdsa) != 0) { - r = SSH_ERR_INVALID_FORMAT; - goto out; - } -# ifdef DEBUG_PK - if (prv != NULL && prv->ecdsa != NULL) - sshkey_dump_ec_key(prv->ecdsa); -# endif -#endif /* OPENSSL_HAS_ECC */ - } else { - r = SSH_ERR_INVALID_FORMAT; + r = sshkey_from_pkey(pk, &prv); + if (r != 0) goto out; + pk = NULL; /* transferred */ + + BIO_free(bio); + bio = BIO_new_mem_buf(sshbuf_mutable_ptr(blob), sshbuf_len(blob)); + if (bio == NULL) { + r = SSH_ERR_ALLOC_FAIL; goto out; } + x509key_parse_cert(prv, bio); + r = 0; if (keyp != NULL) { *keyp = prv; @@ -3512,12 +3220,13 @@ BIO_free(bio); EVP_PKEY_free(pk); sshkey_free(prv); + debug3("read PEM private key done: %d", r); return r; } #endif /* WITH_OPENSSL */ int -sshkey_parse_private_fileblob_type(struct sshbuf *blob, int type, +sshkey_parse_private_fileblob(struct sshbuf *blob, const char *passphrase, struct sshkey **keyp, char **commentp) { int r = SSH_ERR_INTERNAL_ERROR; @@ -3527,58 +3236,26 @@ if (commentp != NULL) *commentp = NULL; - switch (type) { - case KEY_ED25519: - case KEY_XMSS: - /* No fallback for new-format-only keys */ - return sshkey_parse_private2(blob, type, passphrase, - keyp, commentp); - default: - r = sshkey_parse_private2(blob, type, passphrase, keyp, - commentp); - /* Only fallback to PEM parser if a format error occurred. */ - if (r != SSH_ERR_INVALID_FORMAT) - return r; + r = sshkey_parse_private2(blob, passphrase, keyp, commentp); + /* Do not fallback to PEM parser if only passphrase is wrong. */ + if (r == 0 || r == SSH_ERR_KEY_WRONG_PASSPHRASE) + return r; #ifdef WITH_OPENSSL - return sshkey_parse_private_pem_fileblob(blob, type, - passphrase, keyp); + return sshkey_parse_private_pem_fileblob(blob, passphrase, keyp); #else - return SSH_ERR_INVALID_FORMAT; + return SSH_ERR_INVALID_FORMAT; #endif /* WITH_OPENSSL */ - } } int -sshkey_parse_private_fileblob(struct sshbuf *buffer, const char *passphrase, - struct sshkey **keyp, char **commentp) -{ - if (keyp != NULL) - *keyp = NULL; - if (commentp != NULL) - *commentp = NULL; - - return sshkey_parse_private_fileblob_type(buffer, KEY_UNSPEC, - passphrase, keyp, commentp); -} - -void -sshkey_sig_details_free(struct sshkey_sig_details *details) -{ - freezero(details, sizeof(*details)); -} - -int -sshkey_parse_pubkey_from_private_fileblob_type(struct sshbuf *blob, int type, +sshkey_parse_pubkey_from_private_fileblob(struct sshbuf *blob, struct sshkey **pubkeyp) { - int r = SSH_ERR_INTERNAL_ERROR; + if (parse_x509_from_private_fileblob(blob, pubkeyp) == 0) + return 0; - if (pubkeyp != NULL) - *pubkeyp = NULL; - /* only new-format private keys bundle a public key inside */ - if ((r = sshkey_parse_private2_pubkey(blob, type, pubkeyp)) != 0) - return r; - return 0; + /* custom-format private keys bundle a public key inside */ + return sshkey_parse_private2_pubkey(blob, pubkeyp); } #ifdef WITH_XMSS @@ -3644,24 +3321,30 @@ sshkey_private_serialize_maxsign(struct sshkey *k, struct sshbuf *b, u_int32_t maxsign, int printerror) { + UNUSED(maxsign); + UNUSED(printerror); return sshkey_private_serialize_opt(k, b, SSHKEY_SERIALIZE_DEFAULT); } u_int32_t sshkey_signatures_left(const struct sshkey *k) { + UNUSED(k); return 0; } int sshkey_enable_maxsign(struct sshkey *k, u_int32_t maxsign) { + UNUSED(k); + UNUSED(maxsign); return SSH_ERR_INVALID_ARGUMENT; } int sshkey_set_filename(struct sshkey *k, const char *filename) { + UNUSED(filename); if (k == NULL) return SSH_ERR_INVALID_ARGUMENT; return 0; diff -ruN openssh-9.4p1/sshkey-crypto.c openssh-9.4p1+x509-14.2.1/sshkey-crypto.c --- openssh-9.4p1/sshkey-crypto.c 1970-01-01 02:00:00.000000000 +0200 +++ openssh-9.4p1+x509-14.2.1/sshkey-crypto.c 2023-08-20 10:07:01.000000000 +0300 @@ -0,0 +1,1371 @@ +/* + * Copyright (c) 2020-2023 Roumen Petrov. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifndef USE_OPENSSL_PROVIDER +/* TODO: implement OpenSSL 4.0 API, as OpenSSL 3.* is quite nonfunctional */ +# define OPENSSL_SUPPRESS_DEPRECATED +#endif + +#define SSHKEY_INTERNAL +#include "includes.h" + +#ifdef WITH_OPENSSL +#include "evp-compat.h" +#include + +#include /*for memcpy*/ + +#include "ssh-x509.h" +#include "compat.h" +#include "ssherr.h" +#include "crypto_api.h" /*for some Ed25519 defines */ +#include "xmalloc.h" +#include "log.h" + + +#ifndef HAVE_DSA_SIG_GET0 /* OpenSSL < 1.1 */ +static inline void +DSA_SIG_get0(const DSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps) { + if (pr != NULL) *pr = sig->r; + if (ps != NULL) *ps = sig->s; +} +#endif /*ndef HAVE_DSA_SIG_GET0 OpenSSL < 1.1 */ + +#ifndef HAVE_DSA_SIG_SET0 /* OpenSSL < 1.1 */ +static inline int/*bool*/ +DSA_SIG_set0(DSA_SIG *sig, BIGNUM *r, BIGNUM *s) { + if (r == NULL || s == NULL) return 0; + + BN_clear_free(sig->r); + BN_clear_free(sig->s); + + sig->r = r; + sig->s = s; + return 1; +} +#endif /*ndef HAVE_DSA_SIG_SET0 OpenSSL < 1.1 */ + +#ifdef OPENSSL_HAS_ECC +#ifndef HAVE_ECDSA_SIG_GET0 /* OpenSSL < 1.1 */ +static inline void +ECDSA_SIG_get0(const ECDSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps) { + if (pr != NULL) *pr = sig->r; + if (ps != NULL) *ps = sig->s; +} +#endif /*ndef HAVE_ECDSA_SIG_GET0 OpenSSL < 1.1 */ + +#ifndef HAVE_ECDSA_SIG_SET0 /* OpenSSL < 1.1 */ +static inline int/*bool*/ +ECDSA_SIG_set0(ECDSA_SIG *sig, BIGNUM *r, BIGNUM *s) { + if (r == NULL || s == NULL) return 0; + + BN_clear_free(sig->r); + BN_clear_free(sig->s); + + sig->r = r; + sig->s = s; + return 1; +} +#endif /*ndef HAVE_ECDSA_SIG_SET0 OpenSSL < 1.1 */ +#endif /*def OPENSSL_HAS_ECC*/ + +#ifndef HAVE_EVP_DSS1 +/* removed in OpenSSL 1.1 */ +static inline const EVP_MD* EVP_dss1(void) { return EVP_sha1(); } +#endif + + +#ifdef DEBUG_PK +static void +ssh_EVP_PKEY_print_fp(FILE *fp, const EVP_PKEY *pkey) { +#ifdef HAVE_EVP_PKEY_PRINT_PARAMS /* OpenSSL 1.0.0+ */ +{ /* OpenSSL lacks print to file stream */ + BIO *bio = BIO_new_fp(fp, BIO_NOCLOSE); +#ifdef VMS + { BIO *tmpbio = BIO_new(BIO_f_linebuffer()); + bio = BIO_push(tmpbio, bio); + } +#endif + + EVP_PKEY_print_private(bio, pkey, 0, NULL); + BIO_free_all(bio); +} +#else +{ + int evp_id = EVP_PKEY_base_id(pkey); + + switch (evp_id) { + case EVP_PKEY_RSA: { + RSA *rsa = EVP_PKEY_get1_RSA(pkey); + RSA_print_fp(fp, rsa, 0); + RSA_free(rsa); + } break; +#ifdef OPENSSL_HAS_ECC + case EVP_PKEY_EC: { + EC_KEY *ec = EVP_PKEY_get1_EC_KEY(pkey); + EC_KEY_print_fp(fp, ec, 0); + EC_KEY_free(ec); + } break; +#endif /* OPENSSL_HAS_ECC */ + case EVP_PKEY_DSA: { + DSA *dsa = EVP_PKEY_get1_DSA(pkey); + DSA_print_fp(fp, dsa, 0); + DSA_free(dsa); + } break; + } +} +#endif /*ndef HAVE_EVP_PKEY_PRINT_PARAMS*/ +} + +static void +sshkey_dump(const char *func, const struct sshkey *key) { + fprintf(stderr, "dump key %s():\n", func); + ssh_EVP_PKEY_print_fp(stderr, key->pk); +} +#endif /* DEBUG_PK */ + +#define SSHKEY_DUMP(...) sshkey_dump(__func__, __VA_ARGS__) + + +#ifdef OPENSSL_HAS_ECC +extern int /* TODO move to ssh-ecdsa.c */ +sshkey_validate_ec_priv(const EC_KEY *ec); + +int +sshkey_validate_ec_priv(const EC_KEY *ec) { + int r; + const BIGNUM *exponent; + BIGNUM *order = NULL, *tmp = NULL; + + exponent = EC_KEY_get0_private_key(ec); + if (exponent == NULL) { + r = SSH_ERR_INVALID_ARGUMENT; + goto err; + } + + order = BN_new(); + if (order == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto err; + } + + if (EC_GROUP_get_order(EC_KEY_get0_group(ec), order, NULL) != 1) { + r = SSH_ERR_LIBCRYPTO_ERROR; + goto err; + } + + /* log2(private) > log2(order)/2 */ + if (BN_num_bits(exponent) <= BN_num_bits(order) / 2) { + r = SSH_ERR_KEY_INVALID_EC_VALUE; + goto err; + } + + tmp = BN_new(); + if (tmp == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto err; + } + + /* private < order - 1 */ + if (!BN_sub(tmp, order, BN_value_one())) { + r = SSH_ERR_LIBCRYPTO_ERROR; + goto err; + } + if (BN_cmp(exponent, tmp) >= 0) { + r = SSH_ERR_KEY_INVALID_EC_VALUE; + goto err; + } + + /* other checks ? */ + + r = 0; + +err: + BN_clear_free(order); + BN_clear_free(tmp); + return r; +} +#endif + + +#ifdef OPENSSL_HAS_ECC +int +ssh_EC_KEY_preserve_nid(EC_KEY *ec) +{ + static int nids[] = { + NID_X9_62_prime256v1, + NID_secp384r1, +# ifdef OPENSSL_HAS_NISTP521 + NID_secp521r1, +# endif /* OPENSSL_HAS_NISTP521 */ + -1 + }; + int k; + const EC_GROUP *g = EC_KEY_get0_group(ec); + + /* + * The group may be stored in a ASN.1 encoded private key in one of two + * ways: as a "named group", which is reconstituted by ASN.1 object ID + * or explicit group parameters encoded into the key blob. Only the + * "named group" case sets the group NID for us, but we can figure + * it out for the other case by comparing against all the groups that + * are supported. + */ +{ int nid = EC_GROUP_get_curve_name(g); + if (nid > 0) { + for (k = 0; nids[k] != -1; k++) { + if (nid == nids[k]) + return nid; + } + return -1; + } +} +{ EC_GROUP *eg; + for (k = 0; nids[k] != -1; k++) { + eg = EC_GROUP_new_by_curve_name(nids[k]); + if (eg == NULL) return -1; + if (EC_GROUP_cmp(g, eg, NULL) == 0) + break; + EC_GROUP_free(eg); + } + if (nids[k] == -1) return -1; + /* Use the group with the NID attached */ + EC_GROUP_set_asn1_flag(eg, OPENSSL_EC_NAMED_CURVE); + if (EC_KEY_set_group(ec, eg) != 1) { + EC_GROUP_free(eg); + return -1; + } + EC_GROUP_free(eg); +} + return nids[k]; +} +#endif /*def OPENSSL_HAS_ECC*/ + + +extern int +ssh_EVP_PKEY_complete_pub_rsa(EVP_PKEY *pk); + +static int +sshkey_from_pkey_rsa(EVP_PKEY *pk, struct sshkey **keyp) { + int r; + struct sshkey* key; + + r = ssh_EVP_PKEY_complete_pub_rsa(pk); + if (r != 0) return r; + + key = sshkey_new(KEY_UNSPEC); + if (key == NULL) + return SSH_ERR_ALLOC_FAIL; + + key->type = KEY_RSA; + key->pk = pk; + + /* success */ + SSHKEY_DUMP(key); + *keyp = key; + return 0; +} + +extern int +ssh_EVP_PKEY_complete_pub_dsa(EVP_PKEY *pk); + +static int +sshkey_from_pkey_dsa(EVP_PKEY *pk, struct sshkey **keyp) { + int r; + struct sshkey* key; + + r = ssh_EVP_PKEY_complete_pub_dsa(pk); + if (r != 0) return r; + + key = sshkey_new(KEY_UNSPEC); + if (key == NULL) + return SSH_ERR_ALLOC_FAIL; + + /* success */ + key->type = KEY_DSA; + key->pk = pk; + + SSHKEY_DUMP(key); + *keyp = key; + return 0; +} + +#ifdef OPENSSL_HAS_ECC +extern int +ssh_EVP_PKEY_complete_pub_ecdsa(EVP_PKEY *pk); + +static int +sshkey_from_pkey_ecdsa(EVP_PKEY *pk, struct sshkey **keyp) { + int r; + struct sshkey* key; + EC_KEY *ec; + + r = ssh_EVP_PKEY_complete_pub_ecdsa(pk); + if (r != 0) return r; + + key = sshkey_new(KEY_UNSPEC); + if (key == NULL) + return SSH_ERR_ALLOC_FAIL; + + key->type = KEY_ECDSA; + key->pk = pk; + + ec = EVP_PKEY_get1_EC_KEY(key->pk); + if (ec == NULL) { + r = SSH_ERR_LIBCRYPTO_ERROR; + goto err; + } + +{ /* indirectly set in sshkey_ecdsa_key_to_nid(if needed) + when pkey is completed */ + const EC_GROUP *g = EC_KEY_get0_group(ec); + key->ecdsa_nid = EC_GROUP_get_curve_name(g); +} + +{ /* private part is not required */ + const BIGNUM *exponent = EC_KEY_get0_private_key(ec); + if (exponent == NULL) goto skip_private; + + r = sshkey_validate_ec_priv(ec); + if (r != 0) goto err; +} +skip_private: + + /* success */ + SSHKEY_DUMP(key); + *keyp = key; + EC_KEY_free(ec); + return 0; + +err: + EC_KEY_free(ec); + sshkey_free(key); + return r; +} +#endif /* OPENSSL_HAS_ECC */ + +#ifdef OPENSSL_HAS_ED25519 +static int +sshkey_from_pkey_ed25519(EVP_PKEY *pk, struct sshkey **keyp) { + int r; + struct sshkey* key; + char *raw_pk = NULL, *raw_sk = NULL; + size_t len; + + key = sshkey_new(KEY_UNSPEC); + if (key == NULL) + return SSH_ERR_ALLOC_FAIL; + + if ((raw_pk = calloc(1, ED25519_PK_SZ)) == NULL || + (raw_sk = calloc(1, ED25519_SK_SZ)) == NULL + ) { + r = SSH_ERR_ALLOC_FAIL; + goto err; + } + + len = ED25519_PK_SZ; + if (!EVP_PKEY_get_raw_public_key(pk, raw_pk, &len)) { + r = SSH_ERR_LIBCRYPTO_ERROR; + goto err; + } + if (len != ED25519_PK_SZ) { + r = SSH_ERR_INVALID_FORMAT; + goto err; + } + + /* private part is not required */ + len = ED25519_SK_SZ - ED25519_PK_SZ; + if (!EVP_PKEY_get_raw_private_key(pk, raw_sk, &len)) + goto skip_private; + if (len != (ED25519_SK_SZ - ED25519_PK_SZ)) { + r = SSH_ERR_INVALID_FORMAT; + goto err; + } + /* append the public key to private to match internal format */ + memcpy(raw_sk + len, raw_pk, ED25519_PK_SZ); +skip_private: + + key->type = KEY_ED25519; + key->pk = pk; + + /* success */ + SSHKEY_DUMP(key); + *keyp = key; + /* free raw values; TODO */ + key->ed25519_pk = raw_pk; + key->ed25519_sk = raw_sk; + return 0; + +err: + free(raw_pk); + free(raw_sk); + sshkey_free(key); + return r; +} +#endif /*def OPENSSL_HAS_ED25519*/ + +int +sshkey_from_pkey(EVP_PKEY *pk, struct sshkey **keyp) { + int r, evp_id; + + /* NOTE do not set flags |= SSHKEY_FLAG_EXT !!! */ + evp_id = EVP_PKEY_base_id(pk); + switch (evp_id) { + case EVP_PKEY_RSA: + r = sshkey_from_pkey_rsa(pk, keyp); + break; + case EVP_PKEY_DSA: + r = sshkey_from_pkey_dsa(pk, keyp); + break; +#ifdef OPENSSL_HAS_ECC + case EVP_PKEY_EC: + r = sshkey_from_pkey_ecdsa(pk, keyp); + break; +#endif /*def OPENSSL_HAS_ECC*/ +#ifdef OPENSSL_HAS_ED25519 + case EVP_PKEY_ED25519: + r = sshkey_from_pkey_ed25519(pk, keyp); + break; +#endif /*def OPENSSL_HAS_ED25519*/ + default: + error_f("unsupported pkey type %d", evp_id); + r = SSH_ERR_KEY_TYPE_UNKNOWN; + } + + return r; +} + + +void +sshkey_clear_pkey(struct sshkey *key) { + EVP_PKEY_free(key->pk); + key->pk = NULL; +} + + +void +sshkey_move_pk(struct sshkey *from, struct sshkey *to) { + EVP_PKEY_free(to->pk); + to->pk = from->pk; + from->pk = NULL; + SSHKEY_DUMP(to); +} + + +int +sshkey_validate_public(const struct sshkey *key) { + int evp_id = EVP_PKEY_base_id(key->pk); + + switch (evp_id) { + case EVP_PKEY_RSA: return sshkey_validate_public_rsa(key); + case EVP_PKEY_DSA: return sshkey_validate_public_dsa(key); +#ifdef OPENSSL_HAS_ECC + case EVP_PKEY_EC: return sshkey_validate_public_ecdsa(key); +#endif +#ifdef OPENSSL_HAS_ED25519 + case EVP_PKEY_ED25519: return 0 /* TODO? */; +#endif + } + return SSH_ERR_KEY_TYPE_UNKNOWN; +} + + +#ifndef HAVE_EVP_PKEY_CMP /* OpenSSL < 0.9.8 */ +extern int ssh_EVP_PKEY_cmp_rsa(const EVP_PKEY *a, const EVP_PKEY *b); +extern int ssh_EVP_PKEY_cmp_dsa(const EVP_PKEY *a, const EVP_PKEY *b); + +static int +EVP_PKEY_cmp(const EVP_PKEY *a, const EVP_PKEY *b) { + int evp_id = EVP_PKEY_base_id(a); + + switch (evp_id) { + case EVP_PKEY_RSA: return ssh_EVP_PKEY_cmp_rsa(a, b); + case EVP_PKEY_DSA: return ssh_EVP_PKEY_cmp_dsa(a, b); + } + return -2; +} +#endif /*ndef HAVE_EVP_PKEY_CMP*/ + +int +ssh_EVP_PKEY_eq(const EVP_PKEY *a, const EVP_PKEY *b) { +#ifdef HAVE_EVP_PKEY_EQ /* OpenSSL >= 3.0 */ + return EVP_PKEY_eq(a, b); +#else + return EVP_PKEY_cmp(a, b); +#endif +} + +int/*bool*/ +sshkey_equal_public_pkey(const struct sshkey *ka, const struct sshkey *kb) { + const EVP_PKEY *a, *b; + + if (ka == NULL) return 0; + if (kb == NULL) return 0; + + a = ka->pk; + if (a == NULL) return 0; + + b = kb->pk; + if (b == NULL) return 0; + + return ssh_EVP_PKEY_eq(a, b) == 1; +} + + +/* write identity in PEM formats - PKCS#8 or Traditional */ +int +sshkey_private_to_bio(struct sshkey *key, BIO *bio, + const char *passphrase, int format) +{ + int res; + int len = strlen(passphrase); + const EVP_CIPHER *cipher = (len > 0) ? EVP_aes_256_cbc() : NULL; + u_char *_passphrase = (len > 0) ? (u_char*)passphrase : NULL; + + if (key->pk == NULL) + return SSH_ERR_INVALID_ARGUMENT; + if (len > 0 && len <= 4) + return SSH_ERR_PASSPHRASE_TOO_SHORT; + if (len > INT_MAX) + return SSH_ERR_INVALID_ARGUMENT; + + if (format == SSHKEY_PRIVATE_PEM) { + switch (key->type) { + case KEY_RSA: { + RSA *rsa = EVP_PKEY_get1_RSA(key->pk); + res = PEM_write_bio_RSAPrivateKey(bio, rsa, + cipher, _passphrase, len, NULL, NULL); + RSA_free(rsa); + } break; +#ifdef OPENSSL_HAS_ECC + case KEY_ECDSA: { + EC_KEY *ec = EVP_PKEY_get1_EC_KEY(key->pk); + res = PEM_write_bio_ECPrivateKey(bio, ec, + cipher, _passphrase, len, NULL, NULL); + EC_KEY_free(ec); + } break; +#endif + case KEY_DSA: { + DSA *dsa = EVP_PKEY_get1_DSA(key->pk); + res = PEM_write_bio_DSAPrivateKey(bio, dsa, + cipher, _passphrase, len, NULL, NULL); + DSA_free(dsa); + } break; + default: + return SSH_ERR_INVALID_ARGUMENT; + } + } else + res = PEM_write_bio_PKCS8PrivateKey(bio, key->pk, cipher, + _passphrase, len, NULL, NULL); + + if (res && sshkey_is_x509(key)) + res = x509key_write_identity_bio_pem(bio, key); + + return res ? 0 : SSH_ERR_LIBCRYPTO_ERROR; +} + + +/* methods used localy only in ssh-keygen.c */ +extern int +sshkey_public_to_fp(struct sshkey *key, FILE *fp, int format); + +extern int +sshkey_public_from_fp(FILE *fp, int format, struct sshkey **key); + + +int +sshkey_public_to_fp(struct sshkey *key, FILE *fp, int format) { + int res; + + if ((format != SSHKEY_PRIVATE_PEM) && + (format != SSHKEY_PRIVATE_PKCS8)) + return SSH_ERR_INVALID_ARGUMENT; + + if (key->pk == NULL) + return SSH_ERR_INVALID_ARGUMENT; + + if ((format == SSHKEY_PRIVATE_PEM) && + /* Traditional PEM is available only for RSA */ + (key->type == KEY_RSA) + ) { + RSA *rsa = EVP_PKEY_get1_RSA(key->pk); + res = PEM_write_RSAPublicKey(fp, rsa); + RSA_free(rsa); + } else + res = PEM_write_PUBKEY(fp, key->pk); + + return res ? 0 : SSH_ERR_LIBCRYPTO_ERROR; +} + +int +sshkey_public_from_fp(FILE *fp, int format, struct sshkey **key) { + int r; + + if (format == SSHKEY_PRIVATE_PKCS8) { + EVP_PKEY *pk = PEM_read_PUBKEY(fp, NULL, NULL, NULL); + if (pk != NULL) { + r = sshkey_from_pkey(pk, key); + if (r == 0) + pk = NULL; /* transferred */ + } else + r = SSH_ERR_INVALID_FORMAT; + EVP_PKEY_free(pk); + return r; + } + + if (format != SSHKEY_PRIVATE_PEM) + return SSH_ERR_INVALID_ARGUMENT; + +{ /* Traditional PEM is available only for RSA */ + RSA *rsa; + EVP_PKEY *pk = NULL; + struct sshkey *k = NULL; + + rsa = PEM_read_RSAPublicKey(fp, NULL, NULL, NULL); + if (rsa == NULL) return SSH_ERR_INVALID_FORMAT; + + pk = EVP_PKEY_new(); + if (pk == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto err; + } + if (!EVP_PKEY_set1_RSA(pk, rsa)) { + r = SSH_ERR_LIBCRYPTO_ERROR; + goto err; + } + + k = sshkey_new(KEY_UNSPEC); + if (k == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto err; + } + + k->type = KEY_RSA; + k->pk = pk; + RSA_free(rsa); + + *key = k; + return 0; + +err: + EVP_PKEY_free(pk); + RSA_free(rsa); + sshkey_free(k); + return r; +} +} + + +/* digest compatibility */ +#undef WRAP_OPENSSL_EC_EVP_SHA256 +#undef WRAP_OPENSSL_EC_EVP_SHA384 +#undef WRAP_OPENSSL_EC_EVP_SHA512 + +#if defined(OPENSSL_VERSION_NUMBER) && (OPENSSL_VERSION_NUMBER < 0x10000000L) +/* work-arounds for limited EVP digests in OpenSSL 0.9.8* ... + * (missing ecdsa support) + */ + +#if defined(OPENSSL_HAS_NISTP256) || defined(OPENSSL_HAS_NISTP384) || defined(OPENSSL_HAS_NISTP521) +static inline void +ssh_EVP_MD_ecdsa_init(EVP_MD *t, const EVP_MD *s) { + memcpy(t, s, sizeof(*t)); + t->sign = (evp_sign_method*)ECDSA_sign; + t->verify = (evp_verify_method*)ECDSA_verify; + t->required_pkey_type[0] = EVP_PKEY_EC; + t->required_pkey_type[1] = 0; +} +#endif + + +#ifdef OPENSSL_HAS_NISTP256 +# define WRAP_OPENSSL_EC_EVP_SHA256 +/* Test for NID_X9_62_prime256v1(nistp256) includes test for EVP_sha256 */ +static EVP_MD ecdsa_sha256_md = { NID_undef }; + +static inline const EVP_MD* +ssh_ecdsa_EVP_sha256(void) { + if (ecdsa_sha256_md.type == NID_undef) + ssh_EVP_MD_ecdsa_init(&ecdsa_sha256_md, EVP_sha256()); + return &ecdsa_sha256_md; +} +#endif + +#ifdef OPENSSL_HAS_NISTP384 +# define WRAP_OPENSSL_EC_EVP_SHA384 +/* Test for NID_secp384r1(nistp384) includes test for EVP_sha384 */ +static EVP_MD ecdsa_sha384_md = { NID_undef }; + +static inline const EVP_MD* +ssh_ecdsa_EVP_sha384(void) { + if (ecdsa_sha384_md.type == NID_undef) + ssh_EVP_MD_ecdsa_init(&ecdsa_sha384_md, EVP_sha384()); + return &ecdsa_sha384_md; +} +#endif + +#ifdef OPENSSL_HAS_NISTP521 +# define WRAP_OPENSSL_EC_EVP_SHA512 +/* Test for NID_secp521r1(nistp521) includes test for EVP_sha512 */ +static EVP_MD ecdsa_sha512_md = { NID_undef }; + +static inline const EVP_MD* +ssh_ecdsa_EVP_sha512(void) { + if (ecdsa_sha512_md.type == NID_undef) + ssh_EVP_MD_ecdsa_init(&ecdsa_sha512_md, EVP_sha512()); + return &ecdsa_sha512_md; +} +#endif + +#endif /*defined(OPENSSL_VERSION_NUMBER) && (OPENSSL_VERSION_NUMBER < 0x10000000L)*/ + +#if defined(OPENSSL_HAS_NISTP256) && !defined(WRAP_OPENSSL_EC_EVP_SHA256) +static inline const EVP_MD* ssh_ecdsa_EVP_sha256(void) { return EVP_sha256(); } +#endif +#if defined(OPENSSL_HAS_NISTP384) && !defined(WRAP_OPENSSL_EC_EVP_SHA384) +static inline const EVP_MD* ssh_ecdsa_EVP_sha384(void) { return EVP_sha384(); } +#endif +#if defined(OPENSSL_HAS_NISTP521) && !defined(WRAP_OPENSSL_EC_EVP_SHA512) +static inline const EVP_MD* ssh_ecdsa_EVP_sha512(void) { return EVP_sha512(); } +#endif + + + +#ifdef HAVE_EVP_DIGESTSIGN +static inline const EVP_MD* ssh_EVP_none(void) { return NULL; } +#endif + + +#ifdef HAVE_EVP_DIGESTSIGNINIT +static inline int +SSH_SignFinal(EVP_MD_CTX *ctx, unsigned char *sig, size_t *siglen) { + return EVP_DigestSignFinal(ctx, sig, siglen); +} +static inline int +SSH_VerifyFinal(EVP_MD_CTX *ctx, const unsigned char *sig, size_t siglen) { + /*safe cast for OpenSSL < 1.1*/ + return EVP_DigestVerifyFinal(ctx, (unsigned char *)sig, siglen); +} +#else +static inline int +SSH_SignFinal(EVP_MD_CTX *ctx, unsigned char *md, size_t *s, EVP_PKEY *pkey) { + unsigned int t; + int ret = EVP_SignFinal(ctx, md, &t, pkey); + *s = t; + return ret; +} +static inline int +SSH_VerifyFinal(EVP_MD_CTX *ctx, const unsigned char *sigbuf, size_t siglen_t, EVP_PKEY *pkey) { + unsigned int siglen = siglen_t; + /* paranoid check */ + if ((size_t)siglen != siglen_t) return -1; +# if OPENSSL_VERSION_NUMBER < 0x00908000L + return EVP_VerifyFinal(ctx, (unsigned char*)sigbuf, siglen, pkey); +# else + return EVP_VerifyFinal(ctx, sigbuf, siglen, pkey); +# endif +} +#endif + + +#ifdef HAVE_EVP_DIGESTSIGNINIT /* OpenSSL >= 1.0 */ +static inline int +buf_EVP_DigestSignFinal(EVP_MD_CTX *ctx, + unsigned char *sigret, size_t maxlen, size_t *siglen +) { + int ret = EVP_DigestSignFinal(ctx, NULL, siglen); + if (ret <= 0) return ret; + + /* paranoid check */ + if (*siglen > maxlen) return -1; + + return EVP_DigestSignFinal(ctx, sigret, siglen); +} +#endif /*def HAVE_EVP_DIGESTSIGNINIT**/ + + +#define SHARAW_DIGEST_LENGTH (2*SHA_DIGEST_LENGTH) + +static int +DSS1RAW_SignFinal( +#ifdef HAVE_EVP_DIGESTSIGNINIT + EVP_MD_CTX *ctx, unsigned char *sigret, size_t *siglen +#else + EVP_MD_CTX *ctx, unsigned char *sigret, size_t *siglen, EVP_PKEY *pkey +#endif +) { + DSA_SIG *sig; + size_t len; + +{ int ret; + unsigned char buf[20+2*(SHA_DIGEST_LENGTH)]; + +#ifdef HAVE_EVP_DIGESTSIGNINIT + ret = buf_EVP_DigestSignFinal(ctx, buf, sizeof(buf), &len); + if (ret <= 0) return ret; +#else + /* NOTE: Function EVP_SignFinal() in OpenSSL before 1.0 does not + * return signature length if signature argument is NULL. + */ +{ unsigned int t; + ret = EVP_SignFinal(ctx, buf, &t, pkey); + len = t; +} + if (ret <= 0) return ret; +#endif + +{ /* decode DSA signature */ + const unsigned char *psig = buf; + sig = d2i_DSA_SIG(NULL, &psig, (long)/*safe cast*/len); +} + + if (sig == NULL) return -1; +} + +/* encode DSA r&s into SecSH signature blob */ +{ u_int rlen, slen; + const BIGNUM *ps, *pr; + + DSA_SIG_get0(sig, &pr, &ps); + + rlen = BN_num_bytes(pr); + slen = BN_num_bytes(ps); + + if (rlen > SHA_DIGEST_LENGTH || slen > SHA_DIGEST_LENGTH) { + error_f("bad sig size %u %u", rlen, slen); + goto parse_err; + } + + /* NULL if caller checks for signature buffer size */ + if (sigret != NULL) { + explicit_bzero(sigret, SHARAW_DIGEST_LENGTH); + BN_bn2bin(pr, sigret + SHARAW_DIGEST_LENGTH - SHA_DIGEST_LENGTH - rlen); + BN_bn2bin(ps, sigret + SHARAW_DIGEST_LENGTH - slen); + } + *siglen = SHARAW_DIGEST_LENGTH; + + DSA_SIG_free(sig); + return 1; + +parse_err: + DSA_SIG_free(sig); + return -1; +} +} + + +static int +DSS1RAW_VerifyFinal( +#ifdef HAVE_EVP_DIGESTSIGNINIT +EVP_MD_CTX *ctx, const unsigned char *sigbuf, size_t siglen +#else +EVP_MD_CTX *ctx, const unsigned char *sigbuf, size_t siglen, EVP_PKEY *pkey +#endif +) { + DSA_SIG *sig; + + if (siglen != SHARAW_DIGEST_LENGTH) return -1; + +/* decode DSA r&s from SecSH signature blob */ +{ BIGNUM *ps, *pr; + + pr = BN_bin2bn(sigbuf , SHA_DIGEST_LENGTH, NULL); + ps = BN_bin2bn(sigbuf+SHA_DIGEST_LENGTH, SHA_DIGEST_LENGTH, NULL); + if ((pr == NULL) || (ps == NULL)) goto parse_err; + + sig = DSA_SIG_new(); + if (sig == NULL) goto parse_err; + + if (DSA_SIG_set0(sig, pr, ps)) + goto process; + + DSA_SIG_free(sig); + +parse_err: + BN_free(pr); + BN_free(ps); + return -1; +} + +process: +{ int len, slen; + unsigned char *buf; + int ret; + + len = i2d_DSA_SIG(sig, NULL); + if (len <= 0) { + DSA_SIG_free(sig); + return -1; + } + + buf = xmalloc(len); /*fatal on error*/ + +{ /* encode DSA signature */ + unsigned char *pbuf = buf; + slen = i2d_DSA_SIG(sig, &pbuf); +} + + ret = (len == slen) +#ifdef HAVE_EVP_DIGESTSIGNINIT + ? EVP_DigestVerifyFinal(ctx, buf, len) +#else + ? EVP_VerifyFinal(ctx, buf, len, pkey) +#endif + : -1; + + freezero(buf, len); + DSA_SIG_free(sig); + + return ret; +} +} + + +#ifdef OPENSSL_HAS_ECC +static int +SSH_ECDSA_SignFinal( +#ifdef HAVE_EVP_DIGESTSIGNINIT +EVP_MD_CTX *ctx, unsigned char *sigret, size_t *siglen +#else +EVP_MD_CTX *ctx, unsigned char *sigret, size_t *siglen, EVP_PKEY *pkey +#endif +) { + ECDSA_SIG *sig; + size_t len; + +{ int ret; + unsigned char buf[20+2*(SHA512_DIGEST_LENGTH)]; + +#ifdef HAVE_EVP_DIGESTSIGNINIT + ret = buf_EVP_DigestSignFinal(ctx, buf, sizeof(buf), &len); + if (ret <= 0) return ret; +#else + /* NOTE: Function EVP_SignFinal() in OpenSSL before 1.0 does not + * return signature length if signature argument is NULL. + */ +{ unsigned int t; + ret = EVP_SignFinal(ctx, buf, &t, pkey); + len = t; +} + if (ret <= 0) return ret; +#endif + +{ /* decode ECDSA signature */ + const unsigned char *psig = buf; + sig = d2i_ECDSA_SIG(NULL, &psig, (long)/*safe cast*/len); +} + + if (sig == NULL) return -1; +} + +/* encode ECDSA r&s into SecSH signature blob */ +{ int r; + struct sshbuf *buf = NULL; + const BIGNUM *pr, *ps; + + buf = sshbuf_new(); + if (buf == NULL) goto encode_err; + + ECDSA_SIG_get0(sig, &pr, &ps); + + r = sshbuf_put_bignum2(buf, pr); + if (r != 0) goto encode_err; + + r = sshbuf_put_bignum2(buf, ps); + if (r != 0) goto encode_err; + + len = sshbuf_len(buf); + if (len != sshbuf_len(buf)) goto encode_err; + + /* NULL if caller checks for signature buffer size */ + if (sigret != NULL) { + memcpy(sigret, sshbuf_ptr(buf), len); + } + *siglen = len; + + sshbuf_free(buf); + ECDSA_SIG_free(sig); + return 1; + +encode_err: + sshbuf_free(buf); + ECDSA_SIG_free(sig); + return -1; +} +} +#endif /*def OPENSSL_HAS_ECC*/ + + +#ifdef OPENSSL_HAS_ECC +static int +SSH_ECDSA_VerifyFinal( +#ifdef HAVE_EVP_DIGESTSIGNINIT +EVP_MD_CTX *ctx, const unsigned char *sigblob, size_t siglen +#else +EVP_MD_CTX *ctx, const unsigned char *sigblob, size_t siglen, EVP_PKEY *pkey +#endif +) { + ECDSA_SIG *sig; + +/* decode ECDSA r&s from SecSH signature blob */ +{ int r; + struct sshbuf *buf; + BIGNUM *pr = NULL, *ps = NULL; + + buf = sshbuf_from(sigblob, siglen); + if (buf == NULL) return -1; + + /* extract mpint r */ + r = sshbuf_get_bignum2(buf, &pr); + if (r != 0) goto parse_err; + + /* extract mpint s */ + r = sshbuf_get_bignum2(buf, &ps); + if (r != 0) goto parse_err; + + /* unexpected trailing data */ + if (sshbuf_len(buf) != 0) goto parse_err; + + sig = ECDSA_SIG_new(); + if (sig == NULL) goto parse_err; + + if (ECDSA_SIG_set0(sig, pr, ps)) { + sshbuf_free(buf); + goto process; + } + + ECDSA_SIG_free(sig); + +parse_err: + BN_free(ps); + BN_free(pr); + sshbuf_free(buf); + return -1; +} + +process: +{ int len, slen; + unsigned char *buf; + int ret; + + len = i2d_ECDSA_SIG(sig, NULL); + if (len <= 0) { + ECDSA_SIG_free(sig); + return -1; + } + + buf = xmalloc(len); /*fatal on error*/ + +{ /* encode ECDSA signature */ + unsigned char *pbuf = buf; + slen = i2d_ECDSA_SIG(sig, &pbuf); +} + + ret = (len == slen) +#ifdef HAVE_EVP_DIGESTSIGNINIT + ? EVP_DigestVerifyFinal(ctx, buf, len) +#else + ? EVP_VerifyFinal(ctx, buf, len, pkey) +#endif + : -1; + + freezero(buf, len); + ECDSA_SIG_free(sig); + + return ret; +} +} +#endif /*def OPENSSL_HAS_ECC*/ + + +/* order by usability */ +static ssh_evp_md dgsts[] = { +#ifdef HAVE_EVP_SHA256 + { SSH_MD_RSA_SHA256, EVP_sha256, SSH_SignFinal, SSH_VerifyFinal }, + { SSH_MD_RSA_SHA512, EVP_sha512, SSH_SignFinal, SSH_VerifyFinal }, +#endif /* def HAVE_EVP_SHA256 */ +#ifdef OPENSSL_HAS_NISTP256 + { SSH_MD_EC_SHA256_SSH, ssh_ecdsa_EVP_sha256, SSH_ECDSA_SignFinal, SSH_ECDSA_VerifyFinal }, +#endif +#ifdef OPENSSL_HAS_NISTP384 + { SSH_MD_EC_SHA384_SSH, ssh_ecdsa_EVP_sha384, SSH_ECDSA_SignFinal, SSH_ECDSA_VerifyFinal }, +#endif +#ifdef OPENSSL_HAS_NISTP521 + { SSH_MD_EC_SHA512_SSH, ssh_ecdsa_EVP_sha512, SSH_ECDSA_SignFinal, SSH_ECDSA_VerifyFinal }, +#endif + + { SSH_MD_RSA_SHA1, EVP_sha1, SSH_SignFinal, SSH_VerifyFinal }, + { SSH_MD_RSA_MD5, EVP_md5, SSH_SignFinal, SSH_VerifyFinal }, + + { SSH_MD_DSA_SHA1, EVP_dss1, SSH_SignFinal, SSH_VerifyFinal }, + { SSH_MD_DSA_RAW, EVP_dss1, DSS1RAW_SignFinal, DSS1RAW_VerifyFinal }, + + /* PKIX-SSH pre 10.0 does not implement properly rfc6187 */ +#ifdef OPENSSL_HAS_NISTP256 + { SSH_MD_EC_SHA256, ssh_ecdsa_EVP_sha256, SSH_SignFinal, SSH_VerifyFinal }, +#endif +#ifdef OPENSSL_HAS_NISTP384 + { SSH_MD_EC_SHA384, ssh_ecdsa_EVP_sha384, SSH_SignFinal, SSH_VerifyFinal }, +#endif +#ifdef OPENSSL_HAS_NISTP521 + { SSH_MD_EC_SHA512, ssh_ecdsa_EVP_sha512, SSH_SignFinal, SSH_VerifyFinal }, +#endif + +#ifdef HAVE_EVP_DIGESTSIGN + { SSH_MD_NONE, ssh_EVP_none, NULL, NULL }, +#endif + { -1, NULL, NULL , NULL } +}; + + +ssh_evp_md* +ssh_evp_md_find(int id) { + ssh_evp_md *p; + + for (p = dgsts; p->id != -1; p++) { + if (p->id == id) + return p; + } + return NULL; +} + + +void +ssh_xkalg_dgst_compat(ssh_evp_md *dest, const ssh_evp_md *src, ssh_compat *compat) { + dest->id = src->id; + dest->md = src->md; + +#ifdef OPENSSL_HAS_ECC + if (check_compat_extra(compat, SSHX_RFC6187_ASN1_OPAQUE_ECDSA_SIGNATURE)) { + if (src->SignFinal == SSH_ECDSA_SignFinal) { + dest->SignFinal = SSH_SignFinal; + dest->VerifyFinal = SSH_VerifyFinal; + return; + } + } +#else + UNUSED(compat); +#endif /*ndef OPENSSL_HAS_ECC*/ + + dest->SignFinal = src->SignFinal; + dest->VerifyFinal = src->VerifyFinal; +} + + +int +ssh_pkey_sign( + const ssh_evp_md *dgst, EVP_PKEY *privkey, + u_char *sig, size_t *siglen, const u_char *data, size_t datalen +) { + int ret; + EVP_MD_CTX *ctx; + + ctx = EVP_MD_CTX_new(); + if (ctx == NULL) { + error_f("out of memory"); + return -1; + } + +#ifdef HAVE_EVP_DIGESTSIGNINIT + ret = EVP_DigestSignInit(ctx, NULL, dgst->md(), NULL, privkey); +#else + ret = EVP_SignInit_ex(ctx, dgst->md(), NULL); +#endif + if (ret <= 0) { + error_f("init fail"); +#ifdef TRACE_EVP_ERROR + error_crypto("SignInit"); +#endif + goto done; + } + + if (dgst->md() == NULL) { +#ifdef HAVE_EVP_DIGESTSIGN + u_char *sigbuf; + size_t len; + + ret = EVP_DigestSign(ctx, NULL, &len, data, datalen); + if (ret <= 0) { +#ifdef TRACE_EVP_ERROR + error_crypto("DigestSign"); +#endif + goto done; + } + + sigbuf = OPENSSL_malloc(len); + if (sigbuf == NULL) { + ret = -1; + goto done; + } + explicit_bzero(sigbuf, len); + + ret = EVP_DigestSign(ctx, sigbuf, &len, data, datalen); + if (ret <= 0) { + OPENSSL_free(sigbuf); +#ifdef TRACE_EVP_ERROR + error_crypto("DigestSign"); +#endif + goto done; + } + /* NULL if caller checks for signature buffer size */ + if (sig != NULL) { + /*space ensured by caller*/ + memcpy(sig, sigbuf, len); + } + *siglen = len; + + explicit_bzero(sigbuf, len); + OPENSSL_free(sigbuf); +#else + ret = -1; /*unreachable*/ +#endif + goto done; + } + +#ifdef HAVE_EVP_DIGESTSIGNINIT + ret = EVP_DigestSignUpdate(ctx, data, datalen); +#else +# if OPENSSL_VERSION_NUMBER < 0x00908000L +{ + u_int dlen = datalen; + if ((size_t)dlen != datalen) return -1; + ret = EVP_SignUpdate(ctx, data, dlen); +} +# else + ret = EVP_SignUpdate(ctx, data, datalen); +# endif +#endif + if (ret <= 0) { + error_f("update fail"); +#ifdef TRACE_EVP_ERROR + error_crypto("SignUpdate"); +#endif + goto done; + } + +#ifdef HAVE_EVP_DIGESTSIGNINIT + ret = dgst->SignFinal(ctx, sig, siglen); +#else + ret = dgst->SignFinal(ctx, sig, siglen, privkey); +#endif + if (ret <= 0) { +#ifdef TRACE_EVP_ERROR + error_crypto("SignFinal"); +#endif + goto done; + } + +done: + EVP_MD_CTX_free(ctx); + return ret; +} + + +int +ssh_pkey_verify( + const ssh_evp_md *dgst, EVP_PKEY *pubkey, + const u_char *sig, size_t siglen, const u_char *data, size_t datalen +) { + int ret; + EVP_MD_CTX *ctx; + + ctx = EVP_MD_CTX_new(); + if (ctx == NULL) { + error_f("out of memory"); + return -1; + } + +#ifdef HAVE_EVP_DIGESTSIGNINIT + ret = EVP_DigestVerifyInit(ctx, NULL, dgst->md(), NULL, pubkey); +#else + ret = EVP_VerifyInit_ex(ctx, dgst->md(), NULL); +#endif + if (ret <= 0) { + error_f("init fail"); +#ifdef TRACE_EVP_ERROR + error_crypto("VerifyInit"); +#endif + goto done; + } + + if (dgst->md() == NULL) { +#ifdef HAVE_EVP_DIGESTSIGN + ret = EVP_DigestVerify(ctx, sig, siglen, data, datalen); +#ifdef TRACE_EVP_ERROR + if (ret <= 0) + error_crypto("DigestVerify"); +#endif +#else + ret = -1; /*unreachable*/ +#endif + goto done; + } + +#ifdef HAVE_EVP_DIGESTSIGNINIT + ret = EVP_DigestVerifyUpdate(ctx, data, datalen); +#else +# if OPENSSL_VERSION_NUMBER < 0x00908000L +{ + u_int dlen = datalen; + if ((size_t)dlen != datalen) return -1; + ret = EVP_VerifyUpdate(ctx, data, dlen); +} +# else + ret = EVP_VerifyUpdate(ctx, data, datalen); +# endif +#endif + if (ret <= 0) { + error_f("update fail"); +#ifdef TRACE_EVP_ERROR + error_crypto("VerifyUpdate"); +#endif + goto done; + } + +#ifdef HAVE_EVP_DIGESTSIGNINIT + ret = dgst->VerifyFinal(ctx, sig, siglen); +#else + ret = dgst->VerifyFinal(ctx, sig, siglen, pubkey); +#endif + if (ret <= 0) { +#ifdef TRACE_EVP_ERROR + error_crypto("VerifyFinal"); +#endif + goto done; + } + +done: + EVP_MD_CTX_free(ctx); + return ret; +} + +#else + +typedef int sshkey_crypto_empty_translation_unit; + +#endif /* WITH_OPENSSL */ diff -ruN openssh-9.4p1/ssh-keygen.0 openssh-9.4p1+x509-14.2.1/ssh-keygen.0 --- openssh-9.4p1/ssh-keygen.0 2023-08-10 04:11:18.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/ssh-keygen.0 2023-08-20 10:07:00.000000000 +0300 @@ -1,25 +1,23 @@ -SSH-KEYGEN(1) General Commands Manual SSH-KEYGEN(1) +SSH-KEYGEN(1) BSD General Commands Manual SSH-KEYGEN(1) NAME - ssh-keygen M-bM-^@M-^S OpenSSH authentication key utility + ssh-keygen -- Authentication key utility SYNOPSIS ssh-keygen [-q] [-a rounds] [-b bits] [-C comment] [-f output_keyfile] - [-m format] [-N new_passphrase] [-O option] - [-t dsa | ecdsa | ecdsa-sk | ed25519 | ed25519-sk | rsa] - [-w provider] [-Z cipher] + [-m format] [-N new_passphrase] + [-t dsa | ecdsa | ed25519 | rsa] [-Z cipher] ssh-keygen -p [-a rounds] [-f keyfile] [-m format] [-N new_passphrase] [-P old_passphrase] [-Z cipher] - ssh-keygen -i [-f input_keyfile] [-m key_format] - ssh-keygen -e [-f input_keyfile] [-m key_format] + ssh-keygen -i [-f input_keyfile] [-m format] + ssh-keygen -e [-f input_keyfile] [-m format] ssh-keygen -y [-f input_keyfile] ssh-keygen -c [-a rounds] [-C comment] [-f keyfile] [-P passphrase] ssh-keygen -l [-v] [-E fingerprint_hash] [-f input_keyfile] ssh-keygen -B [-f input_keyfile] - ssh-keygen -D pkcs11 + ssh-keygen -D pkcs11 [-l] [-v] ssh-keygen -F hostname [-lv] [-f known_hosts_file] ssh-keygen -H [-f known_hosts_file] - ssh-keygen -K [-a rounds] [-w provider] ssh-keygen -R hostname [-f known_hosts_file] ssh-keygen -r hostname [-g] [-f input_keyfile] ssh-keygen -M generate [-O option] output_file @@ -32,64 +30,58 @@ ssh-keygen -k -f krl_file [-u] [-s ca_public] [-z version_number] file ... ssh-keygen -Q [-l] -f krl_file file ... - ssh-keygen -Y find-principals [-O option] -s signature_file - -f allowed_signers_file - ssh-keygen -Y match-principals -I signer_identity -f allowed_signers_file - ssh-keygen -Y check-novalidate [-O option] -n namespace -s signature_file - ssh-keygen -Y sign [-O option] -f key_file -n namespace file ... - ssh-keygen -Y verify [-O option] -f allowed_signers_file - -I signer_identity -n namespace -s signature_file - [-r revocation_file] DESCRIPTION ssh-keygen generates, manages and converts authentication keys for ssh(1). ssh-keygen can create keys for use by SSH protocol version 2. - The type of key to be generated is specified with the -t option. If - invoked without any arguments, ssh-keygen will generate an RSA key. + The type of key to be generated is specified with the -t option. If in- + voked without any arguments, ssh-keygen will generate an RSA key. + + By default key is stored in PKCS#8 PEM format. For compatibility with + earlier versions programs read keys stored in traditional PEM format as + well. Option -p could be used to convert private key between OpenSSH + proprietary and more portable and widely used PKCS#8 PEM format depending + from option arguments: -m PKCS8 or -m OpenSSH. Note if requested propri- + etary format but key contain X.509 certificate will be used PKCS#8 PEM + format. Also in FIPS mode could be used only PKCS#8 PEM format. ssh-keygen is also used to generate groups for use in Diffie-Hellman group exchange (DH-GEX). See the MODULI GENERATION section for details. - Finally, ssh-keygen can be used to generate and update Key Revocation - Lists, and to test whether given keys have been revoked by one. See the - KEY REVOCATION LISTS section for details. + Finally, ssh-keygen can be used to generate and update custom Key Revoca- + tion Lists, and to test whether given keys have been revoked by one. See + the KEY REVOCATION LISTS section for details. Normally each user wishing to use SSH with public key authentication runs this once to create the authentication key in ~/.ssh/id_dsa, - ~/.ssh/id_ecdsa, ~/.ssh/id_ecdsa_sk, ~/.ssh/id_ed25519, - ~/.ssh/id_ed25519_sk or ~/.ssh/id_rsa. Additionally, the system - administrator may use this to generate host keys, as seen in /etc/rc. + ~/.ssh/id_ecdsa, ~/.ssh/id_ed25519 or ~/.ssh/id_rsa. Additionally, the + system administrator may use this to generate host keys, as seen in + /etc/rc. Normally this program generates the key and asks for a file in which to store the private key. The public key is stored in a file with the same - name but M-bM-^@M-^\.pubM-bM-^@M-^] appended. The program also asks for a passphrase. The + name but ".pub" appended. The program also asks for a passphrase. The passphrase may be empty to indicate no passphrase (host keys must have an empty passphrase), or it may be a string of arbitrary length. A - passphrase is similar to a password, except it can be a phrase with a - series of words, punctuation, numbers, whitespace, or any string of - characters you want. Good passphrases are 10-30 characters long, are not - simple sentences or otherwise easily guessable (English prose has only - 1-2 bits of entropy per character, and provides very bad passphrases), - and contain a mix of upper and lowercase letters, numbers, and non- - alphanumeric characters. The passphrase can be changed later by using - the -p option. + passphrase is similar to a password, except it can be a phrase with a se- + ries of words, punctuation, numbers, whitespace, or any string of charac- + ters you want. Good passphrases are 10-30 characters long, are not sim- + ple sentences or otherwise easily guessable (English prose has only 1-2 + bits of entropy per character, and provides very bad passphrases), and + contain a mix of upper and lowercase letters, numbers, and non-alphanu- + meric characters. The passphrase can be changed later by using the -p + option. There is no way to recover a lost passphrase. If the passphrase is lost or forgotten, a new key must be generated and the corresponding public key copied to other machines. - ssh-keygen will by default write keys in an OpenSSH-specific format. - This format is preferred as it offers better protection for keys at rest - as well as allowing storage of key comments within the private key file - itself. The key comment may be useful to help identify the key. The - comment is initialized to M-bM-^@M-^\user@hostM-bM-^@M-^] when the key is created, but can be - changed using the -c option. - - It is still possible for ssh-keygen to write the previously-used PEM - format private keys using the -m flag. This may be used when generating - new keys, and existing new-format keys may be converted using this option - in conjunction with the -p (change passphrase) flag. + For private keys stored in the proprietary OpenSSH format, there is also + a comment field in the key file that is only for convenience to the user + to help identify the key. The comment can tell what the key is for, or + whatever is useful. The comment is initialized to "user@host" when the + key is created, but can be changed using the -c option. After a key is generated, ssh-keygen will ask where the keys should be placed to be activated. @@ -97,65 +89,68 @@ The options are as follows: -A Generate host keys of all default key types (rsa, ecdsa, and - ed25519) if they do not already exist. The host keys are - generated with the default key file path, an empty passphrase, - default bits for the key type, and default comment. If -f has - also been specified, its argument is used as a prefix to the - default path for the resulting host key files. This is used by - /etc/rc to generate new host keys. + ed25519) if they do not already exist. The host keys are gener- + ated with the default key file path, an empty passphrase, default + bits for the key type, and default comment. If -f has also been + specified, its argument is used as a prefix to the default path + for the resulting host key files. This is used by /etc/rc to + generate new host keys. -a rounds - When saving a private key, this option specifies the number of - KDF (key derivation function, currently bcrypt_pbkdf(3)) rounds - used. Higher numbers result in slower passphrase verification - and increased resistance to brute-force password cracking (should - the keys be stolen). The default is 16 rounds. + When saving a private key in OpenSSH proprietary format, this op- + tion specifies the number of KDF (key derivation function, cur- + rently bcrypt_pbkdf(3)) rounds used. Higher numbers result in + slower passphrase verification and increased resistance to brute- + force password cracking (should the keys be stolen). The default + is 16 rounds. -B Show the bubblebabble digest of specified private or public key file. -b bits Specifies the number of bits in the key to create. For RSA keys, - the minimum size is 1024 bits and the default is 3072 bits. - Generally, 3072 bits is considered sufficient. DSA keys must be - exactly 1024 bits as specified by FIPS 186-2. For ECDSA keys, - the -b flag determines the key length by selecting from one of - three elliptic curve sizes: 256, 384 or 521 bits. Attempting to - use bit lengths other than these three values for ECDSA keys will - fail. ECDSA-SK, Ed25519 and Ed25519-SK keys have a fixed length - and the -b flag will be ignored. + the minimum size is 1024 bits and the default is 3072 bits. Gen- + erally, 3072 bits is considered sufficient. DSA keys must be ex- + actly 1024 bits as specified by FIPS 186-2. For ECDSA keys, the + -b flag determines the key length by selecting from one of three + elliptic curve sizes: 256, 384 or 521 bits. Attempting to use + bit lengths other than these three values for ECDSA keys will + fail. Ed25519 keys have a fixed length and the -b flag will be + ignored. -C comment Provides a new comment. -c Requests changing the comment in the private and public key - files. The program will prompt for the file containing the - private keys, for the passphrase if the key has one, and for the - new comment. + files. This operation is only supported for keys stored in the + proprietary OpenSSH format. The program will prompt for the file + containing the private keys, for the passphrase if the key has + one, and for the new comment. -D pkcs11 - Download the public keys provided by the PKCS#11 shared library - pkcs11. When used in combination with -s, this option indicates - that a CA key resides in a PKCS#11 token (see the CERTIFICATES - section for details). + Download the X.509 certificates or public keys provided by the + PKCS#11 shared library pkcs11. -E fingerprint_hash - Specifies the hash algorithm used when displaying key - fingerprints. Valid options are: M-bM-^@M-^\md5M-bM-^@M-^] and M-bM-^@M-^\sha256M-bM-^@M-^]. The - default is M-bM-^@M-^\sha256M-bM-^@M-^]. - - -e This option will read a private or public OpenSSH key file and - print to stdout a public key in one of the formats specified by - the -m option. The default export format is M-bM-^@M-^\RFC4716M-bM-^@M-^]. This - option allows exporting OpenSSH keys for use by other programs, - including several commercial SSH implementations. - - -F hostname | [hostname]:port - Search for the specified hostname (with optional port number) in - a known_hosts file, listing any occurrences found. This option - is useful to find hashed host names or addresses and may also be - used in conjunction with the -H option to print found keys in a - hashed format. + Specifies the hash algorithm used when displaying key finger- + prints. Valid options are: "md5" and "sha256". The default is + "sha256". + + -e This option will read a private or public key file and print to + stdout a public key in one of the formats specified by the -m op- + tion. The default export format is "RFC4716". This option al- + lows exporting keys for use by other programs, including several + commercial SSH implementations. + + -F hostname + Search for the specified hostname in a known_hosts file, listing + any occurrences found. Specified hostname could be a hostname or + an address optionally enclosed within '[' and ']' brackets then + followed by ':' and a port number. The format of known_hosts is + documented in the SSH_KNOWN_HOSTS section of sshd(8). This op- + tion is useful to find hashed host names or addresses and may + also be used in conjunction with the -H option to print found + keys in a hashed format. -f filename Specifies the filename of the key file. @@ -163,8 +158,8 @@ -g Use generic DNS format when printing fingerprint resource records using the -r command. - -H Hash a known_hosts file. This replaces all hostnames and - addresses with hashed representations within the specified file; + -H Hash a known_hosts file. This replaces all hostnames and ad- + dresses with hashed representations within the specified file; the original content is moved to a file with a .old suffix. These hashes may be used normally by ssh and sshd, but they do not reveal identifying information should the file's contents be @@ -172,75 +167,69 @@ and is therefore safe to use on files that mix hashed and non- hashed names. - -h When signing a key, create a host certificate instead of a user - certificate. See the CERTIFICATES section for details. + -h When signing a key, create a host custom certificate instead of a + user custom certificate. See the CERTIFICATES section for de- + tails. -I certificate_identity Specify the key identity when signing a public key. See the CERTIFICATES section for details. -i This option will read an unencrypted private (or public) key file - in the format specified by the -m option and print an OpenSSH - compatible private (or public) key to stdout. This option allows - importing keys from other software, including several commercial - SSH implementations. The default import format is M-bM-^@M-^\RFC4716M-bM-^@M-^]. - - -K Download resident keys from a FIDO authenticator. Public and - private key files will be written to the current directory for - each downloaded key. If multiple FIDO authenticators are - attached, keys will be downloaded from the first touched - authenticator. See the FIDO AUTHENTICATOR section for more - information. + in the format specified by the -m option and print an compatible + private (or public) key to stdout. This option allows importing + keys from other software, including several commercial SSH imple- + mentations. The default import format is "RFC4716". Note PKCS8 + format is usable only for public keys. -k Generate a KRL file. In this mode, ssh-keygen will generate a KRL file at the location specified via the -f flag that revokes - every key or certificate presented on the command line. - Keys/certificates to be revoked may be specified by public key - file or using the format described in the KEY REVOCATION LISTS - section. - - -L Prints the contents of one or more certificates. - - -l Show fingerprint of specified public key file. For RSA and DSA - keys ssh-keygen tries to find the matching public key file and - prints its fingerprint. If combined with -v, a visual ASCII art + every key or custom certificate presented on the command line. + Keys/custom certificates to be revoked may be specified by public + key file or using the format described in the KEY REVOCATION + LISTS section. + + -L Prints the contents of one or more custom certificates. + + -l Show fingerprint of public key read from specified file. For all + key types ssh-keygen tries to find file with the matching public + key and prints its fingerprint. When identity contain X.509 cer- + tificate public key is extracted from it and fingerprint is + printed for public key. If combined with -v, a visual ASCII art representation of the key is supplied with the fingerprint. -M generate - Generate candidate Diffie-Hellman Group Exchange (DH-GEX) - parameters for eventual use by the - M-bM-^@M-^Xdiffie-hellman-group-exchange-*M-bM-^@M-^Y key exchange methods. The - numbers generated by this operation must be further screened - before use. See the MODULI GENERATION section for more - information. + Generate candidate Diffie-Hellman Group Exchange (DH-GEX) parame- + ters for eventual use by the 'diffie-hellman-group-exchange-*' + key exchange methods. The numbers generated by this operation + must be further screened before use. See the MODULI GENERATION + section for more information. -M screen Screen candidate parameters for Diffie-Hellman Group Exchange. This will accept a list of candidate numbers and test that they - are safe (Sophie Germain) primes with acceptable group - generators. The results of this operation may be added to the - /etc/moduli file. See the MODULI GENERATION section for more - information. - - -m key_format - Specify a key format for key generation, the -i (import), -e - (export) conversion options, and the -p change passphrase - operation. The latter may be used to convert between OpenSSH - private key and PEM private key formats. The supported key - formats are: M-bM-^@M-^\RFC4716M-bM-^@M-^] (RFC 4716/SSH2 public or private key), - M-bM-^@M-^\PKCS8M-bM-^@M-^] (PKCS8 public or private key) or M-bM-^@M-^\PEMM-bM-^@M-^] (PEM public key). - By default OpenSSH will write newly-generated private keys in its - own format, but when converting public keys for export the - default format is M-bM-^@M-^\RFC4716M-bM-^@M-^]. Setting a format of M-bM-^@M-^\PEMM-bM-^@M-^] when - generating or updating a supported private key type will cause - the key to be stored in the legacy PEM private key format. + are safe (Sophie Germain) primes with acceptable group genera- + tors. The results of this operation may be added to the + /etc/moduli file. See the MODULI GENERATION section for more in- + formation. + + -m format + Specify a key format for key generation, the -i (import), -e (ex- + port) conversion options, and the -p change passphrase operation. + The latter may be used to convert between proprietary OpenSSH + private key and portable PKCS#8 PEM private key formats. The + supported formats are: "RFC4716" (RFC 4716/SSH2 public), "PKCS8" + (PKCS#8 PEM public or private key), "PEM" (traditional PEM public + or private key) or "OpenSSH" (proprietary OpenSSH public or pri- + vate key). The default conversion format is "RFC4716" for ex- + port/import of public keys and "PKCS8" for private keys. -N new_passphrase Provides the new passphrase. -n principals - Specify one or more principals (user or host names) to be - included in a certificate when signing a key. Multiple + Specify one or more principals (user or host names) to be in- + cluded in a custom certificate when signing a key. Multiple principals may be specified, separated by commas. See the CERTIFICATES section for details. @@ -248,125 +237,114 @@ Specify a key/value option. These are specific to the operation that ssh-keygen has been requested to perform. - When signing certificates, one of the options listed in the - CERTIFICATES section may be specified here. - - When performing moduli generation or screening, one of the - options listed in the MODULI GENERATION section may be specified. - - When generating FIDO authenticator-backed keys, the options - listed in the FIDO AUTHENTICATOR section may be specified. + When signing custom certificates, one of the options listed in + the CERTIFICATES section may be specified here. - When performing signature-related options using the -Y flag, the - following options are accepted: - - hashalg=algorithm - Selects the hash algorithm to use for hashing the message - to be signed. Valid algorithms are M-bM-^@M-^\sha256M-bM-^@M-^] and - M-bM-^@M-^\sha512.M-bM-^@M-^] The default is M-bM-^@M-^\sha512.M-bM-^@M-^] - - print-pubkey - Print the full public key to standard output after - signature verification. - - verify-time=timestamp - Specifies a time to use when validating signatures - instead of the current time. The time may be specified - as a date or time in the YYYYMMDD[Z] or in - YYYYMMDDHHMM[SS][Z] formats. Dates and times will be - interpreted in the current system time zone unless - suffixed with a Z character, which causes them to be - interpreted in the UTC time zone. + When performing moduli generation or screening, one of the op- + tions listed in the MODULI GENERATION section may be specified. When generating SSHFP DNS records from public keys using the -r flag, the following options are accepted: hashalg=algorithm Selects a hash algorithm to use when printing SSHFP - records using the -D flag. Valid algorithms are M-bM-^@M-^\sha1M-bM-^@M-^] - and M-bM-^@M-^\sha256M-bM-^@M-^]. The default is to print both. + records. Valid algorithms are "sha1" and "sha256". The + default is to print both. The -O option may be specified multiple times. + -o Obsolete option replaced by -m OpenSSH. Causes ssh-keygen to + save private keys using the proprietary OpenSSH format rather + than the more compatible PKCS#8 PEM format. Note Ed25519 keys + will use the proprietary key format if key is not supported by + cryptographic library. + -P passphrase Provides the (old) passphrase. -p Requests changing the passphrase of a private key file instead of creating a new private key. The program will prompt for the file containing the private key, for the old passphrase, and twice for - the new passphrase. + the new passphrase. Options -m PKCS8, -m PEM, or -m OpenSSH + could by used to set explicitly format of stored key: either com- + patible PKCS#8 PEM, traditional PEM, or proprietary OpenSSH for- + mat. Note by default is used PKCS#8 PEM format. -Q Test whether keys have been revoked in a KRL. If the -l option is also specified then the contents of the KRL will be printed. -q Silence ssh-keygen. - -R hostname | [hostname]:port - Removes all keys belonging to the specified hostname (with - optional port number) from a known_hosts file. This option is - useful to delete hashed hosts (see the -H option above). + -R hostname + Removes all keys belonging to the specified hostname from a + known_hosts file. Specified hostname could be a hostname or an + address optionally enclosed within '[' and ']' brackets then fol- + lowed by ':' and a port number. The format of known_hosts is + documented in the SSH_KNOWN_HOSTS section of sshd(8). This op- + tion is useful to delete hashed hosts (see the -H option above). -r hostname - Print the SSHFP fingerprint resource record named hostname for - the specified public key file. + Print the CERT or SSHFP resource record named hostname for the + specified public key file. Note CERT is printed for X.509 cer- + tificate based key. -s ca_key Certify (sign) a public key using the specified CA key. See the CERTIFICATES section for details. When generating a KRL, -s specifies a path to a CA public key - file used to revoke certificates directly by key ID or serial - number. See the KEY REVOCATION LISTS section for details. + file used to revoke custom certificates directly by key ID or se- + rial number. See the KEY REVOCATION LISTS section for details. - -t dsa | ecdsa | ecdsa-sk | ed25519 | ed25519-sk | rsa + -t dsa | ecdsa | ed25519 | rsa Specifies the type of key to create. The possible values are - M-bM-^@M-^\dsaM-bM-^@M-^], M-bM-^@M-^\ecdsaM-bM-^@M-^], M-bM-^@M-^\ecdsa-skM-bM-^@M-^], M-bM-^@M-^\ed25519M-bM-^@M-^], M-bM-^@M-^\ed25519-skM-bM-^@M-^], or M-bM-^@M-^\rsaM-bM-^@M-^]. + "dsa", "ecdsa", "ed25519", or "rsa". This flag may also be used to specify the desired signature type - when signing certificates using an RSA CA key. The available RSA - signature variants are M-bM-^@M-^\ssh-rsaM-bM-^@M-^] (SHA1 signatures, not - recommended), M-bM-^@M-^\rsa-sha2-256M-bM-^@M-^], and M-bM-^@M-^\rsa-sha2-512M-bM-^@M-^] (the default). - - -U When used in combination with -s or -Y sign, this option - indicates that a CA key resides in a ssh-agent(1). See the - CERTIFICATES section for more information. - - -u Update a KRL. When specified with -k, keys listed via the - command line are added to the existing KRL rather than a new KRL - being created. + when signing custom certificates using an RSA CA key. The avail- + able RSA signature variants are "ssh-rsa" (SHA1 signatures, not + recommended), "rsa-sha2-256", (the default) and "rsa-sha2-512". + + -U When used in combination with -s, this option indicates that a CA + key resides in a ssh-agent(1). See the CERTIFICATES section for + more information. + + -u Update a KRL. When specified with -k, keys listed via the com- + mand line are added to the existing KRL rather than a new KRL be- + ing created. -V validity_interval - Specify a validity interval when signing a certificate. A + Specify a validity interval when signing a custom certificate. A validity interval may consist of a single time, indicating that - the certificate is valid beginning now and expiring at that time, - or may consist of two times separated by a colon to indicate an - explicit time interval. + the custom certificate is valid beginning now and expiring at + that time, or may consist of two times separated by a colon to + indicate an explicit time interval. The start time may be specified as: - M-bM-^@M-M-bM-^@M-" The string M-bM-^@M-^\alwaysM-bM-^@M-^] to indicate the certificate has no + o The string "always" to indicate the custom certificate has no specified start time. - M-bM-^@M-M-bM-^@M-" A date or time in the system time zone formatted as YYYYMMDD + o A date or time in the system time zone formatted as YYYYMMDD or YYYYMMDDHHMM[SS]. - M-bM-^@M-M-bM-^@M-" A date or time in the UTC time zone as YYYYMMDDZ or - YYYYMMDDHHMM[SS]Z. - M-bM-^@M-M-bM-^@M-" A relative time before the current system time consisting of + o A date or time in the UTC time zone as YYYYMMDDZ or YYYYMMD- + DHHMM[SS]Z. + o A relative time before the current system time consisting of a minus sign followed by an interval in the format described in the TIME FORMATS section of sshd_config(5). - M-bM-^@M-M-bM-^@M-" A raw seconds since epoch (Jan 1 1970 00:00:00 UTC) as a - hexadecimal number beginning with M-bM-^@M-^\0xM-bM-^@M-^]. + o A raw seconds since epoch (Jan 1 1970 00:00:00 UTC) as a + hexadecimal number beginning with "0x". The end time may be specified similarly to the start time: - M-bM-^@M-M-bM-^@M-" The string M-bM-^@M-^\foreverM-bM-^@M-^] to indicate the certificate has no - specified end time. - M-bM-^@M-M-bM-^@M-" A date or time in the system time zone formatted as YYYYMMDD + o The string "forever" to indicate the custom certificate has + no specified end time. + o A date or time in the system time zone formatted as YYYYMMDD or YYYYMMDDHHMM[SS]. - M-bM-^@M-M-bM-^@M-" A date or time in the UTC time zone as YYYYMMDDZ or - YYYYMMDDHHMM[SS]Z. - M-bM-^@M-M-bM-^@M-" A relative time after the current system time consisting of a + o A date or time in the UTC time zone as YYYYMMDDZ or YYYYMMD- + DHHMM[SS]Z. + o A relative time after the current system time consisting of a plus sign followed by an interval in the format described in the TIME FORMATS section of sshd_config(5). - M-bM-^@M-M-bM-^@M-" A raw seconds since epoch (Jan 1 1970 00:00:00 UTC) as a - hexadecimal number beginning with M-bM-^@M-^\0xM-bM-^@M-^]. + o A raw seconds since epoch (Jan 1 1970 00:00:00 UTC) as a + hexadecimal number beginning with "0x". For example: @@ -376,8 +354,8 @@ Valid from four weeks ago to four weeks from now. 20100101123000:20110101123000 - Valid from 12:30 PM, January 1st, 2010 to 12:30 PM, - January 1st, 2011. + Valid from 12:30 PM, January 1st, 2010 to 12:30 PM, Janu- + ary 1st, 2011. 20100101123000Z:20110101123000Z Similar, but interpreted in the UTC time zone rather than @@ -393,99 +371,43 @@ Valid from one minute ago and never expiring. -v Verbose mode. Causes ssh-keygen to print debugging messages - about its progress. This is helpful for debugging moduli - generation. Multiple -v options increase the verbosity. The - maximum is 3. - - -w provider - Specifies a path to a library that will be used when creating - FIDO authenticator-hosted keys, overriding the default of using - the internal USB HID support. - - -Y find-principals - Find the principal(s) associated with the public key of a - signature, provided using the -s flag in an authorized signers - file provided using the -f flag. The format of the allowed - signers file is documented in the ALLOWED SIGNERS section below. - If one or more matching principals are found, they are returned - on standard output. - - -Y match-principals - Find principal matching the principal name provided using the -I - flag in the authorized signers file specified using the -f flag. - If one or more matching principals are found, they are returned - on standard output. - - -Y check-novalidate - Checks that a signature generated using ssh-keygen -Y sign has a - valid structure. This does not validate if a signature comes - from an authorized signer. When testing a signature, ssh-keygen - accepts a message on standard input and a signature namespace - using -n. A file containing the corresponding signature must - also be supplied using the -s flag. Successful testing of the - signature is signalled by ssh-keygen returning a zero exit - status. - - -Y sign - Cryptographically sign a file or some data using an SSH key. - When signing, ssh-keygen accepts zero or more files to sign on - the command-line - if no files are specified then ssh-keygen will - sign data presented on standard input. Signatures are written to - the path of the input file with M-bM-^@M-^\.sigM-bM-^@M-^] appended, or to standard - output if the message to be signed was read from standard input. - - The key used for signing is specified using the -f option and may - refer to either a private key, or a public key with the private - half available via ssh-agent(1). An additional signature - namespace, used to prevent signature confusion across different - domains of use (e.g. file signing vs email signing) must be - provided via the -n flag. Namespaces are arbitrary strings, and - may include: M-bM-^@M-^\fileM-bM-^@M-^] for file signing, M-bM-^@M-^\emailM-bM-^@M-^] for email signing. - For custom uses, it is recommended to use names following a - NAMESPACE@YOUR.DOMAIN pattern to generate unambiguous namespaces. - - -Y verify - Request to verify a signature generated using ssh-keygen -Y sign - as described above. When verifying a signature, ssh-keygen - accepts a message on standard input and a signature namespace - using -n. A file containing the corresponding signature must - also be supplied using the -s flag, along with the identity of - the signer using -I and a list of allowed signers via the -f - flag. The format of the allowed signers file is documented in - the ALLOWED SIGNERS section below. A file containing revoked - keys can be passed using the -r flag. The revocation file may be - a KRL or a one-per-line list of public keys. Successful - verification by an authorized signer is signalled by ssh-keygen - returning a zero exit status. - - -y This option will read a private OpenSSH format file and print an - OpenSSH public key to stdout. + about its progress. This is helpful for debugging moduli genera- + tion. Multiple -v options increase the verbosity. The maximum + is 3. + + -y This option will read a private key file and print to stdout an + public key in OpenSSH format. For this option keyfile name could + use prefixes "engine:" or "store:" to load identifies using en- + gine or store functionality provided by cryptographic library. + For more details see configuration option IdentityFile in + ssh_config(5). -Z cipher - Specifies the cipher to use for encryption when writing an - OpenSSH-format private key file. The list of available ciphers + Specifies the cipher to use for encryption when saving a private + key in OpenSSH proprietary format. The list of available ciphers may be obtained using "ssh -Q cipher". The default is - M-bM-^@M-^\aes256-ctrM-bM-^@M-^]. + "aes256-ctr". -z serial_number - Specifies a serial number to be embedded in the certificate to - distinguish this certificate from others from the same CA. If - the serial_number is prefixed with a M-bM-^@M-^X+M-bM-^@M-^Y character, then the - serial number will be incremented for each certificate signed on - a single command-line. The default serial number is zero. + Specifies a serial number to be embedded in the custom certifi- + cate to distinguish this custom certificate from others from the + same CA. If the serial_number is prefixed with a '+' character, + then the serial number will be incremented for each custom cer- + tificate signed on a single command-line. The default serial + number is zero. - When generating a KRL, the -z flag is used to specify a KRL - version number. + When generating a KRL, the -z flag is used to specify a KRL ver- + sion number. MODULI GENERATION ssh-keygen may be used to generate groups for the Diffie-Hellman Group Exchange (DH-GEX) protocol. Generating these groups is a two-step process: first, candidate primes are generated using a fast, but memory - intensive process. These candidate primes are then tested for - suitability (a CPU-intensive process). + intensive process. These candidate primes are then tested for suitabil- + ity (a CPU-intensive process). - Generation of primes is performed using the -M generate option. The - desired length of the primes may be specified by the -O bits option. For + Generation of primes is performed using the -M generate option. The de- + sired length of the primes may be specified by the -O bits option. For example: # ssh-keygen -M generate -O bits=2048 moduli-2048.candidates @@ -496,8 +418,8 @@ Once a set of candidates have been generated, they must be screened for suitability. This may be performed using the -M screen option. In this - mode ssh-keygen will read candidates from standard input (or a file - specified using the -f option). For example: + mode ssh-keygen will read candidates from standard input (or a file spec- + ified using the -f option). For example: # ssh-keygen -M screen -f moduli-2048.candidates moduli-2048 @@ -514,22 +436,22 @@ the -O flag: lines=number - Exit after screening the specified number of lines while - performing DH candidate screening. + Exit after screening the specified number of lines while perform- + ing DH candidate screening. start-line=line-number Start screening at the specified line number while performing DH candidate screening. checkpoint=filename - Write the last line processed to the specified file while - performing DH candidate screening. This will be used to skip - lines in the input file that have already been processed if the - job is restarted. + Write the last line processed to the specified file while per- + forming DH candidate screening. This will be used to skip lines + in the input file that have already been processed if the job is + restarted. memory=mbytes - Specify the amount of memory to use (in megabytes) when - generating candidate moduli for DH-GEX. + Specify the amount of memory to use (in megabytes) when generat- + ing candidate moduli for DH-GEX. start=hex-value Specify start point (in hex) when generating candidate moduli for @@ -540,78 +462,68 @@ moduli for DH-GEX. CERTIFICATES - ssh-keygen supports signing of keys to produce certificates that may be - used for user or host authentication. Certificates consist of a public - key, some identity information, zero or more principal (user or host) - names and a set of options that are signed by a Certification Authority - (CA) key. Clients or servers may then trust only the CA key and verify - its signature on a certificate rather than trusting many user/host keys. - Note that OpenSSH certificates are a different, and much simpler, format - to the X.509 certificates used in ssl(8). - - ssh-keygen supports two types of certificates: user and host. User - certificates authenticate users to servers, whereas host certificates - authenticate server hosts to users. To generate a user certificate: + ssh-keygen supports signing of keys to produce custom certificates that + may be used for user or host authentication. Custom certificates consist + of a public key, some identity information, zero or more principal (user + or host) names and a set of options that are signed by a custom Certifi- + cation Authority (CA) key. Clients or servers may then trust only the CA + key and verify its signature on a custom certificate rather than trusting + many user/host keys. Note that OpenSSH custom certificates are a differ- + ent, and much limited, format to the X.509 certificates used in ssl(8). + + ssh-keygen supports two types of custom certificates: user and host. + User custom certificates authenticate users to servers, whereas host cus- + tom certificates authenticate server hosts to users. To generate a user + custom certificate: $ ssh-keygen -s /path/to/ca_key -I key_id /path/to/user_key.pub - The resultant certificate will be placed in /path/to/user_key-cert.pub. - A host certificate requires the -h option: + The resultant custom certificate will be placed in + /path/to/user_key-cert.pub. A host custom certificate requires the -h + option: $ ssh-keygen -s /path/to/ca_key -I key_id -h /path/to/host_key.pub - The host certificate will be output to /path/to/host_key-cert.pub. - - It is possible to sign using a CA key stored in a PKCS#11 token by - providing the token library using -D and identifying the CA key by - providing its public half as an argument to -s: - - $ ssh-keygen -s ca_key.pub -D libpkcs11.so -I key_id user_key.pub - - Similarly, it is possible for the CA key to be hosted in a ssh-agent(1). - This is indicated by the -U flag and, again, the CA key must be - identified by its public half. - - $ ssh-keygen -Us ca_key.pub -I key_id user_key.pub + The host custom certificate will be output to /path/to/host_key-cert.pub. In all cases, key_id is a "key identifier" that is logged by the server - when the certificate is used for authentication. + when the custom certificate is used for authentication. - Certificates may be limited to be valid for a set of principal - (user/host) names. By default, generated certificates are valid for all - users or hosts. To generate a certificate for a specified set of - principals: + Custom certificates may be limited to be valid for a set of principal + (user/host) names. By default, generated custom certificates are valid + for all users or hosts. To generate a custom certificate for a specified + set of principals: $ ssh-keygen -s ca_key -I key_id -n user1,user2 user_key.pub $ ssh-keygen -s ca_key -I key_id -h -n host.domain host_key.pub - Additional limitations on the validity and use of user certificates may - be specified through certificate options. A certificate option may - disable features of the SSH session, may be valid only when presented - from particular source addresses or may force the use of a specific - command. + Additional limitations on the validity and use of user custom certifi- + cates may be specified through custom certificate options. A custom cer- + tificate option may disable features of the SSH session, may be valid + only when presented from particular source addresses or may force the use + of a specific command. - The options that are valid for user certificates are: + The options that are valid for user custom certificates are: clear Clear all enabled permissions. This is useful for clearing the - default set of permissions so permissions may be added - individually. + default set of permissions so permissions may be added individu- + ally. critical:name[=contents] extension:name[=contents] - Includes an arbitrary certificate critical option or extension. - The specified name should include a domain suffix, e.g. - M-bM-^@M-^\name@example.comM-bM-^@M-^]. If contents is specified then it is included - as the contents of the extension/option encoded as a string, - otherwise the extension/option is created with no contents - (usually indicating a flag). Extensions may be ignored by a - client or server that does not recognise them, whereas unknown - critical options will cause the certificate to be refused. + Includes an arbitrary custom certificate critical option or ex- + tension. The specified name should include a domain suffix, e.g. + "name@example.com". If contents is specified then it is included + as the contents of the extension/option encoded as a string, oth- + erwise the extension/option is created with no contents (usually + indicating a flag). Extensions may be ignored by a client or + server that does not recognise them, whereas unknown critical op- + tions will cause the custom certificate to be refused. force-command=command Forces the execution of command instead of any shell or command - specified by the user when the certificate is used for - authentication. + specified by the user when the custom certificate is used for au- + thentication. no-agent-forwarding Disable ssh-agent(1) forwarding (permitted by default). @@ -642,136 +554,59 @@ permit-X11-forwarding Allows X11 forwarding. - no-touch-required - Do not require signatures made using this key include - demonstration of user presence (e.g. by having the user touch the - authenticator). This option only makes sense for the FIDO - authenticator algorithms ecdsa-sk and ed25519-sk. - source-address=address_list - Restrict the source addresses from which the certificate is - considered valid. The address_list is a comma-separated list of - one or more address/netmask pairs in CIDR format. - - verify-required - Require signatures made using this key indicate that the user was - first verified. This option only makes sense for the FIDO - authenticator algorithms ecdsa-sk and ed25519-sk. Currently PIN - authentication is the only supported verification method, but - other methods may be supported in the future. + Restrict the source addresses from which the custom certificate + is considered valid. The address_list is a comma-separated list + of one or more address/netmask pairs in CIDR format. At present, no standard options are valid for host keys. - Finally, certificates may be defined with a validity lifetime. The -V - option allows specification of certificate start and end times. A - certificate that is presented at a time outside this range will not be - considered valid. By default, certificates are valid from the UNIX Epoch - to the distant future. - - For certificates to be used for user or host authentication, the CA - public key must be trusted by sshd(8) or ssh(1). Refer to those manual - pages for details. - -FIDO AUTHENTICATOR - ssh-keygen is able to generate FIDO authenticator-backed keys, after - which they may be used much like any other key type supported by OpenSSH, - so long as the hardware authenticator is attached when the keys are used. - FIDO authenticators generally require the user to explicitly authorise - operations by touching or tapping them. FIDO keys consist of two parts: - a key handle part stored in the private key file on disk, and a per- - device private key that is unique to each FIDO authenticator and that - cannot be exported from the authenticator hardware. These are combined - by the hardware at authentication time to derive the real key that is - used to sign authentication challenges. Supported key types are ecdsa-sk - and ed25519-sk. - - The options that are valid for FIDO keys are: - - application - Override the default FIDO application/origin string of M-bM-^@M-^\ssh:M-bM-^@M-^]. - This may be useful when generating host or domain-specific - resident keys. The specified application string must begin with - M-bM-^@M-^\ssh:M-bM-^@M-^]. - - challenge=path - Specifies a path to a challenge string that will be passed to the - FIDO authenticator during key generation. The challenge string - may be used as part of an out-of-band protocol for key enrollment - (a random challenge is used by default). - - device Explicitly specify a fido(4) device to use, rather than letting - the authenticator middleware select one. - - no-touch-required - Indicate that the generated private key should not require touch - events (user presence) when making signatures. Note that sshd(8) - will refuse such signatures by default, unless overridden via an - authorized_keys option. - - resident - Indicate that the key handle should be stored on the FIDO - authenticator itself. This makes it easier to use the - authenticator on multiple computers. Resident keys may be - supported on FIDO2 authenticators and typically require that a - PIN be set on the authenticator prior to generation. Resident - keys may be loaded off the authenticator using ssh-add(1). - Storing both parts of a key on a FIDO authenticator increases the - likelihood of an attacker being able to use a stolen - authenticator device. - - user A username to be associated with a resident key, overriding the - empty default username. Specifying a username may be useful when - generating multiple resident keys for the same application name. - - verify-required - Indicate that this private key should require user verification - for each signature. Not all FIDO authenticators support this - option. Currently PIN authentication is the only supported - verification method, but other methods may be supported in the - future. - - write-attestation=path - May be used at key generation time to record the attestation data - returned from FIDO authenticators during key generation. This - information is potentially sensitive. By default, this - information is discarded. + Finally, custom certificates may be defined with a validity lifetime. + The -V option allows specification of custom certificate start and end + times. A custom certificate that is presented at a time outside this + range will not be considered valid. By default, custom certificates are + valid from the UNIX Epoch to the distant future. + + For custom certificates to be used for user or host authentication, the + CA public key must be trusted by sshd(8) or ssh(1). Refer to those man- + ual pages for details. KEY REVOCATION LISTS - ssh-keygen is able to manage OpenSSH format Key Revocation Lists (KRLs). - These binary files specify keys or certificates to be revoked using a - compact format, taking as little as one bit per certificate if they are - being revoked by serial number. + ssh-keygen is able to manage OpenSSH format custom Key Revocation Lists + (KRLs). These binary files specify keys or custom certificates to be re- + voked using a compact format, taking as little as one bit per custom cer- + tificate if they are being revoked by serial number. KRLs may be generated using the -k flag. This option reads one or more - files from the command line and generates a new KRL. The files may - either contain a KRL specification (see below) or public keys, listed one - per line. Plain public keys are revoked by listing their hash or - contents in the KRL and certificates revoked by serial number or key ID - (if the serial is zero or not available). + files from the command line and generates a new KRL. The files may ei- + ther contain a KRL specification (see below) or public keys, listed one + per line. Plain public keys are revoked by listing their hash or con- + tents in the KRL and custom certificates revoked by serial number or key + ID (if the serial is zero or not available). Revoking keys using a KRL specification offers explicit control over the types of record used to revoke keys and may be used to directly revoke - certificates by serial number or key ID without having the complete - original certificate on hand. A KRL specification consists of lines - containing one of the following directives followed by a colon and some - directive-specific information. + custom certificates by serial number or key ID without having the com- + plete original custom certificate on hand. A KRL specification consists + of lines containing one of the following directives followed by a colon + and some directive-specific information. serial: serial_number[-serial_number] - Revokes a certificate with the specified serial number. Serial - numbers are 64-bit values, not including zero and may be + Revokes a custom certificate with the specified serial number. + Serial numbers are 64-bit values, not including zero and may be expressed in decimal, hex or octal. If two serial numbers are specified separated by a hyphen, then the range of serial numbers including and between each is revoked. The CA key must have been specified on the ssh-keygen command line using the -s option. id: key_id - Revokes a certificate with the specified key ID string. The CA - key must have been specified on the ssh-keygen command line using - the -s option. + Revokes a custom certificate with the specified key ID string. + The CA key must have been specified on the ssh-keygen command + line using the -s option. key: public_key - Revokes the specified key. If a certificate is listed, then it - is revoked as a plain public key. + Revokes the specified key. If a custom certificate is listed, + then it is revoked as a plain public key. sha1: public_key Revokes the specified key by including its SHA1 hash in the KRL. @@ -787,8 +622,8 @@ Only SHA256 fingerprints are supported here and resultant KRLs are not supported by OpenSSH versions prior to 7.9. - KRLs may be updated using the -u flag in addition to -k. When this - option is specified, keys listed via the command line are merged into the + KRLs may be updated using the -u flag in addition to -k. When this op- + tion is specified, keys listed via the command line are merged into the KRL, adding to those already there. It is also possible, given a KRL, to test whether it revokes a particular @@ -798,98 +633,68 @@ non-zero exit status. A zero exit status will only be returned if no key was revoked. -ALLOWED SIGNERS - When verifying signatures, ssh-keygen uses a simple list of identities - and keys to determine whether a signature comes from an authorized - source. This "allowed signers" file uses a format patterned after the - AUTHORIZED_KEYS FILE FORMAT described in sshd(8). Each line of the file - contains the following space-separated fields: principals, options, - keytype, base64-encoded key. Empty lines and lines starting with a M-bM-^@M-^X#M-bM-^@M-^Y - are ignored as comments. - - The principals field is a pattern-list (see PATTERNS in ssh_config(5)) - consisting of one or more comma-separated USER@DOMAIN identity patterns - that are accepted for signing. When verifying, the identity presented - via the -I option must match a principals pattern in order for the - corresponding key to be considered acceptable for verification. - - The options (if present) consist of comma-separated option - specifications. No spaces are permitted, except within double quotes. - The following option specifications are supported (note that option - keywords are case-insensitive): - - cert-authority - Indicates that this key is accepted as a certificate authority - (CA) and that certificates signed by this CA may be accepted for - verification. - - namespaces=namespace-list - Specifies a pattern-list of namespaces that are accepted for this - key. If this option is present, the signature namespace embedded - in the signature object and presented on the verification - command-line must match the specified list before the key will be - considered acceptable. - - valid-after=timestamp - Indicates that the key is valid for use at or after the specified - timestamp, which may be a date or time in the YYYYMMDD[Z] or - YYYYMMDDHHMM[SS][Z] formats. Dates and times will be interpreted - in the current system time zone unless suffixed with a Z - character, which causes them to be interpreted in the UTC time - zone. - - valid-before=timestamp - Indicates that the key is valid for use at or before the - specified timestamp. - - When verifying signatures made by certificates, the expected principal - name must match both the principals pattern in the allowed signers file - and the principals embedded in the certificate itself. - - An example allowed signers file: - - # Comments allowed at start of line - user1@example.com,user2@example.com ssh-rsa AAAAX1... - # A certificate authority, trusted for all principals in a domain. - *@example.com cert-authority ssh-ed25519 AAAB4... - # A key that is accepted only for file signing. - user2@example.com namespaces="file" ssh-ed25519 AAA41... - ENVIRONMENT - SSH_SK_PROVIDER - Specifies a path to a library that will be used when loading any - FIDO authenticator-hosted keys, overriding the default of using - the built-in USB HID support. + SSH_ASKPASS + If ssh-keygen needs a passphrase, it will read the passphrase + from the current terminal if it was run from a terminal. If + ssh-keygen does not have a terminal associated with it but + DISPLAY and SSH_ASKPASS are set, it will execute the program + specified by SSH_ASKPASS that may open a X11 window to read the + passphrase. For keys from "engine" or "store" SSH_ASKPASS is + preferred over associated terminal. Note if SSH_ASKPASS is not + set will be executed program ssh-askpass located in "libexec" di- + rectory. (Note that on some machines it may be necessary to re- + direct the input from /dev/null to make this work.) + + Remark: On Android DISPLAY is ignored and SSH_ASKPASS is pre- + ferred over associated terminal. + + SSH_ENGINE_CONF + Overrides default location of engine configuration file. FILES ~/.ssh/id_dsa ~/.ssh/id_ecdsa - ~/.ssh/id_ecdsa_sk ~/.ssh/id_ed25519 - ~/.ssh/id_ed25519_sk ~/.ssh/id_rsa - Contains the DSA, ECDSA, authenticator-hosted ECDSA, Ed25519, - authenticator-hosted Ed25519 or RSA authentication identity of - the user. This file should not be readable by anyone but the - user. It is possible to specify a passphrase when generating the - key; that passphrase will be used to encrypt the private part of - this file using 128-bit AES. This file is not automatically - accessed by ssh-keygen but it is offered as the default file for - the private key. ssh(1) will read this file when a login attempt - is made. + Contains the DSA, ECDSA, Ed25519 or RSA authentication identity + of the user. + + This file should not be readable by anyone but the user. + + For RSA, ECDSA, Ed25519 or DSA identity file may contain X.509 + certificate that match it. In addition file may contain extra + X.509 certificates. Extra certificates along with certificates + from X.509 store are used to build chain of certificates leading + to a trusted certificate authority if required by public key al- + gorithm format. + + It is possible to specify a passphrase when generating the key; + that passphrase will be used to encrypt the private part of this + file using 256-bit AES. This file is not automatically accessed + by ssh-keygen but it is offered as the default file for the pri- + vate key. ssh(1) will read this file when a login attempt is + made. ~/.ssh/id_dsa.pub ~/.ssh/id_ecdsa.pub - ~/.ssh/id_ecdsa_sk.pub ~/.ssh/id_ed25519.pub - ~/.ssh/id_ed25519_sk.pub ~/.ssh/id_rsa.pub - Contains the DSA, ECDSA, authenticator-hosted ECDSA, Ed25519, - authenticator-hosted Ed25519 or RSA public key for - authentication. The contents of this file should be added to + Contains the DSA, ECDSA, Ed25519 or RSA public key for authenti- + cation. The contents of this file should be added to ~/.ssh/authorized_keys on all machines where the user wishes to log in using public key authentication. There is no need to keep - the contents of this file secret. + the contents of this file secret. If file ~/.ssh/id_rsa, + ~/.ssh/id_ecdsa, ~/.ssh/id_ed25519, or ~/.ssh/id_dsa contain + RSA/ECDSA/Ed25519/DSA private key and X.509 certificates public + key file must contain certificate that match private key! Use + ssh-keygen with option -y to regenerate its content. Note in + case with X.509 certificate you can append content to + ~/.ssh/authorized_keys or to add certificate "Distinguished Name" + / "Subject" in corresponding format to "authorized keys" file. + See sshd(8). Using distinguished name is preferred as X.509 cer- + tificate could be renewed and after renewal there is no need to + update "authorized keys" file. /etc/moduli Contains Diffie-Hellman groups used for DH-GEX. The file format @@ -898,13 +703,34 @@ SEE ALSO ssh(1), ssh-add(1), ssh-agent(1), moduli(5), sshd(8) - The Secure Shell (SSH) Public Key File Format, RFC 4716, 2006. +CONFORMING TO + 1. D. Eastlake, Domain Name System Security Extensions, RFC 2535, March + 1999. + + 2. D. Eastlake, DSA KEYs and SIGs in the Domain Name System (DNS), RFC + 2536, March 1999. + + 3. D. Eastlake, RSA/MD5 KEYs and SIGs in the Domain Name System (DNS), + RFC 2537, March 1999. + + 4. D. Eastlake and O. Gudmundsson, Storing Certificates in the Domain + Name System (DNS), RFC 2538, March 1999. + + 5. D. Eastlake 3rd, RSA/SHA-1 SIGs and RSA KEYs in the Domain Name + System (DNS), RFC 3110, May 2001. + + 6. J. Schlyter and W. Griffin, Using DNS to Securely Publish Secure + Shell (SSH) Key Fingerprints, RFC 4255, January 2006. + + 7. J. Galbraith and R. Thayer, The Secure Shell (SSH) Public Key File + Format, RFC 4716, November 2006. AUTHORS - OpenSSH is a derivative of the original and free ssh 1.2.12 release by + PKIX-SSH is a derivative of the original and free ssh 1.2.12 release by Tatu Ylonen. Aaron Campbell, Bob Beck, Markus Friedl, Niels Provos, Theo - de Raadt and Dug Song removed many bugs, re-added newer features and - created OpenSSH. Markus Friedl contributed the support for SSH protocol - versions 1.5 and 2.0. + de Raadt and Dug Song removed many bugs, re-added newer features and cre- + ated OpenSSH. Markus Friedl contributed the support for SSH protocol + versions 1.5 and 2.0. Roumen Petrov contributed support for X.509 cer- + tificates. -OpenBSD 7.3 July 23, 2023 OpenBSD 7.3 +BSD 10 February 2023 BSD diff -ruN openssh-9.4p1/ssh-keygen.1 openssh-9.4p1+x509-14.2.1/ssh-keygen.1 --- openssh-9.4p1/ssh-keygen.1 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/ssh-keygen.1 2023-08-20 10:07:00.000000000 +0300 @@ -1,4 +1,4 @@ -.\" $OpenBSD: ssh-keygen.1,v 1.229 2023/07/23 20:04:45 naddy Exp $ +.\" $OpenBSD: ssh-keygen.1,v 1.228 2023/02/10 06:40:48 jmc Exp $ .\" .\" Author: Tatu Ylonen .\" Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -14,6 +14,7 @@ .\" Copyright (c) 1999,2000 Markus Friedl. All rights reserved. .\" Copyright (c) 1999 Aaron Campbell. All rights reserved. .\" Copyright (c) 1999 Theo de Raadt. All rights reserved. +.\" Copyright (c) 2002-2022 Roumen Petrov. All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions @@ -35,12 +36,20 @@ .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.Dd $Mdocdate: July 23 2023 $ +.\" Implement .Dd with the Mdocdate RCS keyword +.rn Dd xD +.de Dd +.ie \\$1$Mdocdate: \{\ +. xD \\$3 \\$2 \\$4 +.\} +.el .xD \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 +.. +.Dd $Mdocdate: February 10 2023 $ .Dt SSH-KEYGEN 1 .Os .Sh NAME .Nm ssh-keygen -.Nd OpenSSH authentication key utility +.Nd Authentication key utility .Sh SYNOPSIS .Nm ssh-keygen .Op Fl q @@ -50,9 +59,7 @@ .Op Fl f Ar output_keyfile .Op Fl m Ar format .Op Fl N Ar new_passphrase -.Op Fl O Ar option -.Op Fl t Cm dsa | ecdsa | ecdsa-sk | ed25519 | ed25519-sk | rsa -.Op Fl w Ar provider +.Op Fl t Cm dsa | ecdsa | ed25519 | rsa .Op Fl Z Ar cipher .Nm ssh-keygen .Fl p @@ -65,11 +72,11 @@ .Nm ssh-keygen .Fl i .Op Fl f Ar input_keyfile -.Op Fl m Ar key_format +.Op Fl m Ar format .Nm ssh-keygen .Fl e .Op Fl f Ar input_keyfile -.Op Fl m Ar key_format +.Op Fl m Ar format .Nm ssh-keygen .Fl y .Op Fl f Ar input_keyfile @@ -89,6 +96,8 @@ .Op Fl f Ar input_keyfile .Nm ssh-keygen .Fl D Ar pkcs11 +.Op Fl l +.Op Fl v .Nm ssh-keygen .Fl F Ar hostname .Op Fl lv @@ -97,10 +106,6 @@ .Fl H .Op Fl f Ar known_hosts_file .Nm ssh-keygen -.Fl K -.Op Fl a Ar rounds -.Op Fl w Ar provider -.Nm ssh-keygen .Fl R Ar hostname .Op Fl f Ar known_hosts_file .Nm ssh-keygen @@ -145,34 +150,6 @@ .Op Fl l .Fl f Ar krl_file .Ar -.Nm ssh-keygen -.Fl Y Cm find-principals -.Op Fl O Ar option -.Fl s Ar signature_file -.Fl f Ar allowed_signers_file -.Nm ssh-keygen -.Fl Y Cm match-principals -.Fl I Ar signer_identity -.Fl f Ar allowed_signers_file -.Nm ssh-keygen -.Fl Y Cm check-novalidate -.Op Fl O Ar option -.Fl n Ar namespace -.Fl s Ar signature_file -.Nm ssh-keygen -.Fl Y Cm sign -.Op Fl O Ar option -.Fl f Ar key_file -.Fl n Ar namespace -.Ar -.Nm ssh-keygen -.Fl Y Cm verify -.Op Fl O Ar option -.Fl f Ar allowed_signers_file -.Fl I Ar signer_identity -.Fl n Ar namespace -.Fl s Ar signature_file -.Op Fl r Ar revocation_file .Sh DESCRIPTION .Nm generates, manages and converts authentication keys for @@ -187,6 +164,21 @@ .Nm will generate an RSA key. .Pp +By default key is stored in PKCS#8 PEM format. +For compatibility with earlier versions programs +read keys stored in traditional PEM format as well. +Option +.Fl p +could be used to convert private key between OpenSSH proprietary +and more portable and widely used PKCS#8 PEM format +depending from option arguments: +.Fl m Ar PKCS8 +or +.Fl m Ar OpenSSH . +Note if requested proprietary format but key contain X.509 certificate +will be used PKCS#8 PEM format. +Also in FIPS mode could be used only PKCS#8 PEM format. +.Pp .Nm is also used to generate groups for use in Diffie-Hellman group exchange (DH-GEX). @@ -196,7 +188,7 @@ .Pp Finally, .Nm -can be used to generate and update Key Revocation Lists, and to test whether +can be used to generate and update custom Key Revocation Lists, and to test whether given keys have been revoked by one. See the .Sx KEY REVOCATION LISTS @@ -207,9 +199,7 @@ key in .Pa ~/.ssh/id_dsa , .Pa ~/.ssh/id_ecdsa , -.Pa ~/.ssh/id_ecdsa_sk , -.Pa ~/.ssh/id_ed25519 , -.Pa ~/.ssh/id_ed25519_sk +.Pa ~/.ssh/id_ed25519 or .Pa ~/.ssh/id_rsa . Additionally, the system administrator may use this to generate host keys, @@ -241,28 +231,16 @@ If the passphrase is lost or forgotten, a new key must be generated and the corresponding public key copied to other machines. .Pp -.Nm -will by default write keys in an OpenSSH-specific format. -This format is preferred as it offers better protection for -keys at rest as well as allowing storage of key comments within -the private key file itself. -The key comment may be useful to help identify the key. +For private keys stored in the proprietary OpenSSH format, +there is also a comment field in the key file that is only for +convenience to the user to help identify the key. +The comment can tell what the key is for, or whatever is useful. The comment is initialized to .Dq user@host when the key is created, but can be changed using the .Fl c option. .Pp -It is still possible for -.Nm -to write the previously-used PEM format private keys using the -.Fl m -flag. -This may be used when generating new keys, and existing new-format -keys may be converted using this option in conjunction with the -.Fl p -(change passphrase) flag. -.Pp After a key is generated, .Nm will ask where the keys @@ -283,7 +261,8 @@ .Pa /etc/rc to generate new host keys. .It Fl a Ar rounds -When saving a private key, this option specifies the number of KDF +When saving a private key in OpenSSH proprietary format, +this option specifies the number of KDF (key derivation function, currently .Xr bcrypt_pbkdf 3 ) rounds used. @@ -303,23 +282,20 @@ curve sizes: 256, 384 or 521 bits. Attempting to use bit lengths other than these three values for ECDSA keys will fail. -ECDSA-SK, Ed25519 and Ed25519-SK keys have a fixed length and the +Ed25519 keys have a fixed length and the .Fl b flag will be ignored. .It Fl C Ar comment Provides a new comment. .It Fl c Requests changing the comment in the private and public key files. +This operation is only supported for keys stored in the +proprietary OpenSSH format. The program will prompt for the file containing the private keys, for the passphrase if the key has one, and for the new comment. .It Fl D Ar pkcs11 -Download the public keys provided by the PKCS#11 shared library +Download the X.509 certificates or public keys provided by the PKCS#11 shared library .Ar pkcs11 . -When used in combination with -.Fl s , -this option indicates that a CA key resides in a PKCS#11 token (see the -.Sx CERTIFICATES -section for details). .It Fl E Ar fingerprint_hash Specifies the hash algorithm used when displaying key fingerprints. Valid options are: @@ -329,21 +305,35 @@ The default is .Dq sha256 . .It Fl e -This option will read a private or public OpenSSH key file and +This option will read a private or public key file and print to stdout a public key in one of the formats specified by the .Fl m option. The default export format is .Dq RFC4716 . -This option allows exporting OpenSSH keys for use by other programs, including +This option allows exporting keys for use by other programs, including several commercial SSH implementations. -.It Fl F Ar hostname | [hostname]:port +.It Fl F Ar hostname Search for the specified .Ar hostname -(with optional port number) in a .Pa known_hosts file, listing any occurrences found. +Specified +.Ar hostname +could be a hostname or an address optionally enclosed within +.Ql \&[ +and +.Ql \&] +brackets then followed by +.Ql \&: +and a port number. +The format of +.Pa known_hosts +is documented in the +.Em SSH_KNOWN_HOSTS +section of +.Xr sshd 8 . This option is useful to find hashed host names or addresses and may also be used in conjunction with the .Fl H @@ -370,8 +360,8 @@ This option will not modify existing hashed hostnames and is therefore safe to use on files that mix hashed and non-hashed names. .It Fl h -When signing a key, create a host certificate instead of a user -certificate. +When signing a key, create a host custom certificate instead of a user +custom certificate. See the .Sx CERTIFICATES section for details. @@ -384,39 +374,35 @@ This option will read an unencrypted private (or public) key file in the format specified by the .Fl m -option and print an OpenSSH compatible private +option and print an compatible private (or public) key to stdout. This option allows importing keys from other software, including several commercial SSH implementations. The default import format is .Dq RFC4716 . -.It Fl K -Download resident keys from a FIDO authenticator. -Public and private key files will be written to the current directory for -each downloaded key. -If multiple FIDO authenticators are attached, keys will be downloaded from -the first touched authenticator. -See the -.Sx FIDO AUTHENTICATOR -section for more information. +Note +.Ar PKCS8 +format is usable only for public keys. .It Fl k Generate a KRL file. In this mode, .Nm will generate a KRL file at the location specified via the .Fl f -flag that revokes every key or certificate presented on the command line. -Keys/certificates to be revoked may be specified by public key file or +flag that revokes every key or custom certificate presented on the command line. +Keys/custom certificates to be revoked may be specified by public key file or using the format described in the .Sx KEY REVOCATION LISTS section. .It Fl L -Prints the contents of one or more certificates. +Prints the contents of one or more custom certificates. .It Fl l -Show fingerprint of specified public key file. -For RSA and DSA keys +Show fingerprint of public key read from specified file. +For all key types .Nm -tries to find the matching public key file and prints its fingerprint. +tries to find file with the matching public key and prints its fingerprint. +When identity contain X.509 certificate public key is extracted +from it and fingerprint is printed for public key. If combined with .Fl v , a visual ASCII art representation of the key is supplied with the @@ -441,7 +427,7 @@ See the .Sx MODULI GENERATION section for more information. -.It Fl m Ar key_format +.It Fl m Ar format Specify a key format for key generation, the .Fl i (import), @@ -449,28 +435,29 @@ (export) conversion options, and the .Fl p change passphrase operation. -The latter may be used to convert between OpenSSH private key and PEM -private key formats. -The supported key formats are: +The latter may be used to convert between proprietary OpenSSH private key +and portable PKCS#8 PEM private key formats. +The supported formats are: .Dq RFC4716 -(RFC 4716/SSH2 public or private key), +(RFC 4716/SSH2 public), .Dq PKCS8 -(PKCS8 public or private key) -or +(PKCS#8 PEM public or private key), .Dq PEM -(PEM public key). -By default OpenSSH will write newly-generated private keys in its own -format, but when converting public keys for export the default format is -.Dq RFC4716 . -Setting a format of -.Dq PEM -when generating or updating a supported private key type will cause the -key to be stored in the legacy PEM private key format. +(traditional PEM public or private key) +or +.Dq OpenSSH +(proprietary OpenSSH public or private key). +The default conversion format is +.Dq RFC4716 +for export/import of public keys and +.Dq PKCS8 +for private keys. +.\" Ignore obsolete PEM for import/export - it is only for RSA public! .It Fl N Ar new_passphrase Provides the new passphrase. .It Fl n Ar principals Specify one or more principals (user or host names) to be included in -a certificate when signing a key. +a custom certificate when signing a key. Multiple principals may be specified, separated by commas. See the .Sx CERTIFICATES @@ -481,7 +468,7 @@ .Nm has been requested to perform. .Pp -When signing certificates, one of the options listed in the +When signing custom certificates, one of the options listed in the .Sx CERTIFICATES section may be specified here. .Pp @@ -490,42 +477,12 @@ .Sx MODULI GENERATION section may be specified. .Pp -When generating FIDO authenticator-backed keys, the options listed in the -.Sx FIDO AUTHENTICATOR -section may be specified. -.Pp -When performing signature-related options using the -.Fl Y -flag, the following options are accepted: -.Bl -tag -width Ds -.It Cm hashalg Ns = Ns Ar algorithm -Selects the hash algorithm to use for hashing the message to be signed. -Valid algorithms are -.Dq sha256 -and -.Dq sha512. -The default is -.Dq sha512. -.It Cm print-pubkey -Print the full public key to standard output after signature verification. -.It Cm verify-time Ns = Ns Ar timestamp -Specifies a time to use when validating signatures instead of the current -time. -The time may be specified as a date or time in the YYYYMMDD[Z] or -in YYYYMMDDHHMM[SS][Z] formats. -Dates and times will be interpreted in the current system time zone unless -suffixed with a Z character, which causes them to be interpreted in the -UTC time zone. -.El -.Pp When generating SSHFP DNS records from public keys using the .Fl r flag, the following options are accepted: .Bl -tag -width Ds .It Cm hashalg Ns = Ns Ar algorithm -Selects a hash algorithm to use when printing SSHFP records using the -.Fl D -flag. +Selects a hash algorithm to use when printing SSHFP records. Valid algorithms are .Dq sha1 and @@ -536,6 +493,15 @@ The .Fl O option may be specified multiple times. +.It Fl o +Obsolete option replaced by +.Fl m Ar OpenSSH . +Causes +.Nm +to save private keys using the proprietary OpenSSH format rather than +the more compatible PKCS#8 PEM format. +Note Ed25519 keys will use the proprietary key format +if key is not supported by cryptographic library. .It Fl P Ar passphrase Provides the (old) passphrase. .It Fl p @@ -544,6 +510,15 @@ The program will prompt for the file containing the private key, for the old passphrase, and twice for the new passphrase. +Options +.Fl m Ar PKCS8 , +.Fl m Ar PEM , +or +.Fl m Ar OpenSSH +could by used to set explicitly format of stored key: +either compatible PKCS#8 PEM, traditional PEM, +or proprietary OpenSSH format. +Note by default is used PKCS#8 PEM format. .It Fl Q Test whether keys have been revoked in a KRL. If the @@ -552,20 +527,35 @@ .It Fl q Silence .Nm ssh-keygen . -.It Fl R Ar hostname | [hostname]:port +.It Fl R Ar hostname Removes all keys belonging to the specified .Ar hostname -(with optional port number) from a .Pa known_hosts file. +Specified +.Ar hostname +could be a hostname or an address optionally enclosed within +.Ql \&[ +and +.Ql \&] +brackets then followed by +.Ql \&: +and a port number. +The format of +.Pa known_hosts +is documented in the +.Em SSH_KNOWN_HOSTS +section of +.Xr sshd 8 . This option is useful to delete hashed hosts (see the .Fl H option above). .It Fl r Ar hostname -Print the SSHFP fingerprint resource record named +Print the CERT or SSHFP resource record named .Ar hostname for the specified public key file. +Note CERT is printed for X.509 certificate based key. .It Fl s Ar ca_key Certify (sign) a public key using the specified CA key. See the @@ -574,36 +564,31 @@ .Pp When generating a KRL, .Fl s -specifies a path to a CA public key file used to revoke certificates directly +specifies a path to a CA public key file used to revoke custom certificates directly by key ID or serial number. See the .Sx KEY REVOCATION LISTS section for details. -.It Fl t Cm dsa | ecdsa | ecdsa-sk | ed25519 | ed25519-sk | rsa +.It Fl t Cm dsa | ecdsa | ed25519 | rsa Specifies the type of key to create. The possible values are .Dq dsa , .Dq ecdsa , -.Dq ecdsa-sk , .Dq ed25519 , -.Dq ed25519-sk , or .Dq rsa . .Pp This flag may also be used to specify the desired signature type when -signing certificates using an RSA CA key. +signing custom certificates using an RSA CA key. The available RSA signature variants are .Dq ssh-rsa (SHA1 signatures, not recommended), .Dq rsa-sha2-256 , -and -.Dq rsa-sha2-512 -(the default). +(the default) and +.Dq rsa-sha2-512 . .It Fl U When used in combination with -.Fl s -or -.Fl Y Cm sign , +.Fl s , this option indicates that a CA key resides in a .Xr ssh-agent 1 . See the @@ -616,9 +601,9 @@ keys listed via the command line are added to the existing KRL rather than a new KRL being created. .It Fl V Ar validity_interval -Specify a validity interval when signing a certificate. +Specify a validity interval when signing a custom certificate. A validity interval may consist of a single time, indicating that the -certificate is valid beginning now and expiring at that time, or may consist +custom certificate is valid beginning now and expiring at that time, or may consist of two times separated by a colon to indicate an explicit time interval. .Pp The start time may be specified as: @@ -626,7 +611,7 @@ .It The string .Dq always -to indicate the certificate has no specified start time. +to indicate the custom certificate has no specified start time. .It A date or time in the system time zone formatted as YYYYMMDD or YYYYMMDDHHMM[SS]. @@ -648,7 +633,7 @@ .It The string .Dq forever -to indicate the certificate has no specified end time. +to indicate the custom certificate has no specified end time. .It A date or time in the system time zone formatted as YYYYMMDD or YYYYMMDDHHMM[SS]. @@ -692,121 +677,35 @@ .Fl v options increase the verbosity. The maximum is 3. -.It Fl w Ar provider -Specifies a path to a library that will be used when creating -FIDO authenticator-hosted keys, overriding the default of using -the internal USB HID support. -.It Fl Y Cm find-principals -Find the principal(s) associated with the public key of a signature, -provided using the -.Fl s -flag in an authorized signers file provided using the -.Fl f -flag. -The format of the allowed signers file is documented in the -.Sx ALLOWED SIGNERS -section below. -If one or more matching principals are found, they are returned on -standard output. -.It Fl Y Cm match-principals -Find principal matching the principal name provided using the -.Fl I -flag in the authorized signers file specified using the -.Fl f -flag. -If one or more matching principals are found, they are returned on -standard output. -.It Fl Y Cm check-novalidate -Checks that a signature generated using -.Nm -.Fl Y Cm sign -has a valid structure. -This does not validate if a signature comes from an authorized signer. -When testing a signature, -.Nm -accepts a message on standard input and a signature namespace using -.Fl n . -A file containing the corresponding signature must also be supplied using the -.Fl s -flag. -Successful testing of the signature is signalled by -.Nm -returning a zero exit status. -.It Fl Y Cm sign -Cryptographically sign a file or some data using an SSH key. -When signing, -.Nm -accepts zero or more files to sign on the command-line - if no files -are specified then -.Nm -will sign data presented on standard input. -Signatures are written to the path of the input file with -.Dq .sig -appended, or to standard output if the message to be signed was read from -standard input. -.Pp -The key used for signing is specified using the -.Fl f -option and may refer to either a private key, or a public key with the private -half available via -.Xr ssh-agent 1 . -An additional signature namespace, used to prevent signature confusion across -different domains of use (e.g. file signing vs email signing) must be provided -via the -.Fl n -flag. -Namespaces are arbitrary strings, and may include: -.Dq file -for file signing, -.Dq email -for email signing. -For custom uses, it is recommended to use names following a -NAMESPACE@YOUR.DOMAIN pattern to generate unambiguous namespaces. -.It Fl Y Cm verify -Request to verify a signature generated using -.Nm -.Fl Y Cm sign -as described above. -When verifying a signature, -.Nm -accepts a message on standard input and a signature namespace using -.Fl n . -A file containing the corresponding signature must also be supplied using the -.Fl s -flag, along with the identity of the signer using -.Fl I -and a list of allowed signers via the -.Fl f -flag. -The format of the allowed signers file is documented in the -.Sx ALLOWED SIGNERS -section below. -A file containing revoked keys can be passed using the -.Fl r -flag. -The revocation file may be a KRL or a one-per-line list of public keys. -Successful verification by an authorized signer is signalled by -.Nm -returning a zero exit status. .It Fl y This option will read a private -OpenSSH format file and print an OpenSSH public key to stdout. +key file and print to stdout an public key in OpenSSH format. +For this option keyfile name could use prefixes +.Dq engine: +or +.Dq store: +to load identifies using engine or store functionality +provided by cryptographic library. +For more details see configuration option +.Cm IdentityFile +in +.Xr ssh_config 5 . .It Fl Z Ar cipher -Specifies the cipher to use for encryption when writing an OpenSSH-format -private key file. +Specifies the cipher to use for encryption +when saving a private key in OpenSSH proprietary format. The list of available ciphers may be obtained using .Qq ssh -Q cipher . The default is .Dq aes256-ctr . .It Fl z Ar serial_number -Specifies a serial number to be embedded in the certificate to distinguish -this certificate from others from the same CA. +Specifies a serial number to be embedded in the custom certificate to distinguish +this custom certificate from others from the same CA. If the .Ar serial_number is prefixed with a .Sq + -character, then the serial number will be incremented for each certificate -signed on a single command-line. +character, then the serial number will be incremented for each +custom certificate signed on a single command-line. The default serial number is zero. .Pp When generating a KRL, the @@ -892,73 +791,56 @@ .El .Sh CERTIFICATES .Nm -supports signing of keys to produce certificates that may be used for +supports signing of keys to produce custom certificates that may be used for user or host authentication. -Certificates consist of a public key, some identity information, zero or +Custom certificates consist of a public key, some identity information, zero or more principal (user or host) names and a set of options that -are signed by a Certification Authority (CA) key. +are signed by a custom Certification Authority (CA) key. Clients or servers may then trust only the CA key and verify its signature -on a certificate rather than trusting many user/host keys. -Note that OpenSSH certificates are a different, and much simpler, format to +on a custom certificate rather than trusting many user/host keys. +Note that OpenSSH custom certificates are a different, and much limited, format to the X.509 certificates used in .Xr ssl 8 . .Pp .Nm -supports two types of certificates: user and host. -User certificates authenticate users to servers, whereas host certificates +supports two types of custom certificates: user and host. +User custom certificates authenticate users to servers, whereas host custom certificates authenticate server hosts to users. -To generate a user certificate: +To generate a user custom certificate: .Pp .Dl $ ssh-keygen -s /path/to/ca_key -I key_id /path/to/user_key.pub .Pp -The resultant certificate will be placed in +The resultant custom certificate will be placed in .Pa /path/to/user_key-cert.pub . -A host certificate requires the +A host custom certificate requires the .Fl h option: .Pp .Dl $ ssh-keygen -s /path/to/ca_key -I key_id -h /path/to/host_key.pub .Pp -The host certificate will be output to +The host custom certificate will be output to .Pa /path/to/host_key-cert.pub . .Pp -It is possible to sign using a CA key stored in a PKCS#11 token by -providing the token library using -.Fl D -and identifying the CA key by providing its public half as an argument -to -.Fl s : -.Pp -.Dl $ ssh-keygen -s ca_key.pub -D libpkcs11.so -I key_id user_key.pub -.Pp -Similarly, it is possible for the CA key to be hosted in a -.Xr ssh-agent 1 . -This is indicated by the -.Fl U -flag and, again, the CA key must be identified by its public half. -.Pp -.Dl $ ssh-keygen -Us ca_key.pub -I key_id user_key.pub -.Pp In all cases, .Ar key_id -is a "key identifier" that is logged by the server when the certificate +is a "key identifier" that is logged by the server when the custom certificate is used for authentication. .Pp -Certificates may be limited to be valid for a set of principal (user/host) +Custom certificates may be limited to be valid for a set of principal (user/host) names. -By default, generated certificates are valid for all users or hosts. -To generate a certificate for a specified set of principals: +By default, generated custom certificates are valid for all users or hosts. +To generate a custom certificate for a specified set of principals: .Pp .Dl $ ssh-keygen -s ca_key -I key_id -n user1,user2 user_key.pub .Dl "$ ssh-keygen -s ca_key -I key_id -h -n host.domain host_key.pub" .Pp -Additional limitations on the validity and use of user certificates may -be specified through certificate options. -A certificate option may disable features of the SSH session, may be +Additional limitations on the validity and use of user custom certificates may +be specified through custom certificate options. +A custom certificate option may disable features of the SSH session, may be valid only when presented from particular source addresses or may force the use of a specific command. .Pp -The options that are valid for user certificates are: +The options that are valid for user custom certificates are: .Pp .Bl -tag -width Ds -compact .It Ic clear @@ -968,7 +850,7 @@ .Pp .It Ic critical : Ns Ar name Ns Op Ns = Ns Ar contents .It Ic extension : Ns Ar name Ns Op Ns = Ns Ar contents -Includes an arbitrary certificate critical option or extension. +Includes an arbitrary custom certificate critical option or extension. The specified .Ar name should include a domain suffix, e.g.\& @@ -979,13 +861,13 @@ encoded as a string, otherwise the extension/option is created with no contents (usually indicating a flag). Extensions may be ignored by a client or server that does not recognise them, -whereas unknown critical options will cause the certificate to be refused. +whereas unknown critical options will cause the custom certificate to be refused. .Pp .It Ic force-command Ns = Ns Ar command Forces the execution of .Ar command instead of any shell or command specified by the user when -the certificate is used for authentication. +the custom certificate is used for authentication. .Pp .It Ic no-agent-forwarding Disable @@ -1028,125 +910,37 @@ .It Ic permit-X11-forwarding Allows X11 forwarding. .Pp -.It Ic no-touch-required -Do not require signatures made using this key include demonstration -of user presence (e.g. by having the user touch the authenticator). -This option only makes sense for the FIDO authenticator algorithms -.Cm ecdsa-sk -and -.Cm ed25519-sk . -.Pp .It Ic source-address Ns = Ns Ar address_list -Restrict the source addresses from which the certificate is considered valid. +Restrict the source addresses from which the custom certificate is considered valid. The .Ar address_list is a comma-separated list of one or more address/netmask pairs in CIDR format. -.Pp -.It Ic verify-required -Require signatures made using this key indicate that the user was first -verified. -This option only makes sense for the FIDO authenticator algorithms -.Cm ecdsa-sk -and -.Cm ed25519-sk . -Currently PIN authentication is the only supported verification method, -but other methods may be supported in the future. .El .Pp At present, no standard options are valid for host keys. .Pp -Finally, certificates may be defined with a validity lifetime. +Finally, custom certificates may be defined with a validity lifetime. The .Fl V -option allows specification of certificate start and end times. -A certificate that is presented at a time outside this range will not be +option allows specification of custom certificate start and end times. +A custom certificate that is presented at a time outside this range will not be considered valid. -By default, certificates are valid from the +By default, custom certificates are valid from the .Ux Epoch to the distant future. .Pp -For certificates to be used for user or host authentication, the CA +For custom certificates to be used for user or host authentication, the CA public key must be trusted by .Xr sshd 8 or .Xr ssh 1 . Refer to those manual pages for details. -.Sh FIDO AUTHENTICATOR -.Nm -is able to generate FIDO authenticator-backed keys, after which -they may be used much like any other key type supported by OpenSSH, so -long as the hardware authenticator is attached when the keys are used. -FIDO authenticators generally require the user to explicitly authorise -operations by touching or tapping them. -FIDO keys consist of two parts: a key handle part stored in the -private key file on disk, and a per-device private key that is unique -to each FIDO authenticator and that cannot be exported from the -authenticator hardware. -These are combined by the hardware at authentication time to derive -the real key that is used to sign authentication challenges. -Supported key types are -.Cm ecdsa-sk -and -.Cm ed25519-sk . -.Pp -The options that are valid for FIDO keys are: -.Bl -tag -width Ds -.It Cm application -Override the default FIDO application/origin string of -.Dq ssh: . -This may be useful when generating host or domain-specific resident keys. -The specified application string must begin with -.Dq ssh: . -.It Cm challenge Ns = Ns Ar path -Specifies a path to a challenge string that will be passed to the -FIDO authenticator during key generation. -The challenge string may be used as part of an out-of-band -protocol for key enrollment -(a random challenge is used by default). -.It Cm device -Explicitly specify a -.Xr fido 4 -device to use, rather than letting the authenticator middleware select one. -.It Cm no-touch-required -Indicate that the generated private key should not require touch -events (user presence) when making signatures. -Note that -.Xr sshd 8 -will refuse such signatures by default, unless overridden via -an authorized_keys option. -.It Cm resident -Indicate that the key handle should be stored on the FIDO -authenticator itself. -This makes it easier to use the authenticator on multiple computers. -Resident keys may be supported on FIDO2 authenticators and typically -require that a PIN be set on the authenticator prior to generation. -Resident keys may be loaded off the authenticator using -.Xr ssh-add 1 . -Storing both parts of a key on a FIDO authenticator increases the likelihood -of an attacker being able to use a stolen authenticator device. -.It Cm user -A username to be associated with a resident key, -overriding the empty default username. -Specifying a username may be useful when generating multiple resident keys -for the same application name. -.It Cm verify-required -Indicate that this private key should require user verification for -each signature. -Not all FIDO authenticators support this option. -Currently PIN authentication is the only supported verification method, -but other methods may be supported in the future. -.It Cm write-attestation Ns = Ns Ar path -May be used at key generation time to record the attestation data -returned from FIDO authenticators during key generation. -This information is potentially sensitive. -By default, this information is discarded. -.El .Sh KEY REVOCATION LISTS .Nm -is able to manage OpenSSH format Key Revocation Lists (KRLs). -These binary files specify keys or certificates to be revoked using a -compact format, taking as little as one bit per certificate if they are being +is able to manage OpenSSH format custom Key Revocation Lists (KRLs). +These binary files specify keys or custom certificates to be revoked using a +compact format, taking as little as one bit per custom certificate if they are being revoked by serial number. .Pp KRLs may be generated using the @@ -1157,18 +951,18 @@ The files may either contain a KRL specification (see below) or public keys, listed one per line. Plain public keys are revoked by listing their hash or contents in the KRL and -certificates revoked by serial number or key ID (if the serial is zero or +custom certificates revoked by serial number or key ID (if the serial is zero or not available). .Pp Revoking keys using a KRL specification offers explicit control over the types of record used to revoke keys and may be used to directly revoke -certificates by serial number or key ID without having the complete original -certificate on hand. +custom certificates by serial number or key ID without having the complete original +custom certificate on hand. A KRL specification consists of lines containing one of the following directives followed by a colon and some directive-specific information. .Bl -tag -width Ds .It Cm serial : Ar serial_number Ns Op - Ns Ar serial_number -Revokes a certificate with the specified serial number. +Revokes a custom certificate with the specified serial number. Serial numbers are 64-bit values, not including zero and may be expressed in decimal, hex or octal. If two serial numbers are specified separated by a hyphen, then the range @@ -1179,7 +973,7 @@ .Fl s option. .It Cm id : Ar key_id -Revokes a certificate with the specified key ID string. +Revokes a custom certificate with the specified key ID string. The CA key must have been specified on the .Nm command line using the @@ -1187,7 +981,7 @@ option. .It Cm key : Ar public_key Revokes the specified key. -If a certificate is listed, then it is revoked as a plain public key. +If a custom certificate is listed, then it is revoked as a plain public key. .It Cm sha1 : Ar public_key Revokes the specified key by including its SHA1 hash in the KRL. .It Cm sha256 : Ar public_key @@ -1222,86 +1016,66 @@ .Nm will exit with a non-zero exit status. A zero exit status will only be returned if no key was revoked. -.Sh ALLOWED SIGNERS -When verifying signatures, -.Nm -uses a simple list of identities and keys to determine whether a signature -comes from an authorized source. -This "allowed signers" file uses a format patterned after the -AUTHORIZED_KEYS FILE FORMAT described in -.Xr sshd 8 . -Each line of the file contains the following space-separated fields: -principals, options, keytype, base64-encoded key. -Empty lines and lines starting with a -.Ql # -are ignored as comments. -.Pp -The principals field is a pattern-list (see PATTERNS in -.Xr ssh_config 5 ) -consisting of one or more comma-separated USER@DOMAIN identity patterns -that are accepted for signing. -When verifying, the identity presented via the -.Fl I -option must match a principals pattern in order for the corresponding key to be -considered acceptable for verification. -.Pp -The options (if present) consist of comma-separated option specifications. -No spaces are permitted, except within double quotes. -The following option specifications are supported (note that option keywords -are case-insensitive): -.Bl -tag -width Ds -.It Cm cert-authority -Indicates that this key is accepted as a certificate authority (CA) and -that certificates signed by this CA may be accepted for verification. -.It Cm namespaces Ns = Ns "namespace-list" -Specifies a pattern-list of namespaces that are accepted for this key. -If this option is present, the signature namespace embedded in the -signature object and presented on the verification command-line must -match the specified list before the key will be considered acceptable. -.It Cm valid-after Ns = Ns "timestamp" -Indicates that the key is valid for use at or after the specified timestamp, -which may be a date or time in the YYYYMMDD[Z] or YYYYMMDDHHMM[SS][Z] formats. -Dates and times will be interpreted in the current system time zone unless -suffixed with a Z character, which causes them to be interpreted in the UTC -time zone. -.It Cm valid-before Ns = Ns "timestamp" -Indicates that the key is valid for use at or before the specified timestamp. -.El -.Pp -When verifying signatures made by certificates, the expected principal -name must match both the principals pattern in the allowed signers file and -the principals embedded in the certificate itself. -.Pp -An example allowed signers file: -.Bd -literal -offset 3n -# Comments allowed at start of line -user1@example.com,user2@example.com ssh-rsa AAAAX1... -# A certificate authority, trusted for all principals in a domain. -*@example.com cert-authority ssh-ed25519 AAAB4... -# A key that is accepted only for file signing. -user2@example.com namespaces="file" ssh-ed25519 AAA41... -.Ed .Sh ENVIRONMENT .Bl -tag -width Ds -.It Ev SSH_SK_PROVIDER -Specifies a path to a library that will be used when loading any -FIDO authenticator-hosted keys, overriding the default of using -the built-in USB HID support. +.It Ev SSH_ASKPASS +If +.Nm +needs a passphrase, it will read the passphrase from the current +terminal if it was run from a terminal. +If +.Nm +does not have a terminal associated with it but +.Ev "DISPLAY" and "SSH_ASKPASS" +are set, it will execute the program specified by +.Ev SSH_ASKPASS +that may open a X11 window to read the passphrase. +For keys from +.Dq engine +or +.Dq store +.Ev SSH_ASKPASS +is preferred over associated terminal. +Note if +.Ev SSH_ASKPASS +is not set will be executed program +.Nm ssh-askpass +located in +.Dq libexec +directory. +(Note that on some machines it +may be necessary to redirect the input from +.Pa /dev/null +to make this work.) +.Pp +Remark: On Android +.Ev DISPLAY +is ignored and +.Ev SSH_ASKPASS +is preferred over associated terminal. +.It Ev SSH_ENGINE_CONF +Overrides default location of engine configuration file. .El .Sh FILES .Bl -tag -width Ds -compact .It Pa ~/.ssh/id_dsa .It Pa ~/.ssh/id_ecdsa -.It Pa ~/.ssh/id_ecdsa_sk .It Pa ~/.ssh/id_ed25519 -.It Pa ~/.ssh/id_ed25519_sk .It Pa ~/.ssh/id_rsa -Contains the DSA, ECDSA, authenticator-hosted ECDSA, Ed25519, -authenticator-hosted Ed25519 or RSA authentication identity of the user. +Contains the DSA, ECDSA, Ed25519 or RSA +authentication identity of the user. +.Pp This file should not be readable by anyone but the user. +.Pp +For RSA, ECDSA, Ed25519 or DSA identity file may contain X.509 certificate that +match it. In addition file may contain extra X.509 certificates. +Extra certificates along with certificates from X.509 store are used +to build chain of certificates leading to a trusted certificate +authority if required by public key algorithm format. +.Pp It is possible to specify a passphrase when generating the key; that passphrase will be -used to encrypt the private part of this file using 128-bit AES. +used to encrypt the private part of this file using 256-bit AES. This file is not automatically accessed by .Nm but it is offered as the default file for the private key. @@ -1310,17 +1084,40 @@ .Pp .It Pa ~/.ssh/id_dsa.pub .It Pa ~/.ssh/id_ecdsa.pub -.It Pa ~/.ssh/id_ecdsa_sk.pub .It Pa ~/.ssh/id_ed25519.pub -.It Pa ~/.ssh/id_ed25519_sk.pub .It Pa ~/.ssh/id_rsa.pub -Contains the DSA, ECDSA, authenticator-hosted ECDSA, Ed25519, -authenticator-hosted Ed25519 or RSA public key for authentication. +Contains the DSA, ECDSA, Ed25519 or RSA +public key for authentication. The contents of this file should be added to .Pa ~/.ssh/authorized_keys on all machines where the user wishes to log in using public key authentication. There is no need to keep the contents of this file secret. +If file +.Pa ~/.ssh/id_rsa , +.Pa ~/.ssh/id_ecdsa , +.Pa ~/.ssh/id_ed25519 , +or +.Pa ~/.ssh/id_dsa +contain RSA/ECDSA/Ed25519/DSA private key and X.509 certificates +public key file must contain certificate that match private key! +Use +.Nm +with option -y to regenerate its content. +Note in case with X.509 certificate you can append content to +.Pa ~/.ssh/authorized_keys +or to add certificate +.Dq Distinguished Name +/ +.Dq Subject +in corresponding format to +.Dq authorized keys +file. See +.Xr sshd 8 . +Using distinguished name is preferred as X.509 certificate could +be renewed and after renewal there is no need to update +.Dq authorized keys +file. .Pp .It Pa /etc/moduli Contains Diffie-Hellman groups used for DH-GEX. @@ -1333,13 +1130,63 @@ .Xr ssh-agent 1 , .Xr moduli 5 , .Xr sshd 8 +.Sh CONFORMING TO +.Bl -enum +.It +.Rs +.%A D. Eastlake +.%D March 1999 +.%R RFC 2535 +.%T Domain Name System Security Extensions +.Re +.It .Rs +.%A D. Eastlake +.%D March 1999 +.%R RFC 2536 +.%T DSA KEYs and SIGs in the Domain Name System (DNS) +.Re +.It +.Rs +.%A D. Eastlake +.%D March 1999 +.%R RFC 2537 +.%T RSA/MD5 KEYs and SIGs in the Domain Name System (DNS) +.Re +.It +.Rs +.%A D. Eastlake +.%A O. Gudmundsson +.%D March 1999 +.%R RFC 2538 +.%T Storing Certificates in the Domain Name System (DNS) +.Re +.It +.Rs +.%A D. Eastlake 3rd +.%D May 2001 +.%R RFC 3110 +.%T RSA/SHA-1 SIGs and RSA KEYs in the Domain Name System (DNS) +.Re +.It +.Rs +.%A J. Schlyter +.%A W. Griffin +.%D January 2006 +.%R RFC 4255 +.%T Using DNS to Securely Publish Secure Shell (SSH) Key Fingerprints +.Re +.It +.Rs +.%A J. Galbraith +.%A R. Thayer +.%D November 2006 .%R RFC 4716 -.%T "The Secure Shell (SSH) Public Key File Format" -.%D 2006 +.%T The Secure Shell (SSH) Public Key File Format .Re +.El .Sh AUTHORS -OpenSSH is a derivative of the original and free +PKIX-SSH is a derivative of the original and free ssh 1.2.12 release by Tatu Ylonen. Aaron Campbell, Bob Beck, Markus Friedl, Niels Provos, Theo de Raadt and Dug Song @@ -1347,3 +1194,4 @@ created OpenSSH. Markus Friedl contributed the support for SSH protocol versions 1.5 and 2.0. +Roumen Petrov contributed support for X.509 certificates. diff -ruN openssh-9.4p1/ssh-keygen.c openssh-9.4p1+x509-14.2.1/ssh-keygen.c --- openssh-9.4p1/ssh-keygen.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/ssh-keygen.c 2023-08-20 10:07:01.000000000 +0300 @@ -10,8 +10,31 @@ * software must be clearly marked as such, and if the derived work is * incompatible with the protocol description in the RFC file, it must be * called by a name other than "ssh" or "Secure Shell". + * + * Copyright (c) 2005-2023 Roumen Petrov. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#define SSHKEY_INTERNAL #include "includes.h" #include @@ -21,7 +44,10 @@ #ifdef WITH_OPENSSL #include #include -#include "openbsd-compat/openssl-compat.h" +#include "evp-compat.h" +#ifdef HAVE_FIPSCHECK_H +# include +#endif #endif #ifdef HAVE_STDINT_H @@ -44,7 +70,10 @@ #include #include "xmalloc.h" -#include "sshkey.h" +#include "ssh-x509.h" +#include "key-eng.h" +#include "ssh-xkalg.h" +#include "compat.h" #include "authfile.h" #include "sshbuf.h" #include "pathnames.h" @@ -62,9 +91,6 @@ #include "digest.h" #include "utf8.h" #include "authfd.h" -#include "sshsig.h" -#include "ssh-sk.h" -#include "sk-api.h" /* XXX for SSH_SK_USER_PRESENCE_REQD; remove */ #include "cipher.h" #ifdef WITH_OPENSSL @@ -121,13 +147,11 @@ static u_int64_t cert_valid_to = ~0ULL; /* Certificate options */ -#define CERTOPT_X_FWD (1) -#define CERTOPT_AGENT_FWD (1<<1) -#define CERTOPT_PORT_FWD (1<<2) -#define CERTOPT_PTY (1<<3) -#define CERTOPT_USER_RC (1<<4) -#define CERTOPT_NO_REQUIRE_USER_PRESENCE (1<<5) -#define CERTOPT_REQUIRE_VERIFY (1<<6) +#define CERTOPT_X_FWD (1) +#define CERTOPT_AGENT_FWD (1<<1) +#define CERTOPT_PORT_FWD (1<<2) +#define CERTOPT_PTY (1<<3) +#define CERTOPT_USER_RC (1<<4) #define CERTOPT_DEFAULT (CERTOPT_X_FWD|CERTOPT_AGENT_FWD| \ CERTOPT_PORT_FWD|CERTOPT_PTY|CERTOPT_USER_RC) static u_int32_t certflags_flags = CERTOPT_DEFAULT; @@ -155,13 +179,10 @@ /* Load key from this PKCS#11 provider */ static char *pkcs11provider = NULL; -/* FIDO/U2F provider to use */ -static char *sk_provider = NULL; - /* Format for writing private keys */ -static int private_key_format = SSHKEY_PRIVATE_OPENSSH; +static int private_key_format = SSHKEY_PRIVATE_PKCS8; -/* Cipher for new-format private keys */ +/* Cipher for private keys in OpenSSH proprietary format */ static char *openssh_format_cipher = NULL; /* Number of KDF rounds to derive new format keys. */ @@ -179,6 +200,30 @@ unsigned long); #endif + +typedef void (*fingerprint_format_f)(const struct sshkey *public, + const char *comment, const char *fp, va_list ap); + +static void +fingerprint_format(const struct sshkey *public, const char *comment, + fingerprint_format_f format_f, ...); + + +static void +print_fingerprint_one_key(const struct sshkey *public, + const char *comment, const char *fp, va_list ap) +{ + UNUSED(ap); + mprintf("%u %s %s (%s)\n", sshkey_size(public), fp, + comment ? comment : "no comment", sshkey_type(public)); +} + +static inline void +fingerprint_one_key(const struct sshkey *public, const char *comment) { + fingerprint_format(public, comment, print_fingerprint_one_key); +} + + static void type_bits_valid(int type, const char *name, u_int32_t *bitsp) { @@ -208,8 +253,8 @@ #ifdef WITH_OPENSSL switch (type) { case KEY_DSA: - if (*bitsp != 1024) - fatal("Invalid DSA key length: must be 1024 bits"); + if (*bitsp != SSH_DSA_BITS) + fatal("Invalid DSA key length: must be %d bits", SSH_DSA_BITS); break; case KEY_RSA: if (*bitsp < SSH_RSA_MINIMUM_MODULUS_SIZE) @@ -244,20 +289,21 @@ char yesno[3]; struct stat st; - if (stat(filename, &st) != 0) + if (stat(filename, &st) == -1) return 1; - printf("%s already exists.\n", filename); - printf("Overwrite (y/n)? "); - fflush(stdout); + + fprintf(stderr, "%s already exists.\n", filename); + fprintf(stderr, "Overwrite (y/n)? :"); + fflush(stderr); /*non-buffered but on some systems ...*/ + if (fgets(yesno, sizeof(yesno), stdin) == NULL) return 0; - if (yesno[0] != 'y' && yesno[0] != 'Y') - return 0; - return 1; + + return yesno[0] == 'y' || yesno[0] == 'Y'; } static void -ask_filename(struct passwd *pw, const char *prompt) +ask_filename(const struct passwd *pw, const char *prompt) { char buf[1024]; char *name = NULL; @@ -275,10 +321,6 @@ case KEY_ECDSA: name = _PATH_SSH_CLIENT_ID_ECDSA; break; - case KEY_ECDSA_SK_CERT: - case KEY_ECDSA_SK: - name = _PATH_SSH_CLIENT_ID_ECDSA_SK; - break; #endif case KEY_RSA_CERT: case KEY_RSA: @@ -288,14 +330,12 @@ case KEY_ED25519_CERT: name = _PATH_SSH_CLIENT_ID_ED25519; break; - case KEY_ED25519_SK: - case KEY_ED25519_SK_CERT: - name = _PATH_SSH_CLIENT_ID_ED25519_SK; - break; +#ifdef WITH_XMSS case KEY_XMSS: case KEY_XMSS_CERT: name = _PATH_SSH_CLIENT_ID_XMSS; break; +#endif default: fatal("bad key type"); } @@ -312,27 +352,47 @@ have_identity = 1; } +static int +Xstat(char *filename) +{ +#ifdef USE_OPENSSL_ENGINE + if (strncmp(filename, "engine:", 7) == 0) return 0; +#endif +#ifdef USE_OPENSSL_STORE2 + if (strncmp(filename, "store:", 6) == 0) return 0; +#endif +{ struct stat st; + return stat(filename, &st); +} +} + static struct sshkey * load_identity(const char *filename, char **commentp) { - char *pass; struct sshkey *prv; int r; - if (commentp != NULL) - *commentp = NULL; - if ((r = sshkey_load_private(filename, "", &prv, commentp)) == 0) - return prv; + /* NOTE: engine or store based keys use method provided + * by crypto-library to get passphrase if needed. + */ + r = sshkey_load_private(filename, "", &prv, commentp); + if (r == 0) return prv; + if (r != SSH_ERR_KEY_WRONG_PASSPHRASE) fatal_r(r, "Load key \"%s\"", filename); + +{ /* try passphrase only for file based keys */ + char *pass; if (identity_passphrase) pass = xstrdup(identity_passphrase); else pass = read_passphrase("Enter passphrase: ", RP_ALLOW_STDIN); r = sshkey_load_private(filename, pass, &prv, commentp); freezero(pass, strlen(pass)); +} if (r != 0) fatal_r(r, "Load key \"%s\"", filename); + return prv; } @@ -343,7 +403,7 @@ #ifdef WITH_OPENSSL static void -do_convert_to_ssh2(struct passwd *pw, struct sshkey *k) +do_convert_to_ssh2(const struct passwd *pw, struct sshkey *k) { struct sshbuf *b; char comment[61], *b64; @@ -358,7 +418,7 @@ /* Comment + surrounds must fit into 72 chars (RFC 4716 sec 3.3) */ snprintf(comment, sizeof(comment), - "%u-bit %s, converted by %s@%s from OpenSSH", + "%u-bit %s, converted by %s@%s from " PACKAGE_NAME, sshkey_size(k), sshkey_type(k), pw->pw_name, hostname); @@ -372,56 +432,13 @@ exit(0); } -static void -do_convert_to_pkcs8(struct sshkey *k) -{ - switch (sshkey_type_plain(k->type)) { - case KEY_RSA: - if (!PEM_write_RSA_PUBKEY(stdout, k->rsa)) - fatal("PEM_write_RSA_PUBKEY failed"); - break; - case KEY_DSA: - if (!PEM_write_DSA_PUBKEY(stdout, k->dsa)) - fatal("PEM_write_DSA_PUBKEY failed"); - break; -#ifdef OPENSSL_HAS_ECC - case KEY_ECDSA: - if (!PEM_write_EC_PUBKEY(stdout, k->ecdsa)) - fatal("PEM_write_EC_PUBKEY failed"); - break; -#endif - default: - fatal_f("unsupported key type %s", sshkey_type(k)); - } - exit(0); -} -static void -do_convert_to_pem(struct sshkey *k) -{ - switch (sshkey_type_plain(k->type)) { - case KEY_RSA: - if (!PEM_write_RSAPublicKey(stdout, k->rsa)) - fatal("PEM_write_RSAPublicKey failed"); - break; - case KEY_DSA: - if (!PEM_write_DSA_PUBKEY(stdout, k->dsa)) - fatal("PEM_write_DSA_PUBKEY failed"); - break; -#ifdef OPENSSL_HAS_ECC - case KEY_ECDSA: - if (!PEM_write_EC_PUBKEY(stdout, k->ecdsa)) - fatal("PEM_write_EC_PUBKEY failed"); - break; -#endif - default: - fatal_f("unsupported key type %s", sshkey_type(k)); - } - exit(0); -} +/* defined in sshkey-crypto.c but used only localy here */ +extern int +sshkey_public_to_fp(struct sshkey *key, FILE *fp, int format); static void -do_convert_to(struct passwd *pw) +do_convert_to(const struct passwd *pw) { struct sshkey *k; struct stat st; @@ -438,10 +455,12 @@ do_convert_to_ssh2(pw, k); break; case FMT_PKCS8: - do_convert_to_pkcs8(k); + if (sshkey_public_to_fp(k, stdout, SSHKEY_PRIVATE_PKCS8) != 0) + fatal_f("unsupported key type %s", sshkey_type(k)); break; case FMT_PEM: - do_convert_to_pem(k); + if (sshkey_public_to_fp(k, stdout, SSHKEY_PRIVATE_PEM) != 0) + fatal_f("unsupported key type %s", sshkey_type(k)); break; default: fatal_f("unknown key format %d", convert_format); @@ -449,43 +468,22 @@ exit(0); } -/* - * This is almost exactly the bignum1 encoding, but with 32 bit for length - * instead of 16. - */ -static void -buffer_get_bignum_bits(struct sshbuf *b, BIGNUM *value) -{ - u_int bytes, bignum_bits; - int r; - if ((r = sshbuf_get_u32(b, &bignum_bits)) != 0) - fatal_fr(r, "parse"); - bytes = (bignum_bits + 7) / 8; - if (sshbuf_len(b) < bytes) - fatal_f("input buffer too small: need %d have %zu", - bytes, sshbuf_len(b)); - if (BN_bin2bn(sshbuf_ptr(b), bytes, value) == NULL) - fatal_f("BN_bin2bn failed"); - if ((r = sshbuf_consume(b, bytes)) != 0) - fatal_fr(r, "consume"); -} +/* defined in sshkey-crypto.c but used only localy here */ +extern int +sshbuf_read_custom_rsa(struct sshbuf *buf, struct sshkey *key); +extern int +sshbuf_read_custom_dsa(struct sshbuf *buf, struct sshkey *key); static struct sshkey * do_convert_private_ssh2(struct sshbuf *b) { struct sshkey *key = NULL; - char *type, *cipher; const char *alg = NULL; - u_char e1, e2, e3, *sig = NULL, data[] = "abcde12345"; + u_char *sig = NULL, data[] = "abcde12345"; int r, rlen, ktype; - u_int magic, i1, i2, i3, i4; + u_int32_t magic; size_t slen; - u_long e; - BIGNUM *dsa_p = NULL, *dsa_q = NULL, *dsa_g = NULL; - BIGNUM *dsa_pub_key = NULL, *dsa_priv_key = NULL; - BIGNUM *rsa_n = NULL, *rsa_e = NULL, *rsa_d = NULL; - BIGNUM *rsa_p = NULL, *rsa_q = NULL, *rsa_iqmp = NULL; if ((r = sshbuf_get_u32(b, &magic)) != 0) fatal_fr(r, "parse magic"); @@ -495,6 +493,10 @@ SSH_COM_PRIVATE_KEY_MAGIC); return NULL; } + +{ char *type, *cipher; + u_int32_t i1, i2, i3, i4; + if ((r = sshbuf_get_u32(b, &i1)) != 0 || (r = sshbuf_get_cstring(b, &type, NULL)) != 0 || (r = sshbuf_get_cstring(b, &cipher, NULL)) != 0 || @@ -519,73 +521,25 @@ free(type); return NULL; } - if ((key = sshkey_new(ktype)) == NULL) - fatal("sshkey_new failed"); free(type); +} - switch (key->type) { + key = sshkey_new(KEY_UNSPEC); + if (key == NULL) + fatal("sshkey_new failed"); + switch (ktype) { case KEY_DSA: - if ((dsa_p = BN_new()) == NULL || - (dsa_q = BN_new()) == NULL || - (dsa_g = BN_new()) == NULL || - (dsa_pub_key = BN_new()) == NULL || - (dsa_priv_key = BN_new()) == NULL) - fatal_f("BN_new"); - buffer_get_bignum_bits(b, dsa_p); - buffer_get_bignum_bits(b, dsa_g); - buffer_get_bignum_bits(b, dsa_q); - buffer_get_bignum_bits(b, dsa_pub_key); - buffer_get_bignum_bits(b, dsa_priv_key); - if (!DSA_set0_pqg(key->dsa, dsa_p, dsa_q, dsa_g)) - fatal_f("DSA_set0_pqg failed"); - dsa_p = dsa_q = dsa_g = NULL; /* transferred */ - if (!DSA_set0_key(key->dsa, dsa_pub_key, dsa_priv_key)) - fatal_f("DSA_set0_key failed"); - dsa_pub_key = dsa_priv_key = NULL; /* transferred */ + r = sshbuf_read_custom_dsa(b, key); + if (r != 0) + fatal_fr(r, "custom dsa failed"); break; case KEY_RSA: - if ((r = sshbuf_get_u8(b, &e1)) != 0 || - (e1 < 30 && (r = sshbuf_get_u8(b, &e2)) != 0) || - (e1 < 30 && (r = sshbuf_get_u8(b, &e3)) != 0)) - fatal_fr(r, "parse RSA"); - e = e1; - debug("e %lx", e); - if (e < 30) { - e <<= 8; - e += e2; - debug("e %lx", e); - e <<= 8; - e += e3; - debug("e %lx", e); - } - if ((rsa_e = BN_new()) == NULL) - fatal_f("BN_new"); - if (!BN_set_word(rsa_e, e)) { - BN_clear_free(rsa_e); - sshkey_free(key); - return NULL; - } - if ((rsa_n = BN_new()) == NULL || - (rsa_d = BN_new()) == NULL || - (rsa_p = BN_new()) == NULL || - (rsa_q = BN_new()) == NULL || - (rsa_iqmp = BN_new()) == NULL) - fatal_f("BN_new"); - buffer_get_bignum_bits(b, rsa_d); - buffer_get_bignum_bits(b, rsa_n); - buffer_get_bignum_bits(b, rsa_iqmp); - buffer_get_bignum_bits(b, rsa_q); - buffer_get_bignum_bits(b, rsa_p); - if (!RSA_set0_key(key->rsa, rsa_n, rsa_e, rsa_d)) - fatal_f("RSA_set0_key failed"); - rsa_n = rsa_e = rsa_d = NULL; /* transferred */ - if (!RSA_set0_factors(key->rsa, rsa_p, rsa_q)) - fatal_f("RSA_set0_factors failed"); - rsa_p = rsa_q = NULL; /* transferred */ - if ((r = ssh_rsa_complete_crt_parameters(key, rsa_iqmp)) != 0) - fatal_fr(r, "generate RSA parameters"); - BN_clear_free(rsa_iqmp); + r = sshbuf_read_custom_rsa(b, key); + if (r != 0) + fatal_fr(r, "custom rsa failed"); + #ifdef HAVE_EVP_SHA256 alg = "rsa-sha2-256"; + #endif break; } rlen = sshbuf_len(b); @@ -593,12 +547,15 @@ error_f("remaining bytes in key blob %d", rlen); /* try the key */ - if ((r = sshkey_sign(key, &sig, &slen, data, sizeof(data), - alg, NULL, NULL, 0)) != 0) +{ ssh_compat ctx_compat = { 0, 0 }; + ssh_sign_ctx sctx = { alg, key, &ctx_compat, NULL, NULL }; + ssh_verify_ctx vctx = { alg, key, &ctx_compat }; + + if ((r = sshkey_sign(&sctx, &sig, &slen, data, sizeof(data))) != 0) error_fr(r, "signing with converted key failed"); - else if ((r = sshkey_verify(key, sig, slen, data, sizeof(data), - alg, 0, NULL)) != 0) + else if ((r = sshkey_verify(&vctx, sig, slen, data, sizeof(data))) != 0) error_fr(r, "verification with converted key failed"); +} if (r != 0) { sshkey_free(key); free(sig); @@ -635,7 +592,7 @@ } static void -do_convert_from_ssh2(struct passwd *pw, struct sshkey **k, int *private) +do_convert_from_ssh2(struct sshkey **k, int *private) { int r, blen, escaped = 0; u_int len; @@ -686,70 +643,28 @@ fclose(fp); } +/* defined in sshkey-crypto.c but used only localy here */ +extern int +sshkey_public_from_fp(FILE *fp, int format, struct sshkey **key); + static void -do_convert_from_pkcs8(struct sshkey **k, int *private) +do_convert_from_file(struct sshkey **k, int format) { - EVP_PKEY *pubkey; - FILE *fp; + int r; - if ((fp = fopen(identity_file, "r")) == NULL) +{ FILE *fp = fopen(identity_file, "r"); + if (fp == NULL) fatal("%s: %s: %s", __progname, identity_file, strerror(errno)); - if ((pubkey = PEM_read_PUBKEY(fp, NULL, NULL, NULL)) == NULL) { - fatal_f("%s is not a recognised public key format", - identity_file); - } + r = sshkey_public_from_fp(fp, format, k); fclose(fp); - switch (EVP_PKEY_base_id(pubkey)) { - case EVP_PKEY_RSA: - if ((*k = sshkey_new(KEY_UNSPEC)) == NULL) - fatal("sshkey_new failed"); - (*k)->type = KEY_RSA; - (*k)->rsa = EVP_PKEY_get1_RSA(pubkey); - break; - case EVP_PKEY_DSA: - if ((*k = sshkey_new(KEY_UNSPEC)) == NULL) - fatal("sshkey_new failed"); - (*k)->type = KEY_DSA; - (*k)->dsa = EVP_PKEY_get1_DSA(pubkey); - break; -#ifdef OPENSSL_HAS_ECC - case EVP_PKEY_EC: - if ((*k = sshkey_new(KEY_UNSPEC)) == NULL) - fatal("sshkey_new failed"); - (*k)->type = KEY_ECDSA; - (*k)->ecdsa = EVP_PKEY_get1_EC_KEY(pubkey); - (*k)->ecdsa_nid = sshkey_ecdsa_key_to_nid((*k)->ecdsa); - break; -#endif - default: - fatal_f("unsupported pubkey type %d", - EVP_PKEY_base_id(pubkey)); - } - EVP_PKEY_free(pubkey); - return; } + if (r == 0) return; -static void -do_convert_from_pem(struct sshkey **k, int *private) -{ - FILE *fp; - RSA *rsa; - - if ((fp = fopen(identity_file, "r")) == NULL) - fatal("%s: %s: %s", __progname, identity_file, strerror(errno)); - if ((rsa = PEM_read_RSAPublicKey(fp, NULL, NULL, NULL)) != NULL) { - if ((*k = sshkey_new(KEY_UNSPEC)) == NULL) - fatal("sshkey_new failed"); - (*k)->type = KEY_RSA; - (*k)->rsa = rsa; - fclose(fp); - return; - } - fatal_f("unrecognised raw private key format"); + fatal_r(r, "%s: unrecognised public key", identity_file); } static void -do_convert_from(struct passwd *pw) +do_convert_from(const struct passwd *pw) { struct sshkey *k = NULL; int r, private = 0, ok = 0; @@ -762,17 +677,18 @@ switch (convert_format) { case FMT_RFC4716: - do_convert_from_ssh2(pw, &k, &private); + do_convert_from_ssh2(&k, &private); break; case FMT_PKCS8: - do_convert_from_pkcs8(&k, &private); + do_convert_from_file(&k, SSHKEY_PRIVATE_PKCS8); break; case FMT_PEM: - do_convert_from_pem(&k, &private); + do_convert_from_file(&k, SSHKEY_PRIVATE_PEM); break; default: fatal_f("unknown key format %d", convert_format); } + if (k == NULL) exit(1); if (!private) { if ((r = sshkey_write(k, stdout)) == 0) @@ -780,26 +696,23 @@ if (ok) fprintf(stdout, "\n"); } else { - switch (k->type) { - case KEY_DSA: - ok = PEM_write_DSAPrivateKey(stdout, k->dsa, NULL, - NULL, 0, NULL, NULL); - break; -#ifdef OPENSSL_HAS_ECC - case KEY_ECDSA: - ok = PEM_write_ECPrivateKey(stdout, k->ecdsa, NULL, - NULL, 0, NULL, NULL); - break; + BIO *out = BIO_new_fp(stdout, BIO_NOCLOSE); + if (out == NULL) goto done; +#ifdef VMS + { + BIO *tmpbio = BIO_new(BIO_f_linebuffer()); + out = BIO_push(tmpbio, out); + } #endif - case KEY_RSA: - ok = PEM_write_RSAPrivateKey(stdout, k->rsa, NULL, - NULL, 0, NULL, NULL); - break; - default: + r = sshkey_private_to_bio(k, out, "", private_key_format); + if (r == 0) + ok = 1; + else if (r == SSH_ERR_INVALID_ARGUMENT) fatal_f("unsupported key type %s", sshkey_type(k)); - } + BIO_free_all(out); } +done: if (!ok) fatal("key write failed"); sshkey_free(k); @@ -808,44 +721,36 @@ #endif static void -do_print_public(struct passwd *pw) +do_print_public(const struct passwd *pw) { struct sshkey *prv; - struct stat st; int r; char *comment = NULL; if (!have_identity) ask_filename(pw, "Enter file in which the key is"); - if (stat(identity_file, &st) == -1) + if (Xstat(identity_file) == -1) fatal("%s: %s", identity_file, strerror(errno)); + prv = load_identity(identity_file, &comment); if ((r = sshkey_write(prv, stdout)) != 0) fatal_fr(r, "write key"); if (comment != NULL && *comment != '\0') fprintf(stdout, " %s", comment); fprintf(stdout, "\n"); - if (sshkey_is_sk(prv)) { - debug("sk_application: \"%s\", sk_flags 0x%02x", - prv->sk_application, prv->sk_flags); - } + sshkey_free(prv); free(comment); exit(0); } static void -do_download(struct passwd *pw) +do_download(void) { #ifdef ENABLE_PKCS11 - struct sshkey **keys = NULL; + struct sshkey **keys; + char **comments; int i, nkeys; - enum sshkey_fp_rep rep; - int fptype; - char *fp, *ra, **comments = NULL; - - fptype = print_bubblebabble ? SSH_DIGEST_SHA1 : fingerprint_hash; - rep = print_bubblebabble ? SSH_FP_BUBBLEBABBLE : SSH_FP_DEFAULT; pkcs11_init(1); nkeys = pkcs11_add_provider(pkcs11provider, NULL, &keys, &comments); @@ -853,21 +758,15 @@ fatal("cannot read public key from pkcs11"); for (i = 0; i < nkeys; i++) { if (print_fingerprint) { - fp = sshkey_fingerprint(keys[i], fptype, rep); - ra = sshkey_fingerprint(keys[i], fingerprint_hash, - SSH_FP_RANDOMART); - if (fp == NULL || ra == NULL) - fatal_f("sshkey_fingerprint fail"); - printf("%u %s %s (PKCS11 key)\n", sshkey_size(keys[i]), - fp, sshkey_type(keys[i])); - if (log_level_get() >= SYSLOG_LEVEL_VERBOSE) - printf("%s\n", ra); - free(ra); - free(fp); + fingerprint_one_key(keys[i], "PKCS11 key"); } else { (void) sshkey_write(keys[i], stdout); /* XXX check */ - fprintf(stdout, "%s%s\n", - *(comments[i]) == '\0' ? "" : " ", comments[i]); + /* let exclude "comment" for X.509 certificate + * as this is doubling information + */ + if (!sshkey_is_x509(keys[i]) && *(comments[i]) != '\0') + fprintf(stdout, " %s", comments[i]); + fprintf(stdout, "\n"); } free(comments[i]); sshkey_free(keys[i]); @@ -897,23 +796,41 @@ } static void -fingerprint_one_key(const struct sshkey *public, const char *comment) +fingerprint_format(const struct sshkey *public, const char *comment, + fingerprint_format_f format_f, ...) { - char *fp = NULL, *ra = NULL; + char *fp; enum sshkey_fp_rep rep; int fptype; fptype = print_bubblebabble ? SSH_DIGEST_SHA1 : fingerprint_hash; rep = print_bubblebabble ? SSH_FP_BUBBLEBABBLE : SSH_FP_DEFAULT; + fp = sshkey_fingerprint(public, fptype, rep); - ra = sshkey_fingerprint(public, fingerprint_hash, SSH_FP_RANDOMART); - if (fp == NULL || ra == NULL) - fatal_f("sshkey_fingerprint failed"); - mprintf("%u %s %s (%s)\n", sshkey_size(public), fp, - comment ? comment : "no comment", sshkey_type(public)); - if (log_level_get() >= SYSLOG_LEVEL_VERBOSE) - printf("%s\n", ra); - free(ra); + if (fp == NULL) { + if (sshkey_is_x509(public)) + verbose("Key only with X.509 certificate distinguished name"); + else + error("Cannot obtain key fingerprint"); + return; + } +{ + va_list ap; + va_start(ap, format_f); + format_f(public, comment, fp, ap); + va_end(ap); +} + free(fp); + + if (get_log_level() < SYSLOG_LEVEL_VERBOSE) + return; + + fp = sshkey_fingerprint(public, fingerprint_hash, SSH_FP_RANDOMART); + if (fp == NULL) { + error("Cannot obtain key random-art"); + return; + } + printf("%s\n", fp); free(fp); } @@ -922,7 +839,7 @@ { struct stat st; char *comment = NULL; - struct sshkey *privkey = NULL, *pubkey = NULL; + struct sshkey *pubkey = NULL, *privkey = NULL; int r; if (stat(identity_file, &st) == -1) @@ -945,11 +862,11 @@ } static void -do_fingerprint(struct passwd *pw) +do_fingerprint(const struct passwd *pw) { FILE *f; struct sshkey *public = NULL; - char *comment = NULL, *cp, *ep, *line = NULL; + char *cp, *ep, *line = NULL; size_t linesize = 0; int i, invalid = 1; const char *path; @@ -966,6 +883,7 @@ fatal("%s: %s: %s", __progname, path, strerror(errno)); while (getline(&line, &linesize, f) != -1) { + char *comment = NULL; lnum++; cp = line; cp[strcspn(cp, "\n")] = '\0'; @@ -997,7 +915,6 @@ * accept a public key prefixed with a hostname or options. * Try a bare key first, otherwise skip the leading stuff. */ - comment = NULL; if ((public = try_read_key(&cp)) == NULL) { i = strtol(cp, &ep, 10); if (i == 0 || ep == NULL || @@ -1042,7 +959,7 @@ } static void -do_gen_all_hostkeys(struct passwd *pw) +do_gen_all_hostkeys(const struct passwd *pw) { struct { char *key_type; @@ -1062,7 +979,6 @@ { NULL, NULL, NULL } }; - u_int32_t bits = 0; int first = 0; struct stat st; struct sshkey *private, *public; @@ -1077,7 +993,7 @@ identity_file, key_types[i].path); /* Check whether private key exists and is not zero-length */ - if (stat(prv_file, &st) == 0) { + if (stat(prv_file, &st) != -1) { if (st.st_size != 0) goto next; } else if (errno != ENOENT) { @@ -1110,12 +1026,13 @@ goto failnext; } (void)close(fd); /* just using mkstemp() to reserve a name */ - bits = 0; + { u_int32_t bits = 0; type_bits_valid(type, NULL, &bits); if ((r = sshkey_generate(type, bits, &private)) != 0) { error_r(r, "sshkey_generate failed"); goto failnext; } + } if ((r = sshkey_from_private(private, &public)) != 0) fatal_fr(r, "sshkey_from_private"); snprintf(comment, sizeof comment, "%s@%s", pw->pw_name, @@ -1131,8 +1048,7 @@ pub_tmp, strerror(errno)); goto failnext; } - (void)fchmod(fd, 0644); - (void)close(fd); + (void)close(fd); /* just using mkstemp() to reserve a name */ if ((r = sshkey_save_public(public, pub_tmp, comment)) != 0) { error_r(r, "Unable to save public key to %s", identity_file); @@ -1140,12 +1056,12 @@ } /* Rename temporary files to their permanent locations. */ - if (rename(pub_tmp, pub_file) != 0) { + if (rename(pub_tmp, pub_file) == -1) { error("Unable to move %s into position: %s", pub_file, strerror(errno)); goto failnext; } - if (rename(prv_tmp, prv_file) != 0) { + if (rename(prv_tmp, prv_file) == -1) { error("Unable to move %s into position: %s", key_types[i].path, strerror(errno)); failnext: @@ -1227,16 +1143,21 @@ return -1; } +static void +print_fingerprint_known_hosts( + const struct sshkey *public, const char *comment, const char *fp, + va_list ap) +{ + char *host; + host = va_arg(ap, char*); + mprintf("%s %s %s%s%s\n", host, + sshkey_type(public), fp, *comment ? " ": "", comment); +} + static int known_hosts_find_delete(struct hostkey_foreach_line *l, void *_ctx) { struct known_hosts_ctx *ctx = (struct known_hosts_ctx *)_ctx; - enum sshkey_fp_rep rep; - int fptype; - char *fp = NULL, *ra = NULL; - - fptype = print_bubblebabble ? SSH_DIGEST_SHA1 : fingerprint_hash; - rep = print_bubblebabble ? SSH_FP_BUBBLEBABBLE : SSH_FP_DEFAULT; if (l->status == HKF_STATUS_MATCHED) { if (ctx->delete_host) { @@ -1266,19 +1187,8 @@ if (ctx->hash_hosts) known_hosts_hash(l, ctx); else if (print_fingerprint) { - fp = sshkey_fingerprint(l->key, fptype, rep); - ra = sshkey_fingerprint(l->key, - fingerprint_hash, SSH_FP_RANDOMART); - if (fp == NULL || ra == NULL) - fatal_f("sshkey_fingerprint failed"); - mprintf("%s %s %s%s%s\n", ctx->host, - sshkey_type(l->key), fp, - l->comment[0] ? " " : "", - l->comment); - if (log_level_get() >= SYSLOG_LEVEL_VERBOSE) - printf("%s\n", ra); - free(ra); - free(fp); + fingerprint_format(l->key, l->comment, + print_fingerprint_known_hosts, ctx->host); } else fprintf(ctx->out, "%s\n", l->line); return 0; @@ -1295,7 +1205,7 @@ } static void -do_known_hosts(struct passwd *pw, const char *name, int find_host, +do_known_hosts(const struct passwd *pw, const char *name, int find_host, int delete_host, int hash_hosts) { char *cp, tmp[PATH_MAX], old[PATH_MAX]; @@ -1346,13 +1256,16 @@ /* XXX support identity_file == "-" for stdin */ foreach_options = find_host ? HKF_WANT_MATCH : 0; foreach_options |= print_fingerprint ? HKF_WANT_PARSE_KEY : 0; - if ((r = hostkeys_foreach(identity_file, (find_host || !hash_hosts) ? - known_hosts_find_delete : known_hosts_hash, &ctx, name, NULL, - foreach_options, 0)) != 0) { +{ hostkeys_foreach_fn *foreach_callback = (find_host || !hash_hosts) + ? known_hosts_find_delete + : known_hosts_hash; + if ((r = hostkeys_foreach(identity_file, foreach_callback, &ctx, + name, NULL, foreach_options, 0)) != 0) { if (inplace) unlink(tmp); fatal_fr(r, "hostkeys_foreach"); } +} if (inplace) fclose(ctx.out); @@ -1373,8 +1286,8 @@ /* Backup existing file */ if (unlink(old) == -1 && errno != ENOENT) fatal("unlink %.100s: %s", old, strerror(errno)); - if (link(identity_file, old) == -1) - fatal("link %.100s to %.100s: %s", identity_file, old, + if (xrename(identity_file, old) == -1) + fatal("xrename %.100s to %.100s: %s", identity_file, old, strerror(errno)); /* Move new one into place */ if (rename(tmp, identity_file) == -1) { @@ -1402,7 +1315,7 @@ * for the current user. */ static void -do_change_passphrase(struct passwd *pw) +do_change_passphrase(const struct passwd *pw) { char *comment; char *old_passphrase, *passphrase1, *passphrase2; @@ -1448,10 +1361,8 @@ /* Verify that they are the same. */ if (strcmp(passphrase1, passphrase2) != 0) { - explicit_bzero(passphrase1, strlen(passphrase1)); - explicit_bzero(passphrase2, strlen(passphrase2)); - free(passphrase1); - free(passphrase2); + freezero(passphrase1, strlen(passphrase1)); + freezero(passphrase2, strlen(passphrase2)); printf("Pass phrases do not match. Try again.\n"); exit(1); } @@ -1481,7 +1392,7 @@ * Print the SSHFP RR. */ static int -do_print_resource_record(struct passwd *pw, char *fname, char *hname, +do_print_resource_record(char *fname, char *hname, int print_generic, char * const *opts, size_t nopts) { struct sshkey *public; @@ -1492,7 +1403,8 @@ for (i = 0; i < nopts; i++) { if (strncasecmp(opts[i], "hashalg=", 8) == 0) { - if ((hash = ssh_digest_alg_by_name(opts[i] + 8)) == -1) + hash = ssh_digest_alg_by_name(opts[i] + 8); + if (hash == -1) fatal("Unsupported hash algorithm"); } else { error("Invalid option \"%s\"", opts[i]); @@ -1518,7 +1430,7 @@ * Change the comment of a private key file. */ static void -do_change_comment(struct passwd *pw, const char *identity_comment) +do_change_comment(const struct passwd *pw, const char *identity_comment) { char new_comment[1024], *comment, *passphrase; struct sshkey *private; @@ -1555,8 +1467,8 @@ if (private->type != KEY_ED25519 && private->type != KEY_XMSS && private_key_format != SSHKEY_PRIVATE_OPENSSH) { error("Comments are only supported for keys stored in " - "the new format (-o)."); - explicit_bzero(passphrase, strlen(passphrase)); + "the OpenSSH proprietary format."); + freezero(passphrase, strlen(passphrase)); sshkey_free(private); exit(1); } @@ -1571,7 +1483,7 @@ printf("New comment: "); fflush(stdout); if (!fgets(new_comment, sizeof(new_comment), stdin)) { - explicit_bzero(passphrase, strlen(passphrase)); + freezero(passphrase, strlen(passphrase)); sshkey_free(private); exit(1); } @@ -1636,11 +1548,9 @@ return (a->crit < b->crit) ? -1 : 1; if ((r = strcmp(a->key, b->key)) != 0) return r; - if ((a->val == NULL) != (b->val == NULL)) - return (a->val == NULL) ? -1 : 1; - if (a->val != NULL && (r = strcmp(a->val, b->val)) != 0) - return r; - return 0; + if (a->val == NULL) return -1; + if (b->val == NULL) return 1; + return strcmp(a->val, b->val); } #define OPTIONS_CRITICAL 1 @@ -1650,14 +1560,14 @@ { struct sshbuf *b; size_t i; - int r; - const struct cert_ext *ext; if ((b = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); sshbuf_reset(c); for (i = 0; i < ncert_ext; i++) { - ext = &cert_ext[i]; + const struct cert_ext *ext = &cert_ext[i]; + int r; + if ((ext->crit && (which & OPTIONS_EXTENSIONS)) || (!ext->crit && (which & OPTIONS_CRITICAL))) continue; @@ -1688,8 +1598,6 @@ cert_ext_add("force-command", certflags_command, 1); if (certflags_src_addr != NULL) cert_ext_add("source-address", certflags_src_addr, 1); - if ((certflags_flags & CERTOPT_REQUIRE_VERIFY) != 0) - cert_ext_add("verify-required", NULL, 1); /* extensions */ if ((certflags_flags & CERTOPT_X_FWD) != 0) cert_ext_add("permit-X11-forwarding", NULL, 0); @@ -1701,8 +1609,6 @@ cert_ext_add("permit-pty", NULL, 0); if ((certflags_flags & CERTOPT_USER_RC) != 0) cert_ext_add("permit-user-rc", NULL, 0); - if ((certflags_flags & CERTOPT_NO_REQUIRE_USER_PRESENCE) != 0) - cert_ext_add("no-touch-required", NULL, 0); /* order lexically by key */ if (ncert_ext > 0) qsort(cert_ext, ncert_ext, sizeof(*cert_ext), cert_ext_cmp); @@ -1734,6 +1640,7 @@ sshkey_free(public); return private; #else + UNUSED(path); fatal("no pkcs11 support"); #endif /* ENABLE_PKCS11 */ } @@ -1743,32 +1650,37 @@ agent_signer(struct sshkey *key, u_char **sigp, size_t *lenp, const u_char *data, size_t datalen, const char *alg, const char *provider, const char *pin, - u_int compat, void *ctx) + u_int compat, void *v_sock) { - int *agent_fdp = (int *)ctx; + int *sock = (int *)v_sock; + ssh_compat ctx_compat = { compat, 0 }; /* TODO-Xkey_sign compat */ + ssh_sign_ctx ctx = { alg, key, &ctx_compat, provider, pin }; - return ssh_agent_sign(*agent_fdp, key, sigp, lenp, - data, datalen, alg, compat); + return Xssh_agent_sign(*sock, &ctx, sigp, lenp, data, datalen); } static void -do_ca_sign(struct passwd *pw, const char *ca_key_path, int prefer_agent, +do_ca_sign(const struct passwd *pw, const char *ca_key_path, int prefer_agent, unsigned long long cert_serial, int cert_serial_autoinc, int argc, char **argv) { int r, i, found, agent_fd = -1; u_int n; struct sshkey *ca, *public; - char valid[64], *otmp, *tmp, *cp, *out, *comment; - char *ca_fp = NULL, **plist = NULL, *pin = NULL; + char valid[64], *otmp, *tmp, *cp, *out, *comment, **plist = NULL; struct ssh_identitylist *agent_ids; size_t j; - struct notifier_ctx *notifier = NULL; #ifdef ENABLE_PKCS11 pkcs11_init(1); #endif tmp = tilde_expand_filename(ca_key_path, pw->pw_uid); + + /* NOTE X.509 certificate support contradict with ca_sing + * => set pkcs11provider to NULL to minimize incompatibility. + */ + pkcs11provider = NULL; + if (pkcs11provider != NULL) { /* If a PKCS#11 token was specified then try to use it */ if ((ca = load_pkcs11_key(tmp)) == NULL) @@ -1799,25 +1711,14 @@ } else { /* CA key is assumed to be a private key on the filesystem */ ca = load_identity(tmp, NULL); - if (sshkey_is_sk(ca) && - (ca->sk_flags & SSH_SK_USER_VERIFICATION_REQD)) { - if ((pin = read_passphrase("Enter PIN for CA key: ", - RP_ALLOW_STDIN)) == NULL) - fatal_f("couldn't read PIN"); - } } free(tmp); - if (key_type_name != NULL) { - if (sshkey_type_from_name(key_type_name) != ca->type) { - fatal("CA key type %s doesn't match specified %s", - sshkey_ssh_name(ca), key_type_name); - } - } else if (ca->type == KEY_RSA) { - /* Default to a good signature algorithm */ - key_type_name = "rsa-sha2-512"; + if (key_type_name != NULL && + sshkey_type_from_name(key_type_name) != ca->type) { + fatal("CA key type %s doesn't match specified %s", + sshkey_ssh_name(ca), key_type_name); } - ca_fp = sshkey_fingerprint(ca, fingerprint_hash, SSH_FP_DEFAULT); finalise_cert_exts(); for (i = 0; i < argc; i++) { @@ -1838,8 +1739,8 @@ tmp = tilde_expand_filename(argv[i], pw->pw_uid); if ((r = sshkey_load_public(tmp, &public, &comment)) != 0) - fatal_r(r, "load pubkey \"%s\"", tmp); - if (sshkey_is_cert(public)) + fatal_fr(r, "load pubkey \"%s\"", tmp); + if (sshkey_is_cert(public) || sshkey_is_x509(public)) fatal_f("key \"%s\" type %s cannot be certified", tmp, sshkey_type(public)); @@ -1861,22 +1762,15 @@ fatal_r(r, "sshkey_from_private (ca key)"); if (agent_fd != -1 && (ca->flags & SSHKEY_FLAG_EXT) != 0) { - if ((r = sshkey_certify_custom(public, ca, - key_type_name, sk_provider, NULL, agent_signer, - &agent_fd)) != 0) + r = sshkey_certify_custom(public, ca, key_type_name, + NULL, NULL, agent_signer, &agent_fd); + if (r != 0) fatal_r(r, "Couldn't certify %s via agent", tmp); } else { - if (sshkey_is_sk(ca) && - (ca->sk_flags & SSH_SK_USER_PRESENCE_REQD)) { - notifier = notify_start(0, - "Confirm user presence for key %s %s", - sshkey_type(ca), ca_fp); - } r = sshkey_certify(public, ca, key_type_name, - sk_provider, pin); - notify_complete(notifier, "User presence confirmed"); + NULL, NULL); if (r != 0) - fatal_r(r, "Couldn't certify key %s", tmp); + fatal_r(r, "Couldn't certify %s", tmp); } if ((cp = strrchr(tmp, '.')) != NULL && strcmp(cp, ".pub") == 0) @@ -1885,7 +1779,7 @@ free(tmp); if ((r = sshkey_save_public(public, out, comment)) != 0) { - fatal_r(r, "Unable to save public key to %s", + fatal_r(r, "Unable to save certified key to %s", identity_file); } @@ -1906,9 +1800,6 @@ if (cert_serial_autoinc) cert_serial++; } - if (pin != NULL) - freezero(pin, strlen(pin)); - free(ca_fp); #ifdef ENABLE_PKCS11 pkcs11_terminate(); #endif @@ -2026,14 +1917,6 @@ certflags_flags &= ~CERTOPT_USER_RC; else if (strcasecmp(opt, "permit-user-rc") == 0) certflags_flags |= CERTOPT_USER_RC; - else if (strcasecmp(opt, "touch-required") == 0) - certflags_flags &= ~CERTOPT_NO_REQUIRE_USER_PRESENCE; - else if (strcasecmp(opt, "no-touch-required") == 0) - certflags_flags |= CERTOPT_NO_REQUIRE_USER_PRESENCE; - else if (strcasecmp(opt, "no-verify-required") == 0) - certflags_flags &= ~CERTOPT_REQUIRE_VERIFY; - else if (strcasecmp(opt, "verify-required") == 0) - certflags_flags |= CERTOPT_REQUIRE_VERIFY; else if (strncasecmp(opt, "force-command=", 14) == 0) { val = opt + 14; if (*val == '\0') @@ -2064,7 +1947,7 @@ static void show_options(struct sshbuf *optbuf, int in_critical) { - char *name, *arg, *hex; + char *name, *arg; struct sshbuf *options, *option = NULL; int r; @@ -2082,21 +1965,17 @@ strcmp(name, "permit-agent-forwarding") == 0 || strcmp(name, "permit-port-forwarding") == 0 || strcmp(name, "permit-pty") == 0 || - strcmp(name, "permit-user-rc") == 0 || - strcmp(name, "no-touch-required") == 0)) { + strcmp(name, "permit-user-rc") == 0)) printf("\n"); - } else if (in_critical && + else if (in_critical && (strcmp(name, "force-command") == 0 || strcmp(name, "source-address") == 0)) { if ((r = sshbuf_get_cstring(option, &arg, NULL)) != 0) fatal_fr(r, "parse critical"); printf(" %s\n", arg); free(arg); - } else if (in_critical && - strcmp(name, "verify-required") == 0) { - printf("\n"); } else if (sshbuf_len(option) > 0) { - hex = sshbuf_dtob16(option); + char *hex = sshbuf_dtob16(option); printf(" UNKNOWN OPTION: %s (len %zu)\n", hex, sshbuf_len(option)); sshbuf_reset(option); @@ -2159,7 +2038,7 @@ } static void -do_show_cert(struct passwd *pw) +do_show_cert(const struct passwd *pw) { struct sshkey *key = NULL; struct stat st; @@ -2238,15 +2117,12 @@ struct sshbuf *b; int r; - if (strncmp(cp, "SHA256:", 7) != 0) - fatal("%s:%lu: unsupported hash algorithm", file, lnum); - cp += 7; - /* * OpenSSH base64 hashes omit trailing '=' * characters; put them back for decode. */ - if ((tlen = strlen(cp)) >= SIZE_MAX - 5) + tlen = strlen(cp); + if (tlen >= SIZE_MAX - 4) fatal_f("hash too long: %zu bytes", tlen); tmp = xmalloc(tlen + 4 + 1); strlcpy(tmp, cp, tlen + 1); @@ -2266,7 +2142,7 @@ } static void -update_krl_from_file(struct passwd *pw, const char *file, int wild_ca, +update_krl_from_file(const struct passwd *pw, const char *file, int wild_ca, const struct sshkey *ca, struct ssh_krl *krl) { struct sshkey *key = NULL; @@ -2361,8 +2237,18 @@ } else if (strncasecmp(cp, "hash:", 5) == 0) { cp += 5; cp = cp + strspn(cp, " \t"); - hash_to_blob(cp, &blob, &blen, file, lnum); - r = ssh_krl_revoke_key_sha256(krl, blob, blen); + if (strncasecmp(cp, "SHA1:", 5) == 0) { + cp += 5; + hash_to_blob(cp, &blob, &blen, file, lnum); + r = ssh_krl_revoke_key_sha1(krl, blob, blen); +#ifdef HAVE_EVP_SHA256 + } else if (strncmp(cp, "SHA256:", 7) == 0) { + cp += 7; + hash_to_blob(cp, &blob, &blen, file, lnum); + r = ssh_krl_revoke_key_sha256(krl, blob, blen); +#endif /*def HAVE_EVP_SHA256*/ + } else + fatal("%s:%lu: unsupported hash algorithm", file, lnum); if (r != 0) fatal_fr(r, "revoke key failed"); } else { @@ -2374,6 +2260,7 @@ cp += 5; cp = cp + strspn(cp, " \t"); was_sha1 = 1; +#ifdef HAVE_EVP_SHA256 } else if (strncasecmp(cp, "sha256:", 7) == 0) { cp += 7; cp = cp + strspn(cp, " \t"); @@ -2382,6 +2269,7 @@ * Just try to process the line as a key. * Parsing will fail if it isn't. */ +#endif /*def HAVE_EVP_SHA256*/ } if ((key = sshkey_new(KEY_UNSPEC)) == NULL) fatal("sshkey_new"); @@ -2396,6 +2284,7 @@ file, lnum); } r = ssh_krl_revoke_key_sha1(krl, blob, blen); +#ifdef HAVE_EVP_SHA256 } else if (was_sha256) { if (sshkey_fingerprint_raw(key, SSH_DIGEST_SHA256, &blob, &blen) != 0) { @@ -2403,6 +2292,7 @@ file, lnum); } r = ssh_krl_revoke_key_sha256(krl, blob, blen); +#endif /*def HAVE_EVP_SHA256*/ } else r = ssh_krl_revoke_key(krl, key); if (r != 0) @@ -2420,7 +2310,7 @@ } static void -do_gen_krl(struct passwd *pw, int updating, const char *ca_key_path, +do_gen_krl(const struct passwd *pw, int updating, const char *ca_key_path, unsigned long long krl_version, const char *krl_comment, int argc, char **argv) { @@ -2476,7 +2366,7 @@ } static void -do_check_krl(struct passwd *pw, int print_krl, int argc, char **argv) +do_check_krl(int print_krl, int argc, char **argv) { int i, r, ret = 0; char *comment; @@ -2504,452 +2394,6 @@ exit(ret); } -static struct sshkey * -load_sign_key(const char *keypath, const struct sshkey *pubkey) -{ - size_t i, slen, plen = strlen(keypath); - char *privpath = xstrdup(keypath); - static const char * const suffixes[] = { "-cert.pub", ".pub", NULL }; - struct sshkey *ret = NULL, *privkey = NULL; - int r, waspub = 0; - struct stat st; - - /* - * If passed a public key filename, then try to locate the corresponding - * private key. This lets us specify certificates on the command-line - * and have ssh-keygen find the appropriate private key. - */ - for (i = 0; suffixes[i]; i++) { - slen = strlen(suffixes[i]); - if (plen <= slen || - strcmp(privpath + plen - slen, suffixes[i]) != 0) - continue; - privpath[plen - slen] = '\0'; - debug_f("%s looks like a public key, using private key " - "path %s instead", keypath, privpath); - waspub = 1; - } - if (waspub && stat(privpath, &st) != 0 && errno == ENOENT) - fatal("No private key found for public key \"%s\"", keypath); - if ((r = sshkey_load_private(privpath, "", &privkey, NULL)) != 0 && - (r != SSH_ERR_KEY_WRONG_PASSPHRASE)) { - debug_fr(r, "load private key \"%s\"", privpath); - fatal("No private key found for \"%s\"", privpath); - } else if (privkey == NULL) - privkey = load_identity(privpath, NULL); - - if (!sshkey_equal_public(pubkey, privkey)) { - error("Public key %s doesn't match private %s", - keypath, privpath); - goto done; - } - if (sshkey_is_cert(pubkey) && !sshkey_is_cert(privkey)) { - /* - * Graft the certificate onto the private key to make - * it capable of signing. - */ - if ((r = sshkey_to_certified(privkey)) != 0) { - error_fr(r, "sshkey_to_certified"); - goto done; - } - if ((r = sshkey_cert_copy(pubkey, privkey)) != 0) { - error_fr(r, "sshkey_cert_copy"); - goto done; - } - } - /* success */ - ret = privkey; - privkey = NULL; - done: - sshkey_free(privkey); - free(privpath); - return ret; -} - -static int -sign_one(struct sshkey *signkey, const char *filename, int fd, - const char *sig_namespace, const char *hashalg, sshsig_signer *signer, - void *signer_ctx) -{ - struct sshbuf *sigbuf = NULL, *abuf = NULL; - int r = SSH_ERR_INTERNAL_ERROR, wfd = -1, oerrno; - char *wfile = NULL, *asig = NULL, *fp = NULL; - char *pin = NULL, *prompt = NULL; - - if (!quiet) { - if (fd == STDIN_FILENO) - fprintf(stderr, "Signing data on standard input\n"); - else - fprintf(stderr, "Signing file %s\n", filename); - } - if (signer == NULL && sshkey_is_sk(signkey)) { - if ((signkey->sk_flags & SSH_SK_USER_VERIFICATION_REQD)) { - xasprintf(&prompt, "Enter PIN for %s key: ", - sshkey_type(signkey)); - if ((pin = read_passphrase(prompt, - RP_ALLOW_STDIN)) == NULL) - fatal_f("couldn't read PIN"); - } - if ((signkey->sk_flags & SSH_SK_USER_PRESENCE_REQD)) { - if ((fp = sshkey_fingerprint(signkey, fingerprint_hash, - SSH_FP_DEFAULT)) == NULL) - fatal_f("fingerprint failed"); - fprintf(stderr, "Confirm user presence for key %s %s\n", - sshkey_type(signkey), fp); - free(fp); - } - } - if ((r = sshsig_sign_fd(signkey, hashalg, sk_provider, pin, - fd, sig_namespace, &sigbuf, signer, signer_ctx)) != 0) { - error_r(r, "Signing %s failed", filename); - goto out; - } - if ((r = sshsig_armor(sigbuf, &abuf)) != 0) { - error_fr(r, "sshsig_armor"); - goto out; - } - if ((asig = sshbuf_dup_string(abuf)) == NULL) { - error_f("buffer error"); - r = SSH_ERR_ALLOC_FAIL; - goto out; - } - - if (fd == STDIN_FILENO) { - fputs(asig, stdout); - fflush(stdout); - } else { - xasprintf(&wfile, "%s.sig", filename); - if (confirm_overwrite(wfile)) { - if ((wfd = open(wfile, O_WRONLY|O_CREAT|O_TRUNC, - 0666)) == -1) { - oerrno = errno; - error("Cannot open %s: %s", - wfile, strerror(errno)); - errno = oerrno; - r = SSH_ERR_SYSTEM_ERROR; - goto out; - } - if (atomicio(vwrite, wfd, asig, - strlen(asig)) != strlen(asig)) { - oerrno = errno; - error("Cannot write to %s: %s", - wfile, strerror(errno)); - errno = oerrno; - r = SSH_ERR_SYSTEM_ERROR; - goto out; - } - if (!quiet) { - fprintf(stderr, "Write signature to %s\n", - wfile); - } - } - } - /* success */ - r = 0; - out: - free(wfile); - free(prompt); - free(asig); - if (pin != NULL) - freezero(pin, strlen(pin)); - sshbuf_free(abuf); - sshbuf_free(sigbuf); - if (wfd != -1) - close(wfd); - return r; -} - -static int -sig_process_opts(char * const *opts, size_t nopts, char **hashalgp, - uint64_t *verify_timep, int *print_pubkey) -{ - size_t i; - time_t now; - - if (verify_timep != NULL) - *verify_timep = 0; - if (print_pubkey != NULL) - *print_pubkey = 0; - if (hashalgp != NULL) - *hashalgp = NULL; - for (i = 0; i < nopts; i++) { - if (hashalgp != NULL && - strncasecmp(opts[i], "hashalg=", 8) == 0) { - *hashalgp = xstrdup(opts[i] + 8); - } else if (verify_timep && - strncasecmp(opts[i], "verify-time=", 12) == 0) { - if (parse_absolute_time(opts[i] + 12, - verify_timep) != 0 || *verify_timep == 0) { - error("Invalid \"verify-time\" option"); - return SSH_ERR_INVALID_ARGUMENT; - } - } else if (print_pubkey && - strcasecmp(opts[i], "print-pubkey") == 0) { - *print_pubkey = 1; - } else { - error("Invalid option \"%s\"", opts[i]); - return SSH_ERR_INVALID_ARGUMENT; - } - } - if (verify_timep && *verify_timep == 0) { - if ((now = time(NULL)) < 0) { - error("Time is before epoch"); - return SSH_ERR_INVALID_ARGUMENT; - } - *verify_timep = (uint64_t)now; - } - return 0; -} - - -static int -sig_sign(const char *keypath, const char *sig_namespace, int require_agent, - int argc, char **argv, char * const *opts, size_t nopts) -{ - int i, fd = -1, r, ret = -1; - int agent_fd = -1; - struct sshkey *pubkey = NULL, *privkey = NULL, *signkey = NULL; - sshsig_signer *signer = NULL; - char *hashalg = NULL; - - /* Check file arguments. */ - for (i = 0; i < argc; i++) { - if (strcmp(argv[i], "-") != 0) - continue; - if (i > 0 || argc > 1) - fatal("Cannot sign mix of paths and standard input"); - } - - if (sig_process_opts(opts, nopts, &hashalg, NULL, NULL) != 0) - goto done; /* error already logged */ - - if ((r = sshkey_load_public(keypath, &pubkey, NULL)) != 0) { - error_r(r, "Couldn't load public key %s", keypath); - goto done; - } - - if ((r = ssh_get_authentication_socket(&agent_fd)) != 0) { - if (require_agent) - fatal("Couldn't get agent socket"); - debug_r(r, "Couldn't get agent socket"); - } else { - if ((r = ssh_agent_has_key(agent_fd, pubkey)) == 0) - signer = agent_signer; - else { - if (require_agent) - fatal("Couldn't find key in agent"); - debug_r(r, "Couldn't find key in agent"); - } - } - - if (signer == NULL) { - /* Not using agent - try to load private key */ - if ((privkey = load_sign_key(keypath, pubkey)) == NULL) - goto done; - signkey = privkey; - } else { - /* Will use key in agent */ - signkey = pubkey; - } - - if (argc == 0) { - if ((r = sign_one(signkey, "(stdin)", STDIN_FILENO, - sig_namespace, hashalg, signer, &agent_fd)) != 0) - goto done; - } else { - for (i = 0; i < argc; i++) { - if (strcmp(argv[i], "-") == 0) - fd = STDIN_FILENO; - else if ((fd = open(argv[i], O_RDONLY)) == -1) { - error("Cannot open %s for signing: %s", - argv[i], strerror(errno)); - goto done; - } - if ((r = sign_one(signkey, argv[i], fd, sig_namespace, - hashalg, signer, &agent_fd)) != 0) - goto done; - if (fd != STDIN_FILENO) - close(fd); - fd = -1; - } - } - - ret = 0; -done: - if (fd != -1 && fd != STDIN_FILENO) - close(fd); - sshkey_free(pubkey); - sshkey_free(privkey); - free(hashalg); - return ret; -} - -static int -sig_verify(const char *signature, const char *sig_namespace, - const char *principal, const char *allowed_keys, const char *revoked_keys, - char * const *opts, size_t nopts) -{ - int r, ret = -1; - int print_pubkey = 0; - struct sshbuf *sigbuf = NULL, *abuf = NULL; - struct sshkey *sign_key = NULL; - char *fp = NULL; - struct sshkey_sig_details *sig_details = NULL; - uint64_t verify_time = 0; - - if (sig_process_opts(opts, nopts, NULL, &verify_time, - &print_pubkey) != 0) - goto done; /* error already logged */ - - memset(&sig_details, 0, sizeof(sig_details)); - if ((r = sshbuf_load_file(signature, &abuf)) != 0) { - error_r(r, "Couldn't read signature file"); - goto done; - } - - if ((r = sshsig_dearmor(abuf, &sigbuf)) != 0) { - error_fr(r, "sshsig_armor"); - goto done; - } - if ((r = sshsig_verify_fd(sigbuf, STDIN_FILENO, sig_namespace, - &sign_key, &sig_details)) != 0) - goto done; /* sshsig_verify() prints error */ - - if ((fp = sshkey_fingerprint(sign_key, fingerprint_hash, - SSH_FP_DEFAULT)) == NULL) - fatal_f("sshkey_fingerprint failed"); - debug("Valid (unverified) signature from key %s", fp); - if (sig_details != NULL) { - debug2_f("signature details: counter = %u, flags = 0x%02x", - sig_details->sk_counter, sig_details->sk_flags); - } - free(fp); - fp = NULL; - - if (revoked_keys != NULL) { - if ((r = sshkey_check_revoked(sign_key, revoked_keys)) != 0) { - debug3_fr(r, "sshkey_check_revoked"); - goto done; - } - } - - if (allowed_keys != NULL && (r = sshsig_check_allowed_keys(allowed_keys, - sign_key, principal, sig_namespace, verify_time)) != 0) { - debug3_fr(r, "sshsig_check_allowed_keys"); - goto done; - } - /* success */ - ret = 0; -done: - if (!quiet) { - if (ret == 0) { - if ((fp = sshkey_fingerprint(sign_key, fingerprint_hash, - SSH_FP_DEFAULT)) == NULL) - fatal_f("sshkey_fingerprint failed"); - if (principal == NULL) { - printf("Good \"%s\" signature with %s key %s\n", - sig_namespace, sshkey_type(sign_key), fp); - - } else { - printf("Good \"%s\" signature for %s with %s key %s\n", - sig_namespace, principal, - sshkey_type(sign_key), fp); - } - } else { - printf("Could not verify signature.\n"); - } - } - /* Print the signature key if requested */ - if (ret == 0 && print_pubkey && sign_key != NULL) { - if ((r = sshkey_write(sign_key, stdout)) == 0) - fputc('\n', stdout); - else { - error_r(r, "Could not print public key.\n"); - ret = -1; - } - } - sshbuf_free(sigbuf); - sshbuf_free(abuf); - sshkey_free(sign_key); - sshkey_sig_details_free(sig_details); - free(fp); - return ret; -} - -static int -sig_find_principals(const char *signature, const char *allowed_keys, - char * const *opts, size_t nopts) -{ - int r, ret = -1; - struct sshbuf *sigbuf = NULL, *abuf = NULL; - struct sshkey *sign_key = NULL; - char *principals = NULL, *cp, *tmp; - uint64_t verify_time = 0; - - if (sig_process_opts(opts, nopts, NULL, &verify_time, NULL) != 0) - goto done; /* error already logged */ - - if ((r = sshbuf_load_file(signature, &abuf)) != 0) { - error_r(r, "Couldn't read signature file"); - goto done; - } - if ((r = sshsig_dearmor(abuf, &sigbuf)) != 0) { - error_fr(r, "sshsig_armor"); - goto done; - } - if ((r = sshsig_get_pubkey(sigbuf, &sign_key)) != 0) { - error_fr(r, "sshsig_get_pubkey"); - goto done; - } - if ((r = sshsig_find_principals(allowed_keys, sign_key, - verify_time, &principals)) != 0) { - if (r != SSH_ERR_KEY_NOT_FOUND) - error_fr(r, "sshsig_find_principal"); - goto done; - } - ret = 0; -done: - if (ret == 0 ) { - /* Emit matching principals one per line */ - tmp = principals; - while ((cp = strsep(&tmp, ",")) != NULL && *cp != '\0') - puts(cp); - } else { - fprintf(stderr, "No principal matched.\n"); - } - sshbuf_free(sigbuf); - sshbuf_free(abuf); - sshkey_free(sign_key); - free(principals); - return ret; -} - -static int -sig_match_principals(const char *allowed_keys, char *principal, - char * const *opts, size_t nopts) -{ - int r; - char **principals = NULL; - size_t i, nprincipals = 0; - - if ((r = sig_process_opts(opts, nopts, NULL, NULL, NULL)) != 0) - return r; /* error already logged */ - - if ((r = sshsig_match_principals(allowed_keys, principal, - &principals, &nprincipals)) != 0) { - debug_f("match: %s", ssh_err(r)); - fprintf(stderr, "No principal matched.\n"); - return r; - } - for (i = 0; i < nprincipals; i++) { - printf("%s\n", principals[i]); - free(principals[i]); - } - free(principals); - - return 0; -} - static void do_moduli_gen(const char *out_file, char **opts, size_t nopts) { @@ -3062,8 +2506,6 @@ generator_wanted, checkpoint, start_lineno, lines_to_process) != 0) fatal("modulus screening failed"); - if (in != stdin) - (void)fclose(in); free(checkpoint); #else /* WITH_OPENSSL */ fatal("Moduli screening is not supported"); @@ -3109,203 +2551,37 @@ "Passphrases do not match. Try again."); } -static char * -sk_suffix(const char *application, const uint8_t *user, size_t userlen) -{ - char *ret, *cp; - size_t slen, i; - - /* Trim off URL-like preamble */ - if (strncmp(application, "ssh://", 6) == 0) - ret = xstrdup(application + 6); - else if (strncmp(application, "ssh:", 4) == 0) - ret = xstrdup(application + 4); - else - ret = xstrdup(application); - - /* Count trailing zeros in user */ - for (i = 0; i < userlen; i++) { - if (user[userlen - i - 1] != 0) - break; - } - if (i >= userlen) - return ret; /* user-id was default all-zeros */ - - /* Append user-id, escaping non-UTF-8 characters */ - slen = userlen - i; - if (asmprintf(&cp, INT_MAX, NULL, "%.*s", (int)slen, user) == -1) - fatal_f("asmprintf failed"); - /* Don't emit a user-id that contains path or control characters */ - if (strchr(cp, '/') != NULL || strstr(cp, "..") != NULL || - strchr(cp, '\\') != NULL) { - free(cp); - cp = tohex(user, slen); - } - xextendf(&ret, "_", "%s", cp); - free(cp); - return ret; -} - -static int -do_download_sk(const char *skprovider, const char *device) -{ - struct sshsk_resident_key **srks; - size_t nsrks, i; - int r, ret = -1; - char *fp, *pin = NULL, *pass = NULL, *path, *pubpath; - const char *ext; - struct sshkey *key; - - if (skprovider == NULL) - fatal("Cannot download keys without provider"); - - pin = read_passphrase("Enter PIN for authenticator: ", RP_ALLOW_STDIN); - if (!quiet) { - printf("You may need to touch your authenticator " - "to authorize key download.\n"); - } - if ((r = sshsk_load_resident(skprovider, device, pin, 0, - &srks, &nsrks)) != 0) { - if (pin != NULL) - freezero(pin, strlen(pin)); - error_r(r, "Unable to load resident keys"); - return -1; - } - if (nsrks == 0) - logit("No keys to download"); - if (pin != NULL) - freezero(pin, strlen(pin)); - - for (i = 0; i < nsrks; i++) { - key = srks[i]->key; - if (key->type != KEY_ECDSA_SK && key->type != KEY_ED25519_SK) { - error("Unsupported key type %s (%d)", - sshkey_type(key), key->type); - continue; - } - if ((fp = sshkey_fingerprint(key, fingerprint_hash, - SSH_FP_DEFAULT)) == NULL) - fatal_f("sshkey_fingerprint failed"); - debug_f("key %zu: %s %s %s (flags 0x%02x)", i, - sshkey_type(key), fp, key->sk_application, key->sk_flags); - ext = sk_suffix(key->sk_application, - srks[i]->user_id, srks[i]->user_id_len); - xasprintf(&path, "id_%s_rk%s%s", - key->type == KEY_ECDSA_SK ? "ecdsa_sk" : "ed25519_sk", - *ext == '\0' ? "" : "_", ext); - - /* If the file already exists, ask the user to confirm. */ - if (!confirm_overwrite(path)) { - free(path); - break; - } - - /* Save the key with the application string as the comment */ - if (pass == NULL) - pass = private_key_passphrase(); - if ((r = sshkey_save_private(key, path, pass, - key->sk_application, private_key_format, - openssh_format_cipher, rounds)) != 0) { - error_r(r, "Saving key \"%s\" failed", path); - free(path); - break; - } - if (!quiet) { - printf("Saved %s key%s%s to %s\n", sshkey_type(key), - *ext != '\0' ? " " : "", - *ext != '\0' ? key->sk_application : "", - path); - } - - /* Save public key too */ - xasprintf(&pubpath, "%s.pub", path); - free(path); - if ((r = sshkey_save_public(key, pubpath, - key->sk_application)) != 0) { - error_r(r, "Saving public key \"%s\" failed", pubpath); - free(pubpath); - break; - } - free(pubpath); - } - - if (i >= nsrks) - ret = 0; /* success */ - if (pass != NULL) - freezero(pass, strlen(pass)); - sshsk_free_resident_keys(srks, nsrks); - return ret; -} - -static void -save_attestation(struct sshbuf *attest, const char *path) -{ - mode_t omask; - int r; - - if (path == NULL) - return; /* nothing to do */ - if (attest == NULL || sshbuf_len(attest) == 0) - fatal("Enrollment did not return attestation data"); - omask = umask(077); - r = sshbuf_write_file(path, attest); - umask(omask); - if (r != 0) - fatal_r(r, "Unable to write attestation data \"%s\"", path); - if (!quiet) - printf("Your FIDO attestation certificate has been saved in " - "%s\n", path); -} - -static int -confirm_sk_overwrite(const char *application, const char *user) -{ - char yesno[3]; - - printf("A resident key scoped to '%s' with user id '%s' already " - "exists.\n", application == NULL ? "ssh:" : application, - user == NULL ? "null" : user); - printf("Overwrite key in token (y/n)? "); - fflush(stdout); - if (fgets(yesno, sizeof(yesno), stdin) == NULL) - return 0; - if (yesno[0] != 'y' && yesno[0] != 'Y') - return 0; - return 1; -} - static void usage(void) { fprintf(stderr, "usage: ssh-keygen [-q] [-a rounds] [-b bits] [-C comment] [-f output_keyfile]\n" - " [-m format] [-N new_passphrase] [-O option]\n" - " [-t dsa | ecdsa | ecdsa-sk | ed25519 | ed25519-sk | rsa]\n" - " [-w provider] [-Z cipher]\n" - " ssh-keygen -p [-a rounds] [-f keyfile] [-m format] [-N new_passphrase]\n" - " [-P old_passphrase] [-Z cipher]\n" -#ifdef WITH_OPENSSL - " ssh-keygen -i [-f input_keyfile] [-m key_format]\n" - " ssh-keygen -e [-f input_keyfile] [-m key_format]\n" -#endif + " [-m format] [-N new_passphrase]\n" + " [-t dsa | ecdsa | ed25519 | rsa]\n" + " [-Z cipher]\n" + " ssh-keygen -p [-a rounds] [-f keyfile] [-m format]\n" + " [-N new_passphrase] [-P old_passphrase] [-Z cipher]\n" + " ssh-keygen -i [-f input_keyfile] [-m format]\n" + " ssh-keygen -e [-f input_keyfile] [-m format]\n" " ssh-keygen -y [-f input_keyfile]\n" " ssh-keygen -c [-a rounds] [-C comment] [-f keyfile] [-P passphrase]\n" " ssh-keygen -l [-v] [-E fingerprint_hash] [-f input_keyfile]\n" " ssh-keygen -B [-f input_keyfile]\n"); #ifdef ENABLE_PKCS11 fprintf(stderr, - " ssh-keygen -D pkcs11\n"); + " ssh-keygen -D pkcs11 [-l] [-v]\n"); #endif fprintf(stderr, " ssh-keygen -F hostname [-lv] [-f known_hosts_file]\n" " ssh-keygen -H [-f known_hosts_file]\n" - " ssh-keygen -K [-a rounds] [-w provider]\n" " ssh-keygen -R hostname [-f known_hosts_file]\n" - " ssh-keygen -r hostname [-g] [-f input_keyfile]\n" + " ssh-keygen -r hostname [-g] [-f input_keyfile] [-O option]\n"); #ifdef WITH_OPENSSL + fprintf(stderr, " ssh-keygen -M generate [-O option] output_file\n" - " ssh-keygen -M screen [-f input_file] [-O option] output_file\n" + " ssh-keygen -M screen [-f input_file] [-O option] output_file\n"); #endif + fprintf(stderr, " ssh-keygen -I certificate_identity -s ca_key [-hU] [-D pkcs11_provider]\n" " [-n principals] [-O option] [-V validity_interval]\n" " [-z serial_number] file ...\n" @@ -3313,13 +2589,7 @@ " ssh-keygen -A [-a rounds] [-f prefix_path]\n" " ssh-keygen -k -f krl_file [-u] [-s ca_public] [-z version_number]\n" " file ...\n" - " ssh-keygen -Q [-l] -f krl_file [file ...]\n" - " ssh-keygen -Y find-principals -s signature_file -f allowed_signers_file\n" - " ssh-keygen -Y match-principals -I signer_identity -f allowed_signers_file\n" - " ssh-keygen -Y check-novalidate -n namespace -s signature_file\n" - " ssh-keygen -Y sign -f key_file -n namespace file [-O option] ...\n" - " ssh-keygen -Y verify -f allowed_signers_file -I signer_identity\n" - " -n namespace -s signature_file [-r krl_file] [-O option]\n"); + " ssh-keygen -Q [-l] -f krl_file [file ...]\n"); exit(1); } @@ -3329,40 +2599,49 @@ int main(int argc, char **argv) { - char comment[1024], *passphrase = NULL; + char comment[1024], *passphrase; char *rr_hostname = NULL, *ep, *fp, *ra; struct sshkey *private, *public; - struct passwd *pw; + const struct passwd *pw; int r, opt, type; int change_passphrase = 0, change_comment = 0, show_cert = 0; int find_host = 0, delete_host = 0, hash_hosts = 0; int gen_all_hostkeys = 0, gen_krl = 0, update_krl = 0, check_krl = 0; int prefer_agent = 0, convert_to = 0, convert_from = 0; int print_public = 0, print_generic = 0, cert_serial_autoinc = 0; - int do_gen_candidates = 0, do_screen_candidates = 0, download_sk = 0; + int do_gen_candidates = 0, do_screen_candidates = 0; unsigned long long cert_serial = 0; char *identity_comment = NULL, *ca_key_path = NULL, **opts = NULL; - char *sk_application = NULL, *sk_device = NULL, *sk_user = NULL; - char *sk_attestation_path = NULL; - struct sshbuf *challenge = NULL, *attest = NULL; - size_t i, nopts = 0; + size_t nopts = 0; u_int32_t bits = 0; - uint8_t sk_flags = SSH_SK_USER_PRESENCE_REQD; const char *errstr; int log_level = SYSLOG_LEVEL_INFO; - char *sign_op = NULL; extern int optind; extern char *optarg; + ssh_malloc_init(); /* must be called before any mallocs */ /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ sanitise_stdfd(); __progname = ssh_get_progname(argv[0]); + ssh_OpenSSL_startup(); +#ifdef OPENSSL_FIPS + if (FIPS_mode()) { + #ifdef HAVE_FIPSCHECK_H + if (!FIPSCHECK_verify(NULL, NULL)) + fatal("FIPS integrity verification test failed."); + #endif + fprintf(stderr, "%s runs in FIPS mode\n", __progname); + } +#endif /*def OPENSSL_FIPS*/ + ssh_engines_startup(); + fill_default_xkalg(); + seed_rng(); - log_init(argv[0], SYSLOG_LEVEL_INFO, SYSLOG_FACILITY_USER, 1); + log_init(__progname, SYSLOG_LEVEL_INFO, SYSLOG_FACILITY_USER, 1); msetlocale(); @@ -3370,16 +2649,16 @@ pw = getpwuid(getuid()); if (!pw) fatal("No user exists for uid %lu", (u_long)getuid()); + /* take a copy of the returned structure! */ pw = pwcopy(pw); + if (gethostname(hostname, sizeof(hostname)) == -1) fatal("gethostname: %s", strerror(errno)); - sk_provider = getenv("SSH_SK_PROVIDER"); - - /* Remaining characters: dGjJSTWx */ - while ((opt = getopt(argc, argv, "ABHKLQUXceghiklopquvy" - "C:D:E:F:I:M:N:O:P:R:V:Y:Z:" - "a:b:f:g:m:n:r:s:t:w:z:")) != -1) { + /* Remaining characters: dGjJKSTwWY */ + while ((opt = getopt(argc, argv, "ABHLQUXceghiklopquvxy" + "C:D:E:F:I:M:N:O:P:R:V:Z:" + "a:b:f:g:m:n:r:s:t:z:")) != -1) { switch (opt) { case 'A': gen_all_hostkeys = 1; @@ -3423,10 +2702,13 @@ if (strcasecmp(optarg, "RFC4716") == 0 || strcasecmp(optarg, "ssh2") == 0) { convert_format = FMT_RFC4716; + /*explicitly preset default key format*/ + private_key_format = SSHKEY_PRIVATE_PKCS8; break; } if (strcasecmp(optarg, "PKCS8") == 0) { convert_format = FMT_PKCS8; + /*explicitly preset default key format*/ private_key_format = SSHKEY_PRIVATE_PKCS8; break; } @@ -3435,12 +2717,18 @@ private_key_format = SSHKEY_PRIVATE_PEM; break; } + if (strcasecmp(optarg, "OpenSSH") == 0) { + /*explicitly preset default conversion format*/ + convert_format = FMT_RFC4716; + private_key_format = SSHKEY_PRIVATE_OPENSSH; + break; + } fatal("Unsupported conversion format \"%s\"", optarg); case 'n': cert_principals = optarg; break; case 'o': - /* no-op; new format is already the default */ + private_key_format = SSHKEY_PRIVATE_OPENSSH; break; case 'p': change_passphrase = 1; @@ -3457,9 +2745,6 @@ case 'g': print_generic = 1; break; - case 'K': - download_sk = 1; - break; case 'P': identity_passphrase = optarg; break; @@ -3477,7 +2762,7 @@ case 'Z': openssh_format_cipher = optarg; if (cipher_by_name(openssh_format_cipher) == NULL) - fatal("Invalid OpenSSH-format cipher '%s'", + fatal("invalid cipher '%s'", openssh_format_cipher); break; case 'C': @@ -3487,6 +2772,7 @@ quiet = 1; break; case 'e': + case 'x': /* export key */ convert_to = 1; break; @@ -3521,13 +2807,8 @@ update_krl = 1; break; case 'v': - if (log_level == SYSLOG_LEVEL_INFO) - log_level = SYSLOG_LEVEL_DEBUG1; - else { - if (log_level >= SYSLOG_LEVEL_DEBUG1 && - log_level < SYSLOG_LEVEL_DEBUG3) - log_level++; - } + if (log_level < SYSLOG_LEVEL_DEBUG3) + log_level++; break; case 'r': rr_hostname = optarg; @@ -3541,12 +2822,6 @@ case 'V': parse_cert_times(optarg); break; - case 'Y': - sign_op = optarg; - break; - case 'w': - sk_provider = optarg; - break; case 'z': errno = 0; if (*optarg == '+') { @@ -3571,106 +2846,39 @@ } } -#ifdef ENABLE_SK_INTERNAL - if (sk_provider == NULL) - sk_provider = "internal"; +#ifdef OPENSSL_FIPS + if (FIPS_mode()) { + if (private_key_format == SSHKEY_PRIVATE_OPENSSH) + fatal("OpenSSH proprietary key format is not allowed in FIPS mode"); + if (private_key_format == SSHKEY_PRIVATE_PEM) { + private_key_format = SSHKEY_PRIVATE_PKCS8; + error("In FIPS mode is used only PKCS#8 format"); + } + } #endif /* reinit */ - log_init(argv[0], log_level, SYSLOG_FACILITY_USER, 1); + log_init(__progname, log_level, SYSLOG_FACILITY_USER, 1); + +#ifdef USE_OPENSSL_ENGINE +{ char *filename = NULL, *engconfig; + + engconfig = getenv(SSH_ENGINE_CONF_ENV); + if (engconfig == NULL) + xasprintf(&filename, "%s/%s", pw->pw_dir, + _PATH_SSH_ENGINE_CONFFILE); /*fatal on error*/ + else + filename = engconfig; + + (void)process_engconfig_file(filename); + if (filename != engconfig) + free(filename); +} +#endif argv += optind; argc -= optind; - if (sign_op != NULL) { - if (strncmp(sign_op, "find-principals", 15) == 0) { - if (ca_key_path == NULL) { - error("Too few arguments for find-principals:" - "missing signature file"); - exit(1); - } - if (!have_identity) { - error("Too few arguments for find-principals:" - "missing allowed keys file"); - exit(1); - } - return sig_find_principals(ca_key_path, identity_file, - opts, nopts); - } else if (strncmp(sign_op, "match-principals", 16) == 0) { - if (!have_identity) { - error("Too few arguments for match-principals:" - "missing allowed keys file"); - exit(1); - } - if (cert_key_id == NULL) { - error("Too few arguments for match-principals: " - "missing principal ID"); - exit(1); - } - return sig_match_principals(identity_file, cert_key_id, - opts, nopts); - } else if (strncmp(sign_op, "sign", 4) == 0) { - /* NB. cert_principals is actually namespace, via -n */ - if (cert_principals == NULL || - *cert_principals == '\0') { - error("Too few arguments for sign: " - "missing namespace"); - exit(1); - } - if (!have_identity) { - error("Too few arguments for sign: " - "missing key"); - exit(1); - } - return sig_sign(identity_file, cert_principals, - prefer_agent, argc, argv, opts, nopts); - } else if (strncmp(sign_op, "check-novalidate", 16) == 0) { - /* NB. cert_principals is actually namespace, via -n */ - if (cert_principals == NULL || - *cert_principals == '\0') { - error("Too few arguments for check-novalidate: " - "missing namespace"); - exit(1); - } - if (ca_key_path == NULL) { - error("Too few arguments for check-novalidate: " - "missing signature file"); - exit(1); - } - return sig_verify(ca_key_path, cert_principals, - NULL, NULL, NULL, opts, nopts); - } else if (strncmp(sign_op, "verify", 6) == 0) { - /* NB. cert_principals is actually namespace, via -n */ - if (cert_principals == NULL || - *cert_principals == '\0') { - error("Too few arguments for verify: " - "missing namespace"); - exit(1); - } - if (ca_key_path == NULL) { - error("Too few arguments for verify: " - "missing signature file"); - exit(1); - } - if (!have_identity) { - error("Too few arguments for sign: " - "missing allowed keys file"); - exit(1); - } - if (cert_key_id == NULL) { - error("Too few arguments for verify: " - "missing principal identity"); - exit(1); - } - return sig_verify(ca_key_path, cert_principals, - cert_key_id, identity_file, rr_hostname, - opts, nopts); - } - error("Unsupported operation for -Y: \"%s\"", sign_op); - usage(); - /* NOTREACHED */ - } - if (ca_key_path != NULL) { if (argc < 1 && !gen_krl) { error("Too few arguments."); @@ -3695,10 +2903,11 @@ return (0); } if (check_krl) { - do_check_krl(pw, print_fingerprint, argc, argv); + do_check_krl(print_fingerprint, argc, argv); return (0); } if (ca_key_path != NULL) { + size_t i; if (cert_key_id == NULL) fatal("Must specify key id (-I) when certifying"); for (i = 0; i < nopts; i++) @@ -3713,18 +2922,7 @@ delete_host, hash_hosts); } if (pkcs11provider != NULL) - do_download(pw); - if (download_sk) { - for (i = 0; i < nopts; i++) { - if (strncasecmp(opts[i], "device=", 7) == 0) { - sk_device = xstrdup(opts[i] + 7); - } else { - fatal("Option \"%s\" is unsupported for " - "FIDO authenticator download", opts[i]); - } - } - return do_download_sk(sk_provider, sk_device); - } + do_download(); if (print_fingerprint || print_bubblebabble) do_fingerprint(pw); if (change_passphrase) @@ -3746,28 +2944,30 @@ unsigned int n = 0; if (have_identity) { - n = do_print_resource_record(pw, identity_file, + n = do_print_resource_record(identity_file, rr_hostname, print_generic, opts, nopts); if (n == 0) fatal("%s: %s", identity_file, strerror(errno)); exit(0); } else { - n += do_print_resource_record(pw, + n += do_print_resource_record( _PATH_HOST_RSA_KEY_FILE, rr_hostname, print_generic, opts, nopts); - n += do_print_resource_record(pw, + n += do_print_resource_record( _PATH_HOST_DSA_KEY_FILE, rr_hostname, print_generic, opts, nopts); - n += do_print_resource_record(pw, + n += do_print_resource_record( _PATH_HOST_ECDSA_KEY_FILE, rr_hostname, print_generic, opts, nopts); - n += do_print_resource_record(pw, + n += do_print_resource_record( _PATH_HOST_ED25519_KEY_FILE, rr_hostname, print_generic, opts, nopts); - n += do_print_resource_record(pw, +#ifdef WITH_XMSS + n += do_print_resource_record( _PATH_HOST_XMSS_KEY_FILE, rr_hostname, print_generic, opts, nopts); +#endif if (n == 0) fatal("no keys found."); exit(0); @@ -3803,88 +3003,8 @@ if (!quiet) printf("Generating public/private %s key pair.\n", key_type_name); - switch (type) { - case KEY_ECDSA_SK: - case KEY_ED25519_SK: - for (i = 0; i < nopts; i++) { - if (strcasecmp(opts[i], "no-touch-required") == 0) { - sk_flags &= ~SSH_SK_USER_PRESENCE_REQD; - } else if (strcasecmp(opts[i], "verify-required") == 0) { - sk_flags |= SSH_SK_USER_VERIFICATION_REQD; - } else if (strcasecmp(opts[i], "resident") == 0) { - sk_flags |= SSH_SK_RESIDENT_KEY; - } else if (strncasecmp(opts[i], "device=", 7) == 0) { - sk_device = xstrdup(opts[i] + 7); - } else if (strncasecmp(opts[i], "user=", 5) == 0) { - sk_user = xstrdup(opts[i] + 5); - } else if (strncasecmp(opts[i], "challenge=", 10) == 0) { - if ((r = sshbuf_load_file(opts[i] + 10, - &challenge)) != 0) { - fatal_r(r, "Unable to load FIDO " - "enrollment challenge \"%s\"", - opts[i] + 10); - } - } else if (strncasecmp(opts[i], - "write-attestation=", 18) == 0) { - sk_attestation_path = opts[i] + 18; - } else if (strncasecmp(opts[i], - "application=", 12) == 0) { - sk_application = xstrdup(opts[i] + 12); - if (strncmp(sk_application, "ssh:", 4) != 0) { - fatal("FIDO application string must " - "begin with \"ssh:\""); - } - } else { - fatal("Option \"%s\" is unsupported for " - "FIDO authenticator enrollment", opts[i]); - } - } - if ((attest = sshbuf_new()) == NULL) - fatal("sshbuf_new failed"); - r = 0; - for (i = 0 ;;) { - if (!quiet) { - printf("You may need to touch your " - "authenticator%s to authorize key " - "generation.\n", - r == 0 ? "" : " again"); - } - fflush(stdout); - r = sshsk_enroll(type, sk_provider, sk_device, - sk_application == NULL ? "ssh:" : sk_application, - sk_user, sk_flags, passphrase, challenge, - &private, attest); - if (r == 0) - break; - if (r == SSH_ERR_KEY_BAD_PERMISSIONS && - (sk_flags & SSH_SK_RESIDENT_KEY) != 0 && - (sk_flags & SSH_SK_FORCE_OPERATION) == 0 && - confirm_sk_overwrite(sk_application, sk_user)) { - sk_flags |= SSH_SK_FORCE_OPERATION; - continue; - } - if (r != SSH_ERR_KEY_WRONG_PASSPHRASE) - fatal_r(r, "Key enrollment failed"); - else if (passphrase != NULL) { - error("PIN incorrect"); - freezero(passphrase, strlen(passphrase)); - passphrase = NULL; - } - if (++i >= 3) - fatal("Too many incorrect PINs"); - passphrase = read_passphrase("Enter PIN for " - "authenticator: ", RP_ALLOW_STDIN); - } - if (passphrase != NULL) { - freezero(passphrase, strlen(passphrase)); - passphrase = NULL; - } - break; - default: - if ((r = sshkey_generate(type, bits, &private)) != 0) - fatal("sshkey_generate failed"); - break; - } + if ((r = sshkey_generate(type, bits, &private)) != 0) + fatal("sshkey_generate failed"); if ((r = sshkey_from_private(private, &public)) != 0) fatal_r(r, "sshkey_from_private"); @@ -3900,6 +3020,7 @@ /* Determine the passphrase for the private key */ passphrase = private_key_passphrase(); + if (identity_comment) { strlcpy(comment, identity_comment, sizeof(comment)); } else { @@ -3914,13 +3035,13 @@ freezero(passphrase, strlen(passphrase)); exit(1); } + freezero(passphrase, strlen(passphrase)); sshkey_free(private); - if (!quiet) { - printf("Your identification has been saved in %s\n", + if (!quiet) + printf("Your identification has been saved in '%s'.\n", identity_file); - } strlcat(identity_file, ".pub", sizeof(identity_file)); if ((r = sshkey_save_public(public, identity_file, comment)) != 0) @@ -3933,7 +3054,7 @@ SSH_FP_RANDOMART); if (fp == NULL || ra == NULL) fatal("sshkey_fingerprint failed"); - printf("Your public key has been saved in %s\n", + printf("Your public key has been saved in '%s'\n", identity_file); printf("The key fingerprint is:\n"); printf("%s %s\n", fp, comment); @@ -3943,11 +3064,6 @@ free(fp); } - if (sk_attestation_path != NULL) - save_attestation(attest, sk_attestation_path); - - sshbuf_free(attest); sshkey_free(public); - exit(0); } diff -ruN openssh-9.4p1/sshkey.h openssh-9.4p1+x509-14.2.1/sshkey.h --- openssh-9.4p1/sshkey.h 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/sshkey.h 2023-08-20 10:07:00.000000000 +0300 @@ -1,7 +1,7 @@ /* $OpenBSD: sshkey.h,v 1.62 2023/06/21 05:10:26 djm Exp $ */ - /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. + * Copyright (c) 2002-2022 Roumen Petrov. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -26,31 +26,14 @@ #ifndef SSHKEY_H #define SSHKEY_H -#include +#include "evp-compat.h" -#ifdef WITH_OPENSSL -#include -#include -# ifdef OPENSSL_HAS_ECC -# include -# include -# else /* OPENSSL_HAS_ECC */ -# define EC_KEY void -# define EC_GROUP void -# define EC_POINT void -# endif /* OPENSSL_HAS_ECC */ -#define SSH_OPENSSL_VERSION OpenSSL_version(OPENSSL_VERSION) -#else /* WITH_OPENSSL */ -# define BIGNUM void -# define RSA void -# define DSA void -# define EC_KEY void -# define EC_GROUP void -# define EC_POINT void -#define SSH_OPENSSL_VERSION "without OpenSSL" -#endif /* WITH_OPENSSL */ #define SSH_RSA_MINIMUM_MODULUS_SIZE 1024 +#ifndef OPENSSL_RSA_MAX_MODULUS_BITS +# define OPENSSL_RSA_MAX_MODULUS_BITS 16384 +#endif +#define SSH_DSA_BITS 1024 #define SSH_KEY_MAX_SIGN_DATA_SIZE (1 << 20) struct sshbuf; @@ -67,15 +50,15 @@ KEY_ED25519_CERT, KEY_XMSS, KEY_XMSS_CERT, - KEY_ECDSA_SK, - KEY_ECDSA_SK_CERT, - KEY_ED25519_SK, - KEY_ED25519_SK_CERT, KEY_UNSPEC }; /* Default fingerprint hash */ +#ifdef HAVE_EVP_SHA256 #define SSH_FP_HASH_DEFAULT SSH_DIGEST_SHA256 +#else +#define SSH_FP_HASH_DEFAULT SSH_DIGEST_SHA1 +#endif /* Fingerprint representation formats */ enum sshkey_fp_rep { @@ -105,6 +88,9 @@ /* key is stored in external hardware */ #define SSHKEY_FLAG_EXT 0x0001 +/* "key shielding" is experimental */ +#undef USE_SSHKEY_SHIELDING + #define SSHKEY_CERT_MAX_PRINCIPALS 256 /* XXX opaquify? */ struct sshkey_cert { @@ -121,52 +107,53 @@ char *signature_type; }; + +typedef struct ssh_x509_st SSH_X509; + /* XXX opaquify? */ struct sshkey { int type; int flags; - /* KEY_RSA */ - RSA *rsa; - /* KEY_DSA */ - DSA *dsa; - /* KEY_ECDSA and KEY_ECDSA_SK */ + EVP_PKEY *pk; int ecdsa_nid; /* NID of curve */ - EC_KEY *ecdsa; - /* KEY_ED25519 and KEY_ED25519_SK */ u_char *ed25519_sk; u_char *ed25519_pk; - /* KEY_XMSS */ + SSH_X509 *x509_data; char *xmss_name; char *xmss_filename; /* for state file updates */ void *xmss_state; /* depends on xmss_name, opaque */ u_char *xmss_sk; u_char *xmss_pk; - /* KEY_ECDSA_SK and KEY_ED25519_SK */ - char *sk_application; - uint8_t sk_flags; - struct sshbuf *sk_key_handle; - struct sshbuf *sk_reserved; - /* Certificates */ struct sshkey_cert *cert; - /* Private key shielding */ +#ifdef USE_SSHKEY_SHIELDING u_char *shielded_private; size_t shielded_len; u_char *shield_prekey; size_t shield_prekey_len; +#endif /*def USE_SSHKEY_SHIELDING*/ }; #define ED25519_SK_SZ crypto_sign_ed25519_SECRETKEYBYTES #define ED25519_PK_SZ crypto_sign_ed25519_PUBLICKEYBYTES -/* Additional fields contained in signature */ -struct sshkey_sig_details { - uint32_t sk_counter; /* U2F signature counter */ - uint8_t sk_flags; /* U2F signature flags; see ssh-sk.h */ +struct ssh_sign_context_st { + const char *alg; /* public key algorithm name (optional) */ + struct sshkey *key; /* signing key */ + ssh_compat *compat; /* ssh compatibilities */ + const char *provider; /* reserved for security key provider */ + const char *pin; /* reserved for security key pin */ }; +struct ssh_verify_context_st { + const char *alg; /* public key algorithm name (optional) */ + struct sshkey *key; /* signing key */ + ssh_compat *compat; /* ssh compatibilities */ +}; + + struct sshkey_impl_funcs { u_int (*size)(const struct sshkey *); /* optional */ - int (*alloc)(struct sshkey *); /* optional */ +/* int (*alloc)(struct sshkey *); reserved */ void (*cleanup)(struct sshkey *); /* optional */ int (*equal)(const struct sshkey *, const struct sshkey *); int (*serialize_public)(const struct sshkey *, struct sshbuf *, @@ -178,13 +165,14 @@ int (*deserialize_private)(const char *, struct sshbuf *, struct sshkey *); int (*generate)(struct sshkey *, int); /* optional */ + void (*move_public)(struct sshkey *, struct sshkey *); int (*copy_public)(const struct sshkey *, struct sshkey *); - int (*sign)(struct sshkey *, u_char **, size_t *, - const u_char *, size_t, const char *, - const char *, const char *, u_int); /* optional */ - int (*verify)(const struct sshkey *, const u_char *, size_t, - const u_char *, size_t, const char *, u_int, - struct sshkey_sig_details **); + int (*sign)(const ssh_sign_ctx *ctx, + u_char **sigp, size_t *lenp, + const u_char *data, size_t dlen); + int (*verify)(const ssh_verify_ctx *ctx, + const u_char *sig, size_t siglen, + const u_char *data, size_t dlen); }; struct sshkey_impl { @@ -204,6 +192,8 @@ int sshkey_equal_public(const struct sshkey *, const struct sshkey *); int sshkey_equal(const struct sshkey *, const struct sshkey *); + /*bool*/ +int sshkey_match_pkalg(struct sshkey *key, const char* pkalg); char *sshkey_fingerprint(const struct sshkey *, int, enum sshkey_fp_rep); int sshkey_fingerprint_raw(const struct sshkey *k, @@ -213,24 +203,39 @@ int sshkey_format_text(const struct sshkey *, struct sshbuf *); int sshkey_write(const struct sshkey *, FILE *); int sshkey_read(struct sshkey *, char **); +int sshkey_read_pkalg(struct sshkey *, char **, char **); u_int sshkey_size(const struct sshkey *); int sshkey_generate(int type, u_int bits, struct sshkey **keyp); int sshkey_from_private(const struct sshkey *, struct sshkey **); +#ifdef USE_SSHKEY_SHIELDING int sshkey_is_shielded(struct sshkey *); int sshkey_shield_private(struct sshkey *); int sshkey_unshield_private(struct sshkey *); +#else +static inline int +sshkey_is_shielded(struct sshkey *key) { + UNUSED(key); + return 0; +} +static inline int +sshkey_shield_private(struct sshkey *key) { + UNUSED(key); + return 0/*SSH_ERR_SUCCESS*/; +} +static inline int +sshkey_unshield_private(struct sshkey *key) { + UNUSED(key); + return 0/*SSH_ERR_SUCCESS*/; +} +#endif /*ndef USE_SSHKEY_SHIELDING*/ int sshkey_type_from_name(const char *); +void sshkey_types_from_name(const char *name, int *type, int *subtype); int sshkey_is_cert(const struct sshkey *); -int sshkey_is_sk(const struct sshkey *); int sshkey_type_is_cert(int); int sshkey_type_plain(int); - -/* Returns non-zero if key name match sigalgs pattern list. (handles RSA) */ -int sshkey_match_keyname_to_sigalgs(const char *, const char *); - int sshkey_to_certified(struct sshkey *); int sshkey_drop_cert(struct sshkey *); int sshkey_cert_copy(const struct sshkey *, struct sshkey *); @@ -239,7 +244,7 @@ int sshkey_cert_check_authority_now(const struct sshkey *, int, int, int, const char *, const char **); int sshkey_cert_check_host(const struct sshkey *, const char *, - int , const char *, const char **); + int, const char *, const char **); size_t sshkey_format_cert_validity(const struct sshkey_cert *, char *, size_t) __attribute__((__bounded__(__string__, 2, 3))); int sshkey_check_cert_sigtype(const struct sshkey *, const char *); @@ -258,15 +263,18 @@ const char * sshkey_curve_nid_to_name(int); u_int sshkey_curve_nid_to_bits(int); int sshkey_ecdsa_bits_to_nid(int); -int sshkey_ecdsa_key_to_nid(EC_KEY *); int sshkey_ec_nid_to_hash_alg(int nid); int sshkey_ec_validate_public(const EC_GROUP *, const EC_POINT *); -int sshkey_ec_validate_private(const EC_KEY *); const char *sshkey_ssh_name(const struct sshkey *); const char *sshkey_ssh_name_plain(const struct sshkey *); int sshkey_names_valid2(const char *, int, int); char *sshkey_alg_list(int, int, int, char); +#define SSHKEY_ALG_PLAINKEY (1<<0) +#define SSHKEY_ALG_CUSTCERT (1<<1) +#define SSHKEY_ALG_ALL (SSHKEY_ALG_PLAINKEY|SSHKEY_ALG_CUSTCERT) +int sshkey_algind(const char **name, u_int filter, int loc); + int sshkey_from_blob(const u_char *, size_t, struct sshkey **); int sshkey_fromb(struct sshbuf *, struct sshkey **); int sshkey_froms(struct sshbuf *, struct sshkey **); @@ -279,17 +287,12 @@ int sshkey_plain_to_blob(const struct sshkey *, u_char **, size_t *); int sshkey_putb_plain(const struct sshkey *, struct sshbuf *); -int sshkey_sign(struct sshkey *, u_char **, size_t *, - const u_char *, size_t, const char *, const char *, const char *, u_int); -int sshkey_verify(const struct sshkey *, const u_char *, size_t, - const u_char *, size_t, const char *, u_int, struct sshkey_sig_details **); +int sshkey_sigtype(const u_char *, size_t, char **); +int sshkey_sign(const ssh_sign_ctx *, u_char **, size_t *, + const u_char *, size_t); +int sshkey_verify(const ssh_verify_ctx *, const u_char *, size_t, + const u_char *, size_t); int sshkey_check_sigtype(const u_char *, size_t, const char *); -const char *sshkey_sigalg_by_name(const char *); -int sshkey_get_sigtype(const u_char *, size_t, char **); - -/* for debug */ -void sshkey_dump_ec_point(const EC_GROUP *, const EC_POINT *); -void sshkey_dump_ec_key(const EC_KEY *); /* private key parsing and serialisation */ int sshkey_private_serialize(struct sshkey *key, struct sshbuf *buf); @@ -301,16 +304,18 @@ int sshkey_private_to_fileblob(struct sshkey *key, struct sshbuf *blob, const char *passphrase, const char *comment, int format, const char *openssh_format_cipher, int openssh_format_rounds); -int sshkey_parse_private_fileblob(struct sshbuf *buffer, - const char *passphrase, struct sshkey **keyp, char **commentp); -int sshkey_parse_private_fileblob_type(struct sshbuf *blob, int type, +int sshkey_parse_private_fileblob(struct sshbuf *blob, const char *passphrase, struct sshkey **keyp, char **commentp); -int sshkey_parse_pubkey_from_private_fileblob_type(struct sshbuf *blob, - int type, struct sshkey **pubkeyp); +int sshkey_parse_pubkey_from_private_fileblob(struct sshbuf *blob, + struct sshkey **pubkeyp); -int sshkey_check_rsa_length(const struct sshkey *, int); -/* XXX should be internal, but used by ssh-keygen */ -int ssh_rsa_complete_crt_parameters(struct sshkey *, const BIGNUM *); +int sshkey_private_to_bio(struct sshkey *key, BIO *bio, + const char *passphrase, int format); + +int sshrsa_verify_length(int bits); +int sshdsa_verify_length(int bits); + +int sshkey_check_length(const struct sshkey *); /* stateful keys (e.g. XMSS) */ int sshkey_set_filename(struct sshkey *, const char *); @@ -320,32 +325,42 @@ int sshkey_private_serialize_maxsign(struct sshkey *key, struct sshbuf *buf, u_int32_t maxsign, int); -void sshkey_sig_details_free(struct sshkey_sig_details *); +int ssh_encode_signature(u_char **, size_t *, const u_char *, + const u_char *, size_t); #ifdef SSHKEY_INTERNAL -int sshkey_sk_fields_equal(const struct sshkey *a, const struct sshkey *b); -void sshkey_sk_cleanup(struct sshkey *k); -int sshkey_serialize_sk(const struct sshkey *key, struct sshbuf *b); -int sshkey_copy_public_sk(const struct sshkey *from, struct sshkey *to); -int sshkey_deserialize_sk(struct sshbuf *b, struct sshkey *key); -int sshkey_serialize_private_sk(const struct sshkey *key, - struct sshbuf *buf); -int sshkey_private_deserialize_sk(struct sshbuf *buf, struct sshkey *k); -#ifdef WITH_OPENSSL -int check_rsa_length(const RSA *rsa); /* XXX remove */ -#endif -#endif +# ifdef WITH_OPENSSL +int sshkey_from_pkey(EVP_PKEY *pk, struct sshkey **keyp); + +void sshkey_clear_pkey(struct sshkey *key); + +void sshkey_move_pk(struct sshkey *from, struct sshkey *to); -#if !defined(WITH_OPENSSL) -# undef RSA -# undef DSA -# undef EC_KEY -# undef EC_GROUP -# undef EC_POINT -#elif !defined(OPENSSL_HAS_ECC) -# undef EC_KEY -# undef EC_GROUP -# undef EC_POINT +#ifdef DEBUG_PK +static void sshkey_dump(const char *func, const struct sshkey *key); +#else +static inline void +sshkey_dump(const char *func, const struct sshkey *key) { + UNUSED(func); + UNUSED(key); +} #endif +#define SSHKEY_DUMP(...) sshkey_dump(__func__, __VA_ARGS__) + +# ifdef OPENSSL_HAS_ECC +int ssh_EC_KEY_preserve_nid(EC_KEY *); +# endif /* OPENSSL_HAS_ECC */ +# endif /* WITH_OPENSSL */ +#endif /* SSHKEY_INTERNAL */ + +/*TODO internal*/ +int sshkey_validate_public_rsa(const struct sshkey *key); +int sshkey_validate_public_dsa(const struct sshkey *key); +# ifdef OPENSSL_HAS_ECC +int sshkey_validate_public_ecdsa(const struct sshkey *key); +# endif /* OPENSSL_HAS_ECC */ +int sshkey_validate_public(const struct sshkey *key); + +int sshkey_equal_public_pkey(const struct sshkey *, const struct sshkey *); #endif /* SSHKEY_H */ diff -ruN openssh-9.4p1/ssh-keyscan.0 openssh-9.4p1+x509-14.2.1/ssh-keyscan.0 --- openssh-9.4p1/ssh-keyscan.0 2023-08-10 04:11:18.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/ssh-keyscan.0 2023-08-20 10:07:00.000000000 +0300 @@ -1,29 +1,29 @@ -SSH-KEYSCAN(1) General Commands Manual SSH-KEYSCAN(1) +SSH-KEYSCAN(1) BSD General Commands Manual SSH-KEYSCAN(1) NAME - ssh-keyscan M-bM-^@M-^S gather SSH public keys from servers + ssh-keyscan -- Gather secure shell public keys from servers SYNOPSIS - ssh-keyscan [-46cDHv] [-f file] [-O option] [-p port] [-T timeout] + ssh-keyscan [-46DdHv] [-f file] [-O option] [-p port] [-T timeout] [-t type] [host | addrlist namelist] DESCRIPTION - ssh-keyscan is a utility for gathering the public SSH host keys of a - number of hosts. It was designed to aid in building and verifying + ssh-keyscan is a utility for gathering the public SSH host keys of a num- + ber of hosts. It was designed to aid in building and verifying ssh_known_hosts files, the format of which is documented in sshd(8). ssh-keyscan provides a minimal interface suitable for use by shell and perl scripts. - ssh-keyscan uses non-blocking socket I/O to contact as many hosts as - possible in parallel, so it is very efficient. The keys from a domain of + ssh-keyscan uses non-blocking socket I/O to contact as many hosts as pos- + sible in parallel, so it is very efficient. The keys from a domain of 1,000 hosts can be collected in tens of seconds, even when some of those hosts are down or do not run sshd(8). For scanning, one does not need - login access to the machines that are being scanned, nor does the - scanning process involve any encryption. + login access to the machines that are being scanned, nor does the scan- + ning process involve any encryption. - Hosts to be scanned may be specified by hostname, address or by CIDR - network range (e.g. 192.168.16/28). If a network range is specified, - then all addresses in that range will be scanned. + Hosts to be scanned may be specified by hostname, address or by CIDR net- + work range (e.g. 192.168.16/28). If a network range is specified, then + all addresses in that range will be scanned. The options are as follows: @@ -31,19 +31,21 @@ -6 Force ssh-keyscan to use IPv6 addresses only. - -c Request certificates from target hosts instead of plain keys. + -D Print keys found as DNS Resource Records (CERT or SSHFP). The + default is to print keys in a format usable as a ssh(1) + known_hosts file. - -D Print keys found as SSHFP DNS records. The default is to print - keys in a format usable as a ssh(1) known_hosts file. + -d Print keys found as DNS Resource Records (CERT or SSHFP) in + generic format. -f file - Read hosts or M-bM-^@M-^\addrlist namelistM-bM-^@M-^] pairs from file, one per line. - If M-bM-^@M-^X-M-bM-^@M-^Y is supplied instead of a filename, ssh-keyscan will read + Read hosts or "addrlist namelist" pairs from file, one per line. + If '-' is supplied instead of a filename, ssh-keyscan will read from the standard input. Names read from a file must start with - an address, hostname or CIDR network range to be scanned. - Addresses and hostnames may optionally be followed by comma- - separated name or address aliases that will be copied to the - output. For example: + an address, hostname or CIDR network range to be scanned. Ad- + dresses and hostnames may optionally be followed by comma-sepa- + rated name or address aliases that will be copied to the output. + For example: 192.168.11.0/24 10.20.1.1 @@ -60,8 +62,8 @@ hashalg=algorithm Selects a hash algorithm to use when printing SSHFP - records using the -D flag. Valid algorithms are M-bM-^@M-^\sha1M-bM-^@M-^] - and M-bM-^@M-^\sha256M-bM-^@M-^]. The default is to print both. + records using the -D flag. Valid algorithms are "sha1" + and "sha256". The default is to print both. -p port Connect to port on the remote host. @@ -70,32 +72,42 @@ Set the timeout for connection attempts. If timeout seconds have elapsed since a connection was initiated to a host or since the last time anything was read from that host, the connection is - closed and the host in question considered unavailable. The - default is 5 seconds. + closed and the host in question considered unavailable. The de- + fault is 5 seconds. -t type - Specify the type of the key to fetch from the scanned hosts. The - possible values are M-bM-^@M-^\dsaM-bM-^@M-^], M-bM-^@M-^\ecdsaM-bM-^@M-^], M-bM-^@M-^\ed25519M-bM-^@M-^], M-bM-^@M-^\ecdsa-skM-bM-^@M-^], - M-bM-^@M-^\ed25519-skM-bM-^@M-^], or M-bM-^@M-^\rsaM-bM-^@M-^]. Multiple values may be specified by - separating them with commas. The default is to fetch M-bM-^@M-^\rsaM-bM-^@M-^], - M-bM-^@M-^\ecdsaM-bM-^@M-^], M-bM-^@M-^\ed25519M-bM-^@M-^], M-bM-^@M-^\ecdsa-skM-bM-^@M-^], and M-bM-^@M-^\ed25519-skM-bM-^@M-^] keys. + Specify the host-key algorithms as pattern-list to fetch from the + scanned hosts. See PATTERNS in ssh_config(5) for more informa- + tion on patterns. + + The supported host-key algorithms are + "x509v3-ecdsa-sha2-nistp256", "x509v3-ecdsa-sha2-nistp384", + "x509v3-ecdsa-sha2-nistp521", "x509v3-rsa2048-sha256", + "x509v3-ssh-rsa", "x509v3-sign-rsa", "x509v3-ssh-dss", + "x509v3-sign-dss", "x509v3-ssh-ed25519," "ssh-ed25519", + "ssh-rsa", "rsa-sha2-256", "rsa-sha2-512", "ssh-dss", + "ecdsa-sha2-nistp256", "ecdsa-sha2-nistp384", or + "ecdsa-sha2-nistp521". The default is "*" , i.e. all supported + algorithms. + + Note that host-key algorithms "rsa-sha2-256", "rsa-sha2-512", and + "ssh-rsa" share one and the same format of host-key. -v Verbose mode: print debugging messages about progress. - If an ssh_known_hosts file is constructed using ssh-keyscan without - verifying the keys, users will be vulnerable to man in the middle - attacks. On the other hand, if the security model allows such a risk, - ssh-keyscan can help in the detection of tampered keyfiles or man in the - middle attacks which have begun after the ssh_known_hosts file was - created. + If an ssh_known_hosts file is constructed using ssh-keyscan without veri- + fying the keys, users will be vulnerable to man in the middle attacks. + On the other hand, if the security model allows such a risk, ssh-keyscan + can help in the detection of tampered keyfiles or man in the middle at- + tacks which have begun after the ssh_known_hosts file was created. FILES /etc/ssh/ssh_known_hosts EXAMPLES - Print the RSA host key for machine hostname: + Print the all RSA host-keys for machine hostname: - $ ssh-keyscan -t rsa hostname + $ ssh-keyscan -t '*rsa*' hostname Search a network range, printing all supported key types: @@ -104,18 +116,25 @@ Find all hosts from the file ssh_hosts which have new or different keys from those in the sorted file ssh_known_hosts: - $ ssh-keyscan -t rsa,dsa,ecdsa,ed25519 -f ssh_hosts | \ + $ ssh-keyscan -f ssh_hosts | \ sort -u - ssh_known_hosts | diff ssh_known_hosts - SEE ALSO ssh(1), sshd(8) - Using DNS to Securely Publish Secure Shell (SSH) Key Fingerprints, RFC - 4255, 2006. +CONFORMING TO + 1. D. Eastlake and O. Gudmundsson, Storing Certificates in the Domain + Name System (DNS), RFC 2538, March 1999. + + 2. R. Arends, R. Austein, M. Larson, D. Massey, and S. Rose, Resource + Records for the DNS Security Extensions, RFC 4034, March 2005. + + 3. J. Schlyter and W. Griffin, Using DNS to Securely Publish Secure + Shell (SSH) Key Fingerprints, RFC 4255, January 2006. AUTHORS - David Mazieres wrote the initial version, and Wayne - Davison added support for protocol version - 2. + David Mazieres wrote the initial version, Wayne Davison + added support for protocol version 2, and + Roumen Petrov contributed support for X.509 certificates. -OpenBSD 7.3 February 10, 2023 OpenBSD 7.3 +BSD 10 February 2023 BSD diff -ruN openssh-9.4p1/ssh-keyscan.1 openssh-9.4p1+x509-14.2.1/ssh-keyscan.1 --- openssh-9.4p1/ssh-keyscan.1 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/ssh-keyscan.1 2023-08-20 10:07:00.000000000 +0300 @@ -6,15 +6,45 @@ .\" permitted provided that due credit is given to the author and the .\" OpenBSD project by leaving this copyright notice intact. .\" +.\" Copyright (c) 2002-2022 Roumen Petrov. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +.\" +.\" Implement .Dd with the Mdocdate RCS keyword +.rn Dd xD +.de Dd +.ie \\$1$Mdocdate: \{\ +. xD \\$3 \\$2 \\$4 +.\} +.el .xD \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 +.. .Dd $Mdocdate: February 10 2023 $ .Dt SSH-KEYSCAN 1 .Os .Sh NAME .Nm ssh-keyscan -.Nd gather SSH public keys from servers +.Nd Gather secure shell public keys from servers .Sh SYNOPSIS .Nm ssh-keyscan -.Op Fl 46cDHv +.Op Fl 46DdHv .Op Fl f Ar file .Op Fl O Ar option .Op Fl p Ar port @@ -60,14 +90,14 @@ Force .Nm to use IPv6 addresses only. -.It Fl c -Request certificates from target hosts instead of plain keys. .It Fl D -Print keys found as SSHFP DNS records. +Print keys found as DNS Resource Records (CERT or SSHFP). The default is to print keys in a format usable as a .Xr ssh 1 .Pa known_hosts file. +.It Fl d +Print keys found as DNS Resource Records (CERT or SSHFP) in generic format. .It Fl f Ar file Read hosts or .Dq addrlist namelist @@ -125,24 +155,42 @@ closed and the host in question considered unavailable. The default is 5 seconds. .It Fl t Ar type -Specify the type of the key to fetch from the scanned hosts. -The possible values are -.Dq dsa , -.Dq ecdsa , -.Dq ed25519 , -.Dq ecdsa-sk , -.Dq ed25519-sk , +Specify the host-key algorithms as pattern-list to fetch from the scanned hosts. +See +.Em PATTERNS +in +.Xr ssh_config 5 +for more information on patterns. +.Pp +The supported host-key algorithms are +.Dq x509v3-ecdsa-sha2-nistp256 , +.Dq x509v3-ecdsa-sha2-nistp384 , +.Dq x509v3-ecdsa-sha2-nistp521 , +.Dq x509v3-rsa2048-sha256 , +.Dq x509v3-ssh-rsa , +.Dq x509v3-sign-rsa , +.Dq x509v3-ssh-dss , +.Dq x509v3-sign-dss , +.Dq x509v3-ssh-ed25519, +.Dq ssh-ed25519 , +.Dq ssh-rsa , +.Dq rsa-sha2-256 , +.Dq rsa-sha2-512 , +.Dq ssh-dss , +.Dq ecdsa-sha2-nistp256 , +.Dq ecdsa-sha2-nistp384 , or -.Dq rsa . -Multiple values may be specified by separating them with commas. -The default is to fetch -.Dq rsa , -.Dq ecdsa , -.Dq ed25519 , -.Dq ecdsa-sk , +.Dq ecdsa-sha2-nistp521 . +The default is +.Dq * +, i.e. all supported algorithms. +.Pp +Note that host-key algorithms +.Dq rsa-sha2-256 , +.Dq rsa-sha2-512 , and -.Dq ed25519-sk -keys. +.Dq ssh-rsa +share one and the same format of host-key. .It Fl v Verbose mode: print debugging messages about progress. @@ -160,10 +208,10 @@ .Sh FILES .Pa /etc/ssh/ssh_known_hosts .Sh EXAMPLES -Print the RSA host key for machine +Print the all RSA host-keys for machine .Ar hostname : .Pp -.Dl $ ssh-keyscan -t rsa hostname +.Dl $ ssh-keyscan -t '*rsa*' hostname .Pp Search a network range, printing all supported key types: .Pp @@ -174,20 +222,47 @@ which have new or different keys from those in the sorted file .Pa ssh_known_hosts : .Bd -literal -offset indent -$ ssh-keyscan -t rsa,dsa,ecdsa,ed25519 -f ssh_hosts | \e +$ ssh-keyscan -f ssh_hosts | \e sort -u - ssh_known_hosts | diff ssh_known_hosts - .Ed .Sh SEE ALSO .Xr ssh 1 , .Xr sshd 8 +.Sh CONFORMING TO +.Bl -enum +.It .Rs -.%D 2006 +.%A D. Eastlake +.%A O. Gudmundsson +.%D March 1999 +.%R RFC 2538 +.%T Storing Certificates in the Domain Name System (DNS) +.Re +.It +.Rs +.%A R. Arends +.%A R. Austein +.%A M. Larson +.%A D. Massey +.%A S. Rose +.%D March 2005 +.%R RFC 4034 +.%T Resource Records for the DNS Security Extensions +.Re +.It +.Rs +.%A J. Schlyter +.%A W. Griffin +.%D January 2006 .%R RFC 4255 .%T Using DNS to Securely Publish Secure Shell (SSH) Key Fingerprints .Re +.El .Sh AUTHORS .An -nosplit .An David Mazieres Aq Mt dm@lcs.mit.edu -wrote the initial version, and +wrote the initial version, .An Wayne Davison Aq Mt wayned@users.sourceforge.net -added support for protocol version 2. +added support for protocol version 2, and +.An Roumen Petrov +contributed support for X.509 certificates. diff -ruN openssh-9.4p1/ssh-keyscan.c openssh-9.4p1+x509-14.2.1/ssh-keyscan.c --- openssh-9.4p1/ssh-keyscan.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/ssh-keyscan.c 2023-08-20 10:07:01.000000000 +0300 @@ -5,10 +5,32 @@ * Modification and redistribution in source and binary forms is * permitted provided that due credit is given to the author and the * OpenBSD project by leaving this copyright notice intact. + * + * Copyright (c) 2002-2022 Roumen Petrov. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "includes.h" - + #include #include "openbsd-compat/sys-queue.h" #include @@ -21,13 +43,18 @@ #ifdef WITH_OPENSSL #include +#include "evp-compat.h" #endif #include #include #include #ifdef HAVE_POLL_H -#include +# include +#else +# ifdef HAVE_SYS_POLL_H +# include +# endif #endif #include #include @@ -39,11 +66,12 @@ #include "xmalloc.h" #include "ssh.h" #include "sshbuf.h" -#include "sshkey.h" +#include "ssh-x509.h" +#include "match.h" +#include "version.h" #include "cipher.h" #include "digest.h" #include "kex.h" -#include "compat.h" #include "myproposal.h" #include "packet.h" #include "dispatch.h" @@ -56,33 +84,48 @@ #include "dns.h" #include "addr.h" +/* Operations on timespecs. */ +#ifndef timespecclear +#define timespecclear(tsp) (tsp)->tv_sec = (tsp)->tv_nsec = 0 +#endif +#ifndef timespeccmp +#define timespeccmp(tsp, usp, cmp) \ + (((tsp)->tv_sec == (usp)->tv_sec) ? \ + ((tsp)->tv_nsec cmp (usp)->tv_nsec) : \ + ((tsp)->tv_sec cmp (usp)->tv_sec)) +#endif +#ifndef timespecsub +#define timespecsub(tsp, usp, vsp) \ + do { \ + (vsp)->tv_sec = (tsp)->tv_sec - (usp)->tv_sec; \ + (vsp)->tv_nsec = (tsp)->tv_nsec - (usp)->tv_nsec; \ + if ((vsp)->tv_nsec < 0) { \ + (vsp)->tv_sec--; \ + (vsp)->tv_nsec += 1000000000L; \ + } \ + } while (0) +#endif + +static char *def_kex = NULL; +static char *def_cipher = NULL; +static char *def_mac = NULL; + /* Flag indicating whether IPv4 or IPv6. This can be set on the command line. Default value is AF_UNSPEC means both IPv4 and IPv6. */ int IPv4or6 = AF_UNSPEC; int ssh_port = SSH_DEFAULT_PORT; -#define KT_DSA (1) -#define KT_RSA (1<<1) -#define KT_ECDSA (1<<2) -#define KT_ED25519 (1<<3) -#define KT_XMSS (1<<4) -#define KT_ECDSA_SK (1<<5) -#define KT_ED25519_SK (1<<6) - -#define KT_MIN KT_DSA -#define KT_MAX KT_ED25519_SK - -int get_cert = 0; -int get_keytypes = KT_RSA|KT_ECDSA|KT_ED25519|KT_ECDSA_SK|KT_ED25519_SK; +char *keynames_filter = NULL; int hash_hosts = 0; /* Hash hostname on output */ -int print_sshfp = 0; /* Print SSHFP records instead of known_hosts */ +static int print_dns_rr = 0; /* Print DNS RR records(CERT or SSHFP) instead of known_hosts */ +static int print_generic = 0; /* Use generic format for DNS RR records */ int found_one = 0; /* Successfully found a key */ -int hashalg = -1; /* Hash for SSHFP records or -1 for all */ +static int hashalg = -1; /* Hash for SSHFP records or -1 for all */ #define MAXMAXFD 256 @@ -110,7 +153,7 @@ int c_plen; /* Packet length field for ssh packet */ int c_len; /* Total bytes which must be read. */ int c_off; /* Length of data read so far. */ - int c_keytype; /* Only one of KT_* */ + const char *c_keyname; sig_atomic_t c_done; /* SSH2 done */ char *c_namebase; /* Address to free for c_name and c_namelist */ char *c_name; /* Hostname of connection for errors */ @@ -137,34 +180,30 @@ if (getrlimit(RLIMIT_NOFILE, &rlfd) == -1) return -1; lim = hard ? rlfd.rlim_max : rlfd.rlim_cur; - if (lim <= 0) - return -1; if (lim == RLIM_INFINITY) lim = SSH_SYSFDMAX; - if (lim >= INT_MAX) - lim = INT_MAX; - return lim; #else - return (SSH_SYSFDMAX <= 0) ? -1 : - ((SSH_SYSFDMAX >= INT_MAX) ? INT_MAX : SSH_SYSFDMAX); + long lim = SSH_SYSFDMAX; + UNUSED(hard); #endif + if (lim <= 0) return -1; + return MINIMUM(lim, INT_MAX); } static int fdlim_set(int lim) { -#if defined(HAVE_SETRLIMIT) && defined(RLIMIT_NOFILE) - struct rlimit rlfd; -#endif - if (lim <= 0) return (-1); -#if defined(HAVE_SETRLIMIT) && defined(RLIMIT_NOFILE) +#if defined(HAVE_SETRLIMIT) && defined(RLIMIT_NOFILE) && defined(HAVE_GETRLIMIT) +{ struct rlimit rlfd; + if (getrlimit(RLIMIT_NOFILE, &rlfd) == -1) return (-1); rlfd.rlim_cur = lim; if (setrlimit(RLIMIT_NOFILE, &rlfd) == -1) return (-1); +} #elif defined (HAVE_SETDTABLESIZE) setdtablesize(lim); #endif @@ -199,7 +238,7 @@ * null token for two adjacent separators, so we may have to loop. */ static char * -strnnsep(char **stringp, char *delim) +strnnsep(char **stringp, const char *delim) { char *tok; @@ -243,70 +282,19 @@ char *myproposal[PROPOSAL_MAX] = { KEX_CLIENT }; int r; - switch (c->c_keytype) { - case KT_DSA: - myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = get_cert ? - "ssh-dss-cert-v01@openssh.com" : "ssh-dss"; - break; - case KT_RSA: - myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = get_cert ? - "rsa-sha2-512-cert-v01@openssh.com," - "rsa-sha2-256-cert-v01@openssh.com," - "ssh-rsa-cert-v01@openssh.com" : - "rsa-sha2-512," - "rsa-sha2-256," - "ssh-rsa"; - break; - case KT_ED25519: - myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = get_cert ? - "ssh-ed25519-cert-v01@openssh.com" : "ssh-ed25519"; - break; - case KT_XMSS: - myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = get_cert ? - "ssh-xmss-cert-v01@openssh.com" : "ssh-xmss@openssh.com"; - break; - case KT_ECDSA: - myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = get_cert ? - "ecdsa-sha2-nistp256-cert-v01@openssh.com," - "ecdsa-sha2-nistp384-cert-v01@openssh.com," - "ecdsa-sha2-nistp521-cert-v01@openssh.com" : - "ecdsa-sha2-nistp256," - "ecdsa-sha2-nistp384," - "ecdsa-sha2-nistp521"; - break; - case KT_ECDSA_SK: - myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = get_cert ? - "sk-ecdsa-sha2-nistp256-cert-v01@openssh.com" : - "sk-ecdsa-sha2-nistp256@openssh.com"; - break; - case KT_ED25519_SK: - myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = get_cert ? - "sk-ssh-ed25519-cert-v01@openssh.com" : - "sk-ssh-ed25519@openssh.com"; - break; - default: - fatal("unknown key type %d", c->c_keytype); - break; - } + myproposal[PROPOSAL_KEX_ALGS] = def_kex; + myproposal[PROPOSAL_ENC_ALGS_CTOS] = + myproposal[PROPOSAL_ENC_ALGS_STOC] = def_cipher; + myproposal[PROPOSAL_MAC_ALGS_CTOS] = + myproposal[PROPOSAL_MAC_ALGS_STOC] = def_mac; + + myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = (char*)c->c_keyname; if ((r = kex_setup(c->c_ssh, myproposal)) != 0) { free(c->c_ssh); fprintf(stderr, "kex_setup: %s\n", ssh_err(r)); exit(1); } -#ifdef WITH_OPENSSL - c->c_ssh->kex->kex[KEX_DH_GRP1_SHA1] = kex_gen_client; - c->c_ssh->kex->kex[KEX_DH_GRP14_SHA1] = kex_gen_client; - c->c_ssh->kex->kex[KEX_DH_GRP14_SHA256] = kex_gen_client; - c->c_ssh->kex->kex[KEX_DH_GRP16_SHA512] = kex_gen_client; - c->c_ssh->kex->kex[KEX_DH_GRP18_SHA512] = kex_gen_client; - c->c_ssh->kex->kex[KEX_DH_GEX_SHA1] = kexgex_client; - c->c_ssh->kex->kex[KEX_DH_GEX_SHA256] = kexgex_client; -# ifdef OPENSSL_HAS_ECC - c->c_ssh->kex->kex[KEX_ECDH_SHA2] = kex_gen_client; -# endif -#endif - c->c_ssh->kex->kex[KEX_C25519_SHA256] = kex_gen_client; - c->c_ssh->kex->kex[KEX_KEM_SNTRUP761X25519_SHA512] = kex_gen_client; + kex_set_callbacks_client(c->c_ssh->kex); ssh_set_verify_host_key_callback(c->c_ssh, key_print_wrapper); /* * do the key-exchange until an error occurs or until @@ -316,16 +304,15 @@ } static void -keyprint_one(const char *host, struct sshkey *key) +keyprint_one(const char *host, con *c, struct sshkey *key) { - char *hostport = NULL, *hashed = NULL; + char *hostport, *hashed = NULL; const char *known_host; - int r = 0; - found_one = 1; + ++found_one; - if (print_sshfp) { - export_dns_rr(host, key, stdout, 0, hashalg); + if (print_dns_rr) { + export_dns_rr(host, key, stdout, print_generic, hashalg); return; } @@ -334,10 +321,20 @@ if (hash_hosts && (hashed = host_hash(hostport, NULL, 0)) == NULL) fatal("host_hash failed"); known_host = hash_hosts ? hashed : hostport; - if (!get_cert) - r = fprintf(stdout, "%s ", known_host); - if (r >= 0 && sshkey_write(key, stdout) == 0) - (void)fputs("\n", stdout); + + if (fprintf(stdout, "%s ", known_host) < 0) + goto out; + /* sshkey_write prints X.509 certificate in blob format :-( */ + if (sshkey_is_x509(key)) { + if (!Xkey_write_subject(c->c_keyname, key, stdout)) + goto out; + } else { + if (sshkey_write(key, stdout) != 0) + goto out; + } + (void)fputs("\n", stdout); + +out: free(hashed); free(hostport); } @@ -350,13 +347,13 @@ if (key == NULL) return; - if (get_cert || (!hash_hosts && ssh_port == SSH_DEFAULT_PORT)) { - keyprint_one(hosts, key); + if (!hash_hosts && ssh_port == SSH_DEFAULT_PORT) { + keyprint_one(hosts, c, key); return; } ohosts = hosts = xstrdup(hosts); while ((host = strsep(&hosts, ",")) != NULL) - keyprint_one(host, key); + keyprint_one(host, c, key); free(ohosts); } @@ -396,7 +393,7 @@ } static int -conalloc(const char *iname, const char *oname, int keytype) +conalloc(const char *iname, const char *oname, const char *keyname) { char *namebase, *name, *namelist; int s; @@ -409,14 +406,14 @@ free(namebase); return (-1); } - } while ((s = tcpconnect(name)) < 0); + } while ((s = tcpconnect(name)) == -1); if (s >= maxfd) - fatal("conalloc: fdno %d too high", s); + fatal_f("fdno %d too high", s); if (fdcon[s].c_status) - fatal("conalloc: attempt to reuse fdno %d", s); + fatal_f("attempt to reuse fdno %d", s); - debug3_f("oname %s kt %d", oname, keytype); + debug3_f("oname %s keyname %s", oname, keyname); fdcon[s].c_fd = s; fdcon[s].c_status = CS_CON; fdcon[s].c_namebase = namebase; @@ -426,7 +423,7 @@ fdcon[s].c_data = (char *) &fdcon[s].c_plen; fdcon[s].c_len = 4; fdcon[s].c_off = 0; - fdcon[s].c_keytype = keytype; + fdcon[s].c_keyname = keyname; monotime_ts(&fdcon[s].c_ts); fdcon[s].c_ts.tv_sec += timeout; TAILQ_INSERT_TAIL(&tq, &fdcon[s], c_link); @@ -440,13 +437,13 @@ confree(int s) { if (s >= maxfd || fdcon[s].c_status == CS_UNUSED) - fatal("confree: attempt to free bad fdno %d", s); + fatal_f("attempt to free bad fdno %d", s); free(fdcon[s].c_namebase); free(fdcon[s].c_output_name); if (fdcon[s].c_status == CS_KEYS) free(fdcon[s].c_data); fdcon[s].c_status = CS_UNUSED; - fdcon[s].c_keytype = 0; + fdcon[s].c_keyname = NULL; if (fdcon[s].c_ssh) { ssh_packet_close(fdcon[s].c_ssh); free(fdcon[s].c_ssh); @@ -474,7 +471,7 @@ con *c = &fdcon[s]; int ret; - ret = conalloc(c->c_namelist, c->c_output_name, c->c_keytype); + ret = conalloc(c->c_namelist, c->c_output_name, c->c_keyname); confree(s); return (ret); } @@ -489,8 +486,8 @@ con *c = &fdcon[s]; /* send client banner */ - n = snprintf(buf, sizeof buf, "SSH-%d.%d-OpenSSH-keyscan\r\n", - PROTOCOL_MAJOR_2, PROTOCOL_MINOR_2); + n = snprintf(buf, sizeof buf, "SSH-%d.%d-%s %s\r\n", + PROTOCOL_MAJOR_2, PROTOCOL_MINOR_2, SSH_VERSION, "PKIX["PACKAGE_VERSION"] keyscan"); if (n < 0 || (size_t)n >= sizeof(buf)) { error("snprintf: buffer too small"); confree(s); @@ -553,17 +550,18 @@ fatal("ssh_packet_set_connection failed"); ssh_packet_set_timeout(c->c_ssh, timeout, 1); ssh_set_app_data(c->c_ssh, c); /* back link */ - c->c_ssh->compat = 0; if (sscanf(buf, "SSH-%d.%d-%[^\n]\n", &remote_major, &remote_minor, remote_version) == 3) - compat_banner(c->c_ssh, remote_version); + ssh_set_compatibility(c->c_ssh, remote_version); + else + ssh_set_compatibility(c->c_ssh, NULL); if (!ssh2_capable(remote_major, remote_minor)) { debug("%s doesn't support ssh2", c->c_name); confree(s); return; } - fprintf(stderr, "%c %s:%d %s\n", print_sshfp ? ';' : '#', - c->c_name, ssh_port, chop(buf)); + fprintf(stderr, "%c %s:%d (%s) %s\n", print_dns_rr ? ';' : '#', + c->c_name, ssh_port, fdcon[s].c_keyname, chop(buf)); keygrab_ssh2(c); confree(s); } @@ -596,7 +594,7 @@ c->c_status = CS_KEYS; break; default: - fatal("conread: invalid status %d", c->c_status); + fatal_f("invalid status %d", c->c_status); break; } @@ -621,7 +619,8 @@ while (ppoll(read_wait, maxfd, &seltime, NULL) == -1) { if (errno == EAGAIN || errno == EINTR || errno == EWOULDBLOCK) continue; - error("poll error"); + error("ppoll: %s", strerror(errno)); + break; } for (i = 0; i < maxfd; i++) { @@ -644,16 +643,31 @@ do_one_host(char *host) { char *name = strnnsep(&host, " \t\n"); - int j; + const char *keyname; + const char *filter = keynames_filter != NULL ? keynames_filter : "*"; + char *alglist; if (name == NULL) return; - for (j = KT_MIN; j <= KT_MAX; j *= 2) { - if (get_keytypes & j) { - while (ncon >= MAXCON) - conloop(); - conalloc(name, *host ? host : name, j); + + /* Do not free as some list element are used later on connection as keyname! + * NOTE: sshkey_alg_list() initialize internally list with default X.509 + * algorithms, i.e call fill_default_xkalg(). + */ + alglist = sshkey_alg_list(0, 1, 1, ','); + + for ( + keyname = strtok(alglist, ","); + keyname != NULL; + keyname = strtok(NULL, ",") + ) { + while (ncon >= MAXCON) + conloop(); + if (match_pattern_list(keyname, filter, 0) != 1 ) { + debug_f("%s host key not permitted by filter", keyname); + continue; } + conalloc(name, *host ? host : name, keyname); } } @@ -693,24 +707,13 @@ } } -void -sshfatal(const char *file, const char *func, int line, int showfunc, - LogLevel level, const char *suffix, const char *fmt, ...) -{ - va_list args; - - va_start(args, fmt); - sshlogv(file, func, line, showfunc, level, suffix, fmt, args); - va_end(args); - cleanup_exit(255); -} - static void usage(void) { fprintf(stderr, - "usage: ssh-keyscan [-46cDHv] [-f file] [-O option] [-p port] [-T timeout]\n" - " [-t type] [host | addrlist namelist]\n"); + "usage: %s [-46cDdHv] [-f file] [-O option] [-p port] [-T timeout]\n" + "\t\t [-t type] [host | addrlist namelist]\n", + __progname); exit(1); } @@ -719,13 +722,14 @@ { int debug_flag = 0, log_level = SYSLOG_LEVEL_INFO; int opt, fopt_count = 0, j; - char *tname, *cp, *line = NULL; + char *cp, *line = NULL; size_t linesize = 0; FILE *fp; extern int optind; extern char *optarg; + ssh_malloc_init(); /* must be called before any mallocs */ __progname = ssh_get_progname(argv[0]); seed_rng(); TAILQ_INIT(&tq); @@ -736,16 +740,18 @@ if (argc <= 1) usage(); - while ((opt = getopt(argc, argv, "cDHv46O:p:T:t:f:")) != -1) { + while ((opt = getopt(argc, argv, "DdHv46O:p:T:t:f:")) != -1) { switch (opt) { case 'H': hash_hosts = 1; break; - case 'c': - get_cert = 1; - break; case 'D': - print_sshfp = 1; + print_dns_rr = 1; + print_generic = 0; + break; + case 'd': + print_dns_rr = 1; + print_generic = 1; break; case 'p': ssh_port = a2port(optarg); @@ -755,12 +761,19 @@ } break; case 'T': - timeout = convtime(optarg); - if (timeout == -1 || timeout == 0) { + { long t = convtime(optarg); + if ((t == -1) || (t == 0)) { fprintf(stderr, "Bad timeout '%s'\n", optarg); usage(); } - break; + #if SIZEOF_LONG_INT > SIZEOF_INT + if (t > INT_MAX) { + fprintf(stderr, "Timeout too high '%s'\n", optarg); + exit(1); + } + #endif + timeout = (int)t; /*safe cast*/ + } break; case 'v': if (!debug_flag) { debug_flag = 1; @@ -780,43 +793,15 @@ /* Maybe other misc options in the future too */ if (strncmp(optarg, "hashalg=", 8) != 0) fatal("Unsupported -O option"); - if ((hashalg = ssh_digest_alg_by_name( - optarg + 8)) == -1) + hashalg = ssh_digest_alg_by_name(optarg + 8); + if (hashalg == -1) fatal("Unsupported hash algorithm"); break; case 't': - get_keytypes = 0; - tname = strtok(optarg, ","); - while (tname) { - int type = sshkey_type_from_name(tname); - - switch (type) { - case KEY_DSA: - get_keytypes |= KT_DSA; - break; - case KEY_ECDSA: - get_keytypes |= KT_ECDSA; - break; - case KEY_RSA: - get_keytypes |= KT_RSA; - break; - case KEY_ED25519: - get_keytypes |= KT_ED25519; - break; - case KEY_XMSS: - get_keytypes |= KT_XMSS; - break; - case KEY_ED25519_SK: - get_keytypes |= KT_ED25519_SK; - break; - case KEY_ECDSA_SK: - get_keytypes |= KT_ECDSA_SK; - break; - case KEY_UNSPEC: - default: - fatal("Unknown key type \"%s\"", tname); - } - tname = strtok(NULL, ","); + keynames_filter = xstrdup(optarg); + if (!sshkey_names_valid2(keynames_filter, 1, 0)) { + fatal("Bad hostkey key algorithms '%s'", + keynames_filter); } break; case '4': @@ -832,7 +817,7 @@ if (optind == argc && !fopt_count) usage(); - log_init("ssh-keyscan", log_level, SYSLOG_FACILITY_USER, 1); + log_init(__progname, log_level, SYSLOG_FACILITY_USER, 1); maxfd = fdlim_get(1); if (maxfd < 0) @@ -848,6 +833,22 @@ for (j = 0; j < maxfd; j++) read_wait[j].fd = -1; + /* default KEX and etc. name lists */ +{ char *all; + + all = kex_alg_list(','); + def_kex = match_filter_allowlist(KEX_CLIENT_KEX, all); + free(all); + + all = cipher_alg_list(',', 0); + def_cipher = match_filter_allowlist(KEX_CLIENT_ENCRYPT, all); + free(all); + + all = mac_alg_list(','); + def_mac = match_filter_allowlist(KEX_CLIENT_MAC, all); + free(all); +} + for (j = 0; j < fopt_count; j++) { if (argv[j] == NULL) fp = stdin; @@ -886,5 +887,5 @@ while (ncon > 0) conloop(); - return found_one ? 0 : 1; + return found_one > 0 ? 0 : 1; } diff -ruN openssh-9.4p1/ssh-keysign.0 openssh-9.4p1+x509-14.2.1/ssh-keysign.0 --- openssh-9.4p1/ssh-keysign.0 2023-08-10 04:11:19.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/ssh-keysign.0 2023-08-20 10:07:00.000000000 +0300 @@ -1,7 +1,7 @@ -SSH-KEYSIGN(8) System Manager's Manual SSH-KEYSIGN(8) +SSH-KEYSIGN(8) BSD System Manager's Manual SSH-KEYSIGN(8) NAME - ssh-keysign M-bM-^@M-^S OpenSSH helper for host-based authentication + ssh-keysign -- Helper for host-based authentication SYNOPSIS ssh-keysign @@ -12,11 +12,11 @@ ssh-keysign is disabled by default and can only be enabled in the global client configuration file /etc/ssh/ssh_config by setting EnableSSHKeysign - to M-bM-^@M-^\yesM-bM-^@M-^]. + to "yes". ssh-keysign is not intended to be invoked by the user, but from ssh(1). - See ssh(1) and sshd(8) for more information about host-based - authentication. + See ssh(1) and sshd(8) for more information about host-based authentica- + tion. FILES /etc/ssh/ssh_config @@ -32,21 +32,24 @@ are readable only by root, ssh-keysign must be set-uid root if host-based authentication is used. + For RSA, ECDSA, Ed25519 or DSA host key file may contain X.509 + certificate that match the key. In addition file may contain ex- + tra X.509 certificates. Extra certificates along with certifi- + cates from X.509 store are used to build chain of certificates + leading to a trusted certificate authority if required by public + key algorithm format. + /etc/ssh/ssh_host_dsa_key-cert.pub /etc/ssh/ssh_host_ecdsa_key-cert.pub /etc/ssh/ssh_host_ed25519_key-cert.pub /etc/ssh/ssh_host_rsa_key-cert.pub - If these files exist, they are assumed to contain public - certificate information corresponding with the private keys - above. + If these files exist, they are assumed to contain public certifi- + cate information corresponding with the private keys above. SEE ALSO ssh(1), ssh-keygen(1), ssh_config(5), sshd(8) -HISTORY - ssh-keysign first appeared in OpenBSD 3.2. - AUTHORS Markus Friedl -OpenBSD 7.3 March 31, 2022 OpenBSD 7.3 +BSD 17 December 2022 BSD diff -ruN openssh-9.4p1/ssh-keysign.8 openssh-9.4p1+x509-14.2.1/ssh-keysign.8 --- openssh-9.4p1/ssh-keysign.8 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/ssh-keysign.8 2023-08-20 10:07:00.000000000 +0300 @@ -1,6 +1,7 @@ .\" $OpenBSD: ssh-keysign.8,v 1.17 2022/03/31 17:27:27 naddy Exp $ .\" .\" Copyright (c) 2002 Markus Friedl. All rights reserved. +.\" Copyright (c) 2002-2022 Roumen Petrov. All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions @@ -22,12 +23,20 @@ .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.Dd $Mdocdate: March 31 2022 $ +.\" Implement .Dd with the Mdocdate RCS keyword +.rn Dd xD +.de Dd +.ie \\$1$Mdocdate: \{\ +. xD \\$3 \\$2 \\$4 +.\} +.el .xD \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 +.. +.Dd $Mdocdate: December 17 2022 $ .Dt SSH-KEYSIGN 8 .Os .Sh NAME .Nm ssh-keysign -.Nd OpenSSH helper for host-based authentication +.Nd Helper for host-based authentication .Sh SYNOPSIS .Nm .Sh DESCRIPTION @@ -73,6 +82,12 @@ .Nm must be set-uid root if host-based authentication is used. .Pp +For RSA, ECDSA, Ed25519 or DSA host key file may contain X.509 certificate that +match the key. In addition file may contain extra X.509 certificates. +Extra certificates along with certificates from X.509 store are used +to build chain of certificates leading to a trusted certificate +authority if required by public key algorithm format. +.Pp .It Pa /etc/ssh/ssh_host_dsa_key-cert.pub .It Pa /etc/ssh/ssh_host_ecdsa_key-cert.pub .It Pa /etc/ssh/ssh_host_ed25519_key-cert.pub @@ -85,9 +100,5 @@ .Xr ssh-keygen 1 , .Xr ssh_config 5 , .Xr sshd 8 -.Sh HISTORY -.Nm -first appeared in -.Ox 3.2 . .Sh AUTHORS .An Markus Friedl Aq Mt markus@openbsd.org diff -ruN openssh-9.4p1/ssh-keysign.c openssh-9.4p1+x509-14.2.1/ssh-keysign.c --- openssh-9.4p1/ssh-keysign.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/ssh-keysign.c 2023-08-20 10:07:01.000000000 +0300 @@ -1,6 +1,7 @@ -/* $OpenBSD: ssh-keysign.c,v 1.71 2022/08/01 11:09:26 djm Exp $ */ +/* $OpenBSD: ssh-keysign.c,v 1.70 2022/01/06 22:00:18 djm Exp $ */ /* * Copyright (c) 2002 Markus Friedl. All rights reserved. + * Copyright (c) 2011-2021 Roumen Petrov. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -37,16 +38,11 @@ #include #include -#ifdef WITH_OPENSSL -#include -#include -#include -#include "openbsd-compat/openssl-compat.h" -#endif - #include "xmalloc.h" #include "log.h" -#include "sshkey.h" +#include "compat.h" +#include "ssh-x509.h" +#include "ssh-xkalg.h" #include "ssh.h" #include "ssh2.h" #include "misc.h" @@ -57,26 +53,93 @@ #include "pathnames.h" #include "readconf.h" #include "uidswap.h" -#include "ssherr.h" extern char *__progname; +/* used in ssh-x509.c */ +extern STACK_OF(X509)* (*pssh_x509store_build_certchain)(X509 *cert, STACK_OF(X509) *untrusted); + +/* minimize OCSP dependencies */ +#ifdef SSH_OCSP_ENABLED + +#if 1 /* used in readconf.c */ + +void +ssh_set_validator(const VAOptions *_va) { + (void)_va; + return; +} + +int +ssh_get_default_vatype(void) { + return(SSHVA_NONE); +} + +int +ssh_get_vatype_s(const char* type) { + (void)type; + return(-1); +} + +const char* +ssh_get_vatype_i(int id) { + (void)id; + return(NULL); +} + +#endif /* end of used in readconf.c */ +#endif /*def SSH_OCSP_ENABLED*/ + + +#if 1 /* used in x509store.c */ +int +ssh_ocsp_validate(X509 *cert, X509_STORE *x509store) { + UNUSED(cert); + UNUSED(x509store); + return -1; +} + +#ifdef LDAP_ENABLED +#ifdef USE_LDAP_STORE /* OpenSSL >= 1.1.1 */ +void ENGINE_load_ldap(void); +void ENGINE_load_ldap(void) {} +#endif /*def USE_LDAP_STORE*/ + +#ifndef USE_X509_LOOKUP_STORE /* OpenSSL < 3.0 */ +X509_LOOKUP_METHOD* X509_LOOKUP_ldap(void); +X509_LOOKUP_METHOD* +X509_LOOKUP_ldap(void) { + return NULL; +} +#endif /*ndef USE_X509_LOOKUP_STORE*/ +#endif /*def LDAP_ENABLED*/ + +#ifdef USE_X509_LOOKUP_MYSTORE /* OpenSSL 1.1.1* */ +X509_LOOKUP_METHOD* X509_LOOKUP_mystore(void); +X509_LOOKUP_METHOD* +X509_LOOKUP_mystore(void) { + return NULL; +} +#endif /*ndef USE_X509_LOOKUP_MYSTORE*/ +#endif /* end of used in x509store.c */ + + static int -valid_request(struct passwd *pw, char *host, struct sshkey **ret, char **pkalgp, +valid_request(struct passwd *pw, char *host, struct sshkey **retkey, char **retalg, u_char *data, size_t datalen) { struct sshbuf *b; struct sshkey *key = NULL; - u_char type, *pkblob; + u_char type; char *p; size_t blen, len; - char *pkalg, *luser; + char *pkalg = NULL, *luser; int r, pktype, fail; - if (ret != NULL) - *ret = NULL; - if (pkalgp != NULL) - *pkalgp = NULL; + if (retkey != NULL) + *retkey = NULL; + if (retalg != NULL) + *retalg = NULL; fail = 0; if ((b = sshbuf_from(data, datalen)) == NULL) @@ -114,7 +177,8 @@ fail++; free(p); - /* pubkey */ +{ /* pubkey */ + u_char *pkblob; if ((r = sshbuf_get_cstring(b, &pkalg, NULL)) != 0 || (r = sshbuf_get_string(b, &pkblob, &blen)) != 0) fatal_fr(r, "parse pk"); @@ -122,11 +186,13 @@ pktype = sshkey_type_from_name(pkalg); if (pktype == KEY_UNSPEC) fail++; - else if ((r = sshkey_from_blob(pkblob, blen, &key)) != 0) { + else if ((r = Xkey_from_blob(pkalg, pkblob, blen, &key)) != 0) { error_fr(r, "decode key"); fail++; } else if (key->type != pktype) fail++; + free(pkblob); +} /* client host name, handle trailing dot */ if ((r = sshbuf_get_cstring(b, &p, &len)) != 0) @@ -155,19 +221,19 @@ debug3_f("fail %d", fail); - if (!fail) { - if (ret != NULL) { - *ret = key; + if (fail == 0) { + if (retkey != NULL) { + *retkey = key; key = NULL; } - if (pkalgp != NULL) { - *pkalgp = pkalg; - pkalg = NULL; + if (retalg != NULL) { + *retalg = pkalg; + pkalg= NULL; } } + sshkey_free(key); free(pkalg); - free(pkblob); return (fail ? -1 : 0); } @@ -182,9 +248,12 @@ struct passwd *pw; int r, key_fd[NUM_KEYTYPES], i, found, version = 2, fd; u_char *signature, *data, rver; - char *host, *fp, *pkalg; + char *host, *fp, *alg = NULL; size_t slen, dlen; + UNUSED(argc); + ssh_malloc_init(); /* must be called before any mallocs */ + __progname = ssh_get_progname(argv[0]); if (pledge("stdio rpath getpw dns id", NULL) != 0) fatal("%s: pledge: %s", __progname, strerror(errno)); @@ -195,16 +264,34 @@ if (fd > 2) close(fd); + ssh_OpenSSL_startup(); + fill_default_xkalg(); +{ + X509StoreOptions ca; + + X509StoreOptions_init(&ca); + X509StoreOptions_system_defaults(&ca); + ssh_x509store_addlocations(&ca); + X509StoreOptions_cleanup(&ca); +} + pssh_x509store_build_certchain = ssh_x509store_build_certchain; + i = 0; /* XXX This really needs to read sshd_config for the paths */ - key_fd[i++] = open(_PATH_HOST_DSA_KEY_FILE, O_RDONLY); - key_fd[i++] = open(_PATH_HOST_ECDSA_KEY_FILE, O_RDONLY); key_fd[i++] = open(_PATH_HOST_ED25519_KEY_FILE, O_RDONLY); - key_fd[i++] = open(_PATH_HOST_XMSS_KEY_FILE, O_RDONLY); +#ifdef OPENSSL_HAS_ECC + key_fd[i++] = open(_PATH_HOST_ECDSA_KEY_FILE, O_RDONLY); +#endif key_fd[i++] = open(_PATH_HOST_RSA_KEY_FILE, O_RDONLY); + key_fd[i++] = open(_PATH_HOST_DSA_KEY_FILE, O_RDONLY); +#ifdef WITH_XMSS + key_fd[i++] = open(_PATH_HOST_XMSS_KEY_FILE, O_RDONLY); +#else + key_fd[i++] = -1; +#endif if ((pw = getpwuid(getuid())) == NULL) - fatal("getpwuid failed"); + fatal("%s: getpwuid failed", __progname); pw = pwcopy(pw); permanently_set_uid(pw); @@ -212,7 +299,7 @@ seed_rng(); #ifdef DEBUG_SSH_KEYSIGN - log_init("ssh-keysign", SYSLOG_LEVEL_DEBUG3, SYSLOG_FACILITY_AUTH, 0); + log_init(__progname, SYSLOG_LEVEL_DEBUG3, SYSLOG_FACILITY_AUTH, 0); #endif /* verify that ssh-keysign is enabled by the admin */ @@ -221,7 +308,7 @@ &options, 0, NULL); (void)fill_default_options(&options); if (options.enable_ssh_keysign != 1) - fatal("ssh-keysign not enabled in %s", + fatal("%s: ssh-keysign not enabled in %s", __progname, _PATH_HOST_CONFIG_FILE); if (pledge("stdio dns", NULL) != 0) @@ -232,15 +319,14 @@ found = 1; } if (found == 0) - fatal("could not open any host key"); + fatal("%s: could not open any host key", __progname); found = 0; for (i = 0; i < NUM_KEYTYPES; i++) { keys[i] = NULL; if (key_fd[i] == -1) continue; - r = sshkey_load_private_type_fd(key_fd[i], KEY_UNSPEC, - NULL, &key, NULL); + r = sshkey_load_private_fd(key_fd[i], NULL, &key, NULL); close(key_fd[i]); if (r != 0) debug_r(r, "parse key %d", i); @@ -250,7 +336,7 @@ } } if (!found) - fatal("no hostkey found"); + fatal("%s: no hostkey found", __progname); if ((b = sshbuf_new()) == NULL) fatal("%s: sshbuf_new failed", __progname); @@ -270,7 +356,7 @@ if ((r = sshbuf_get_string(b, &data, &dlen)) != 0) fatal_r(r, "%s: buffer error", __progname); - if (valid_request(pw, host, &key, &pkalg, data, dlen) < 0) + if (valid_request(pw, host, &key, &alg, data, dlen) < 0) fatal("%s: not a valid request", __progname); free(host); @@ -290,9 +376,12 @@ sshkey_type(key), fp ? fp : ""); } - if ((r = sshkey_sign(keys[i], &signature, &slen, data, dlen, - pkalg, NULL, NULL, 0)) != 0) - fatal_r(r, "%s: sshkey_sign failed", __progname); +{ ssh_compat ctx_compat = { 0, 0 }; /* TODO-Xkey_sign compat */ + ssh_sign_ctx ctx = { alg, keys[i], &ctx_compat, NULL, NULL }; + + if ((r = Xkey_sign(&ctx, &signature, &slen, data, dlen)) != 0) + fatal_r(r, "%s: Xkey_sign failed", __progname); +} free(data); /* send reply */ diff -ruN openssh-9.4p1/sshkey-xmss.c openssh-9.4p1+x509-14.2.1/sshkey-xmss.c --- openssh-9.4p1/sshkey-xmss.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/sshkey-xmss.c 2023-08-20 10:07:01.000000000 +0300 @@ -1,6 +1,7 @@ /* $OpenBSD: sshkey-xmss.c,v 1.12 2022/10/28 00:39:29 djm Exp $ */ /* * Copyright (c) 2017 Markus Friedl. All rights reserved. + * Copyright (c) 2022 Roumen Petrov. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -88,8 +89,8 @@ int sshkey_xmss_serialize_enc_key(const struct sshkey *, struct sshbuf *); int sshkey_xmss_deserialize_enc_key(struct sshkey *, struct sshbuf *); -#define PRINT(...) do { if (printerror) sshlog(__FILE__, __func__, __LINE__, \ - 0, SYSLOG_LEVEL_ERROR, NULL, __VA_ARGS__); } while (0) +#define PRINT(...) do { if (printerror) sshlog_f(__FILE__, __func__, __LINE__, \ + SYSLOG_LEVEL_ERROR, __VA_ARGS__); } while (0) int sshkey_xmss_init(struct sshkey *key, const char *name) @@ -141,10 +142,8 @@ sshkey_xmss_free_bds(key); if (state) { - if (state->enc_keyiv) { - explicit_bzero(state->enc_keyiv, state->enc_keyiv_len); - free(state->enc_keyiv); - } + if (state->enc_keyiv) + freezero(state->enc_keyiv, state->enc_keyiv_len); free(state->enc_ciphername); free(state); } @@ -330,10 +329,10 @@ u_int32_t idx; int r; - if (state == NULL) - return SSH_ERR_INVALID_ARGUMENT; if (opts != SSHKEY_SERIALIZE_INFO) return 0; + if (state == NULL) + return SSH_ERR_INVALID_ARGUMENT; idx = k->xmss_sk ? PEEK_U32(k->xmss_sk) : state->idx; if ((r = sshbuf_put_u8(b, have_info)) != 0 || (r = sshbuf_put_u32(b, idx)) != 0 || @@ -402,7 +401,7 @@ unsigned char buf[4], *data = NULL; *have_file = 0; - if ((fd = open(filename, O_RDONLY)) >= 0) { + if ((fd = open(filename, O_RDONLY)) != -1) { *have_file = 1; if (atomicio(read, fd, buf, sizeof(buf)) != sizeof(buf)) { PRINT("corrupt state file: %s", filename); @@ -469,9 +468,9 @@ } if ((filename = k->xmss_filename) == NULL) goto done; - if (asprintf(&lockfile, "%s.lock", filename) == -1 || - asprintf(&statefile, "%s.state", filename) == -1 || - asprintf(&ostatefile, "%s.ostate", filename) == -1) { + if (asprintf(&lockfile, "%s.lock", filename) < 0 || + asprintf(&statefile, "%s.state", filename) < 0 || + asprintf(&ostatefile, "%s.ostate", filename) < 0) { ret = SSH_ERR_ALLOC_FAIL; goto done; } @@ -596,9 +595,9 @@ state->idx = idx; if ((filename = k->xmss_filename) == NULL) goto done; - if (asprintf(&statefile, "%s.state", filename) == -1 || - asprintf(&ostatefile, "%s.ostate", filename) == -1 || - asprintf(&nstatefile, "%s.nstate", filename) == -1) { + if (asprintf(&statefile, "%s.state", filename) < 0 || + asprintf(&ostatefile, "%s.ostate", filename) < 0 || + asprintf(&nstatefile, "%s.nstate", filename) < 0) { ret = SSH_ERR_ALLOC_FAIL; goto done; } @@ -775,7 +774,7 @@ treehash_inst *th; u_int32_t i, lh, node; size_t ls, lsl, la, lk, ln, lr; - char *magic; + char *magic = NULL; int r = SSH_ERR_INTERNAL_ERROR; if (state == NULL) @@ -887,7 +886,7 @@ int sshkey_xmss_encrypt_state(const struct sshkey *k, struct sshbuf *b, - struct sshbuf **retp) + struct sshbuf **retp) { struct ssh_xmss_state *state = k->xmss_state; struct sshbuf *encrypted = NULL, *encoded = NULL, *padded = NULL; @@ -978,7 +977,7 @@ int sshkey_xmss_decrypt_state(const struct sshkey *k, struct sshbuf *encoded, - struct sshbuf **retp) + struct sshbuf **retp) { struct ssh_xmss_state *state = k->xmss_state; struct sshbuf *copy = NULL, *decrypted = NULL; diff -ruN openssh-9.4p1/sshkey-xmss.h openssh-9.4p1+x509-14.2.1/sshkey-xmss.h --- openssh-9.4p1/sshkey-xmss.h 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/sshkey-xmss.h 2023-08-20 10:07:00.000000000 +0300 @@ -1,4 +1,4 @@ -/* $OpenBSD: sshkey-xmss.h,v 1.4 2022/10/28 00:39:29 djm Exp $ */ +/* $OpenBSD: sshkey-xmss.h,v 1.3 2021/04/03 06:18:41 djm Exp $ */ /* * Copyright (c) 2017 Markus Friedl. All rights reserved. * diff -ruN openssh-9.4p1/ssh_ldap.c openssh-9.4p1+x509-14.2.1/ssh_ldap.c --- openssh-9.4p1/ssh_ldap.c 1970-01-01 02:00:00.000000000 +0200 +++ openssh-9.4p1+x509-14.2.1/ssh_ldap.c 2023-08-20 10:07:01.000000000 +0300 @@ -0,0 +1,527 @@ +/* + * Copyright (c) 2004-2021 Roumen Petrov. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "ssh_ldap.h" + +#include +#include + + +#ifdef TRACE_BY_LDAP_ENABLED +void +TRACE_BY_LDAP(const char *f, const char *fmt, ...) { + va_list ap; + va_start(ap, fmt); + fputs("TRACE_BY_LDAP ", stderr); + fputs(f, stderr); + fputs(": ", stderr); + vfprintf(stderr, fmt, ap); + va_end(ap); + fputs("\n", stderr); +} +#endif /*def TRACE_BY_LDAP_ENABLED*/ + + +/* ================================================================== */ +/* wrappers for some LDAP-functions */ + +int +ssh_ldap_bind_s(LDAP *ld) { + int result; + +{ int version = ssh_ldap_version(); + if (version >= 0) { + result = ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION, &version); + if (result != LDAP_OPT_SUCCESS) return result; + } +} + + /* anonymous bind - data must be retrieved by anybody */ +#ifdef HAVE_LDAP_SASL_BIND_S +{ + static struct berval cred = { 0, (char*)"" }; + + result = ldap_sasl_bind_s( + ld, NULL/*dn*/, LDAP_SASL_SIMPLE, &cred, + NULL, NULL, NULL); +} +#else + result = ldap_simple_bind_s(ld, NULL/*binddn*/, NULL/*bindpw*/); +#endif + +TRACE_BY_LDAP(__func__, "ldap_XXX_bind_s return 0x%x(%s)" +, result, ldap_err2string(result)); + return result; +} + + +int +ssh_ldap_unbind_s(LDAP *ld) { + int result; +#ifdef HAVE_LDAP_UNBIND_EXT_S + result = ldap_unbind_ext_s(ld, NULL, NULL); +#else + result = ldap_unbind_s(ld); +#endif + +TRACE_BY_LDAP(__func__, "ldap_XXX_unbind_s return 0x%x(%s)" +, result, ldap_err2string(result)); + return result; +} + + +int +ssh_ldap_search_s( + LDAP *ld, + LDAP_CONST char *base, + int scope, + LDAP_CONST char *filter, + char **attrs, + int attrsonly, + LDAPMessage **res +) { + int result; +#ifdef HAVE_LDAP_SEARCH_EXT_S + result = ldap_search_ext_s(ld, base, + scope, filter, attrs, attrsonly, + NULL, NULL, NULL, 0, res); +#else + result = ldap_search_s(ld, base, scope, filter, attrs, attrsonly, res); +#endif + +TRACE_BY_LDAP(__func__, "..." +"\n base: '%s'\n filter: '%s'\n ldap_search_{XXX}s return 0x%x(%s)" +, base, filter, result, ldap_err2string(result)); + return result; +} + + +void +ssh_ldap_parse_result ( + LDAP *ld, + LDAPMessage *res +) { + static const int freeit = 0; + int result; +#ifdef HAVE_LDAP_PARSE_RESULT + int ret; + char *matcheddn; + char *errmsg; + + ret = ldap_parse_result(ld, res, &result, &matcheddn, &errmsg, NULL, NULL, freeit); + if (ret == LDAP_SUCCESS) { + if (errmsg) ERR_add_error_data(1, errmsg); + } + if (matcheddn) ldap_memfree(matcheddn); + if (errmsg) ldap_memfree(errmsg); +#else + result = ldap_result2error(ld, res, freeit); + crypto_add_ldap_error(result); +#endif +} + + +/* ================================================================== */ +/* Crypto library error management */ +extern void ERR_load_SSHLDAP_strings(void); +extern void ERR_load_X509byLDAP_strings(void); + +/* Function codes. */ +#define SSHLDAP_F_LDAPHOST_NEW 101 +#define SSHLDAP_F_LDAPSEARCH_ITERATOR 102 + +/* Reason codes. */ +#define SSHLDAP_R_NOT_LDAP_URL 101 +#define SSHLDAP_R_INVALID_URL 102 +#define SSHLDAP_R_INITIALIZATION_ERROR 103 +#define SSHLDAP_R_UNABLE_TO_GET_PROTOCOL_VERSION 104 +#define SSHLDAP_R_UNABLE_TO_COUNT_ENTRIES 105 + + +#ifndef OPENSSL_NO_ERR + +static ERR_STRING_DATA SSHLDAP_str_functs[] = { + { ERR_PACK(0, SSHLDAP_F_LDAPHOST_NEW, 0) , "LDAPHOST_NEW" }, + { ERR_PACK(0, SSHLDAP_F_LDAPSEARCH_ITERATOR, 0) , "LDAPSEARCH_ITERATOR" }, + { 0, NULL } +}; + +static ERR_STRING_DATA SSHLDAP_str_reasons[] = { + { ERR_PACK(0, 0, SSHLDAP_R_NOT_LDAP_URL) , "not ldap url" }, + { ERR_PACK(0, 0, SSHLDAP_R_INVALID_URL) , "invalid ldap url" }, + { ERR_PACK(0, 0, SSHLDAP_R_INITIALIZATION_ERROR) , "ldap initialization error" }, + { ERR_PACK(0, 0, SSHLDAP_R_UNABLE_TO_GET_PROTOCOL_VERSION) , "unable to get ldap protocol version" }, + { ERR_PACK(0, 0, SSHLDAP_R_UNABLE_TO_COUNT_ENTRIES) , "unable to count ldap entries" }, + { 0, NULL } +}; + +static ERR_STRING_DATA SSHLDAP_lib_name[] = { + { 0, "SSHLDAP" }, + { 0, NULL } +}; + +#endif /*ndef OPENSSL_NO_ERR*/ + + +static int ERR_LIB_SSHLDAP = 0; + +static inline void +SSHLDAP_PUT_error(int function, int reason, const char *file, int line, const char *funcname) { + if (ERR_LIB_SSHLDAP == 0) + ERR_LIB_SSHLDAP = ERR_get_next_error_library(); + +#ifdef OPENSSL_NO_FILENAMES /* OpenSSL 1.1+ */ + file = NULL; + line = 0; +#endif +#ifdef ERR_raise_data + UNUSED(function); + ERR_new(); + ERR_set_debug(file, line, funcname); + ERR_set_error(ERR_LIB_SSHLDAP, reason, NULL); +#else +# ifdef OPENSSL_NO_ERR + /* If ERR_PUT_error macro ignores file and line */ + UNUSED(file); + UNUSED(line); +# endif + UNUSED(funcname); + ERR_PUT_error(ERR_LIB_SSHLDAP, function, reason, file, line); +#endif /*ndef ERR_raise_data*/ +} + +#define SSHLDAPerr(f,r) SSHLDAP_PUT_error((f),(r),__FILE__,__LINE__, __func__) + + +void +ERR_load_SSHLDAP_strings(void) { +#ifndef OPENSSL_NO_ERR +{ static int loaded = 0; + if (loaded) return; + loaded = 1; +} + if (ERR_LIB_SSHLDAP == 0) + ERR_LIB_SSHLDAP = ERR_get_next_error_library(); + + ERR_load_strings(ERR_LIB_SSHLDAP, SSHLDAP_str_functs); + ERR_load_strings(ERR_LIB_SSHLDAP, SSHLDAP_str_reasons); + + SSHLDAP_lib_name[0].error = ERR_PACK(ERR_LIB_SSHLDAP, 0, 0); + ERR_load_strings(0, SSHLDAP_lib_name); +#endif /*ndef OPENSSL_NO_ERR*/ +#ifndef USE_OPENSSL_STORE2 + ERR_load_X509byLDAP_strings(); +#endif +} + + +/* ================================================================== */ +/* LDAP connection details */ + +ldaphost* +ldaphost_new(const char *url) { + ldaphost *p; + int ret; + +TRACE_BY_LDAP(__func__, "url: '%s')", url); + p = OPENSSL_malloc(sizeof(ldaphost)); + if (p == NULL) return NULL; + + memset(p, 0, sizeof(ldaphost)); + + p->url = OPENSSL_malloc(strlen(url) + 1); + if (p->url == NULL) goto error; + strcpy(p->url, url); + + /*ldap://hostport/dn[?attrs[?scope[?filter[?exts]]]] */ + ret = ldap_is_ldap_url(url); + if (ret < 0) { + SSHLDAPerr(SSHLDAP_F_LDAPHOST_NEW, SSHLDAP_R_NOT_LDAP_URL); + goto error; + } + + ret = ldap_url_parse(p->url, &p->ldapurl); + if (ret != 0) { + SSHLDAPerr(SSHLDAP_F_LDAPHOST_NEW, SSHLDAP_R_INVALID_URL); + crypto_add_ldap_error(ret); + goto error; + } +#ifdef TRACE_BY_LDAP_ENABLED +{ +char *uri = ldap_url_desc2str(p->ldapurl); +TRACE_BY_LDAP(__func__, "ldap_url_desc2str: '%s'", uri); +ldap_memfree(uri); +} +#endif /*def TRACE_BY_LDAP_ENABLED*/ +TRACE_BY_LDAP(__func__, "ldapurl: '%s://%s:%d'", p->ldapurl->lud_scheme, p->ldapurl->lud_host, p->ldapurl->lud_port); + + /* allocate connection without to open */ +#ifdef HAVE_LDAP_INITIALIZE + ret = ldap_initialize(&p->ld, p->url); + if (ret != LDAP_SUCCESS) { + SSHLDAPerr(SSHLDAP_F_LDAPHOST_NEW, SSHLDAP_R_INITIALIZATION_ERROR); + crypto_add_ldap_error(ret); + goto error; + } +#else /*ndef HAVE_LDAP_INITIALIZE*/ + p->ld = ldap_init(p->ldapurl->lud_host, p->ldapurl->lud_port); + if(p->ld == NULL) { + SSHLDAPerr(SSHLDAP_F_LDAPHOST_NEW, SSHLDAP_R_INITIALIZATION_ERROR); + goto error; + } +#endif /*ndef HAVE_LDAP_INITIALIZE*/ + +{ int version = -1; + + ret = ldap_get_option(p->ld, LDAP_OPT_PROTOCOL_VERSION, &version); + if (ret != LDAP_OPT_SUCCESS) { + SSHLDAPerr(SSHLDAP_F_LDAPHOST_NEW, SSHLDAP_R_UNABLE_TO_GET_PROTOCOL_VERSION ); + goto error; + } +TRACE_BY_LDAP(__func__, "using protocol v%d (default)", version); +} + + return p; +error: + ldaphost_free(p); + return NULL; +} + + +void +ldaphost_free(ldaphost *p) { +TRACE_BY_LDAP(__func__, "..."); + if (p == NULL) return; + if (p->url != NULL) OPENSSL_free(p->url); + if (p->binddn != NULL) OPENSSL_free(p->binddn); + if (p->bindpw != NULL) OPENSSL_free(p->bindpw); + if (p->ldapurl != NULL) { + ldap_free_urldesc(p->ldapurl); + p->ldapurl = NULL; + } + if (p->ld != NULL) { + (void)ssh_ldap_unbind_s(p->ld); + p->ld = NULL; + } + OPENSSL_free(p); +} + + +/* ================================================================== */ +/* LDAP search filter */ + +static char* +ldapsearch_ASN1_STRING(ASN1_STRING *nv) { + char *p = NULL; + int k; + BIO *mbio; + + mbio = BIO_new(BIO_s_mem()); + if (mbio == NULL) return NULL; + + k = ASN1_STRING_print_ex(mbio, nv, XN_FLAG_RFC2253); + p = OPENSSL_malloc(k + 1); + if (p == NULL) goto done; + + k = BIO_read(mbio, p, k); + p[k] = '\0'; + +done: + BIO_free_all(mbio); + return p; +} + + +char* +X509_NAME_ldapfilter(X509_NAME *name, const char *attribute) { + char *p = NULL; + int k; + BIO *mbio; + + mbio = BIO_new(BIO_s_mem()); + if (mbio == NULL) return NULL; + + BIO_puts(mbio, "(&"); + + k = X509_NAME_entry_count(name); + for (--k; k >= 0; k--) { + X509_NAME_ENTRY *ne; + ASN1_STRING *nv; + int nid; + + ne = X509_NAME_get_entry(name, k); + nid = OBJ_obj2nid(X509_NAME_ENTRY_get_object(ne)); + + if ( + (nid != NID_organizationName) && + (nid != NID_organizationalUnitName) && + (nid != NID_commonName) + ) continue; + + BIO_puts(mbio, "("); + BIO_puts(mbio, OBJ_nid2sn(nid)); + BIO_puts(mbio, "="); + nv = X509_NAME_ENTRY_get_data(ne); + { + char *q, *s; + + q = ldapsearch_ASN1_STRING(nv); +TRACE_BY_LDAP(__func__, "ldapsearch_ASN1_STRING(nv) return '%s'", (q ? q : "")); + if (q == NULL) goto done; + /* escape some charecters according to RFC2254 */ + for (s=q; *s; s++) { + if ((*s == '*') || + (*s == '(') || + (*s == ')') + /* character '\' should be already escaped ! */ + ) { + /* RFC2254 recommendation */ + BIO_printf(mbio, "\\%02X", (int)*s); + continue; + } + BIO_write(mbio, s, 1); + } + + OPENSSL_free(q); + } + BIO_puts(mbio, ")"); + } + + if (attribute != NULL) { + BIO_puts(mbio, "("); + BIO_puts(mbio, attribute); + BIO_puts(mbio, "=*)"); + } + + BIO_puts(mbio, ")"); + (void)BIO_flush(mbio); + + k = BIO_pending(mbio); + p = OPENSSL_malloc(k + 1); + if (p == NULL) goto done; + + k = BIO_read(mbio, p, k); + p[k] = '\0'; +TRACE_BY_LDAP(__func__, "result: '%.1024s'%s", p, (k > 1024 ? "...": "")); + +done: + BIO_free_all(mbio); + return p; +} + + +/* ================================================================== */ +/* LDAP result iterator */ + +ldapsearch_result* +ldapsearch_iterator(LDAP *ld, LDAPMessage *res) { +{ int k = ldap_count_entries(ld, res); +TRACE_BY_LDAP(__func__, "ldap_count_entries: %d", k); + if (k < 0) { + SSHLDAPerr(SSHLDAP_F_LDAPSEARCH_ITERATOR, SSHLDAP_R_UNABLE_TO_COUNT_ENTRIES); + ssh_ldap_parse_result (ld, res); + return NULL; + } +} +{ + ldapsearch_result *ret = OPENSSL_malloc(sizeof(ldapsearch_result)); + if (ret == NULL) return NULL; + + memset(ret, 0, sizeof(ldapsearch_result)); + + ret->ld = ld; + ret->entry = ldap_first_entry(ld, res); + return ret; +} +} + + +int/*bool*/ +ldapsearch_advance(ldapsearch_result* r) { + while(r->entry != NULL) { +#ifdef TRACE_BY_LDAP_ENABLED +{ +char *dn = ldap_get_dn(r->ld, r->entry); +TRACE_BY_LDAP(__func__, "ldap_get_dn: '%s'", dn); +ldap_memfree(dn); +} +#endif /*def TRACE_BY_LDAP_ENABLED*/ + if (r->attr == NULL) + r->attr = ldap_first_attribute(r->ld, r->entry, &r->attr_ber); + + while(r->attr != NULL) { +TRACE_BY_LDAP(__func__, "attr: '%s'", r->attr); + + if (r->p == NULL) { + r->vals = ldap_get_values_len(r->ld, r->entry, r->attr); + /* silently ignore error if return value is NULL */ + if (r->vals == NULL) goto next_attr; + + r->p = r->vals; +TRACE_BY_LDAP(__func__, "r->p[0]=%p'", *r->p); + /* just in case */ + if (*r->p == NULL) goto end_vals; + + /* advance to first value / index zero */ + return 1; + } + + /* advance to next value */ + r->p++; +TRACE_BY_LDAP(__func__, "r->p[x]=%p'", *r->p); + if (*r->p != NULL) + return 1; + +end_vals: + ldap_value_free_len(r->vals); + r->p = NULL; + +next_attr: + ldap_memfree(r->attr); + r->attr = ldap_next_attribute(r->ld, r->entry, r->attr_ber); + } + + ber_free(r->attr_ber, 0); + + r->entry = ldap_next_entry(r->ld, r->entry); + } +TRACE_BY_LDAP(__func__, "end"); + return 0; +} + + +/* ================================================================== */ + +static inline char* +ldap_errormsg(char *buf, size_t len, int err) { + snprintf(buf, len, "ldaperror=0x%x(%.256s)", err, ldap_err2string(err)); + return buf; +} + + +void +crypto_add_ldap_error(int err) { + char buf[512]; + ERR_add_error_data(1, ldap_errormsg(buf, sizeof(buf), err)); +} diff -ruN openssh-9.4p1/ssh_ldap.h openssh-9.4p1+x509-14.2.1/ssh_ldap.h --- openssh-9.4p1/ssh_ldap.h 1970-01-01 02:00:00.000000000 +0200 +++ openssh-9.4p1+x509-14.2.1/ssh_ldap.h 2023-08-20 10:07:00.000000000 +0300 @@ -0,0 +1,109 @@ +#ifndef SSH_LDAP_H +#define SSH_LDAP_H +/* + * Copyright (c) 2004-2021 Roumen Petrov. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "includes.h" +#ifndef LDAP_ENABLED +# include "error: LDAP is disabled" +#endif + +#ifndef LDAP_DEPRECATED + /* to suppress warnings in some 2.3x versions */ +# define LDAP_DEPRECATED 0 +#endif +#include + +int ssh_ldap_version(void); + +int ssh_ldap_bind_s(LDAP *ld); +int ssh_ldap_unbind_s(LDAP *ld); + +int ssh_ldap_search_s(LDAP *ld, LDAP_CONST char *base, int scope, + LDAP_CONST char *filter, char **attrs, int attrsonly, + LDAPMessage **res); +void ssh_ldap_parse_result (LDAP *ld, LDAPMessage *res); + + +void crypto_add_ldap_error(int err); + + +/* LDAP connection details */ +typedef struct ldaphost_s ldaphost; +struct ldaphost_s { + char *url; + char *binddn; + char *bindpw; + LDAPURLDesc *ldapurl; + LDAP *ld; +}; + +ldaphost* ldaphost_new(const char *url); +void ldaphost_free(ldaphost *p); + + +char* +X509_NAME_ldapfilter(X509_NAME *name, const char *attribute); + + +/* LDAP result iterator */ +typedef struct ldapsearch_result_st ldapsearch_result; +struct ldapsearch_result_st { + LDAP *ld; + LDAPMessage *entry; /* pointer to current message */ + /* loop on attribute */ + char *attr; /* pointer to current attribute */ + BerElement *attr_ber; + /* loop on attribute values */ + struct berval **p; /* pointer to current value */ + struct berval **vals; + int eom; +}; + +ldapsearch_result* +ldapsearch_iterator(LDAP *ld, LDAPMessage *res); + +int/*bool*/ +ldapsearch_advance(ldapsearch_result* r); + + +#ifdef USE_LDAP_STORE +void ENGINE_load_ldap(void); +#endif + + +#undef TRACE_BY_LDAP_ENABLED +#ifdef TRACE_BY_LDAP +# undef TRACE_BY_LDAP +# define TRACE_BY_LDAP_ENABLED 1 +void TRACE_BY_LDAP(const char *f, const char *fmt, ...); +#else +static inline void +TRACE_BY_LDAP(const char *f, const char *fmt, ...) { + UNUSED(f); + UNUSED(fmt); +} +#endif + +#endif /*ndef SSH_LDAP_H*/ diff -ruN openssh-9.4p1/sshlogin.c openssh-9.4p1+x509-14.2.1/sshlogin.c --- openssh-9.4p1/sshlogin.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/sshlogin.c 2023-08-20 10:07:01.000000000 +0300 @@ -57,7 +57,6 @@ #include #include "sshlogin.h" -#include "ssherr.h" #include "loginrec.h" #include "log.h" #include "sshbuf.h" @@ -78,6 +77,7 @@ { struct logininfo li; + UNUSED(logname); login_get_lastlog(&li, uid); strlcpy(buf, li.hostname, bufsize); return (time_t)li.tv_sec; @@ -90,26 +90,25 @@ static void store_lastlog_message(const char *user, uid_t uid) { -#ifndef NO_SSH_LASTLOG -# ifndef CUSTOM_SYS_AUTH_GET_LASTLOGIN_MSG - char hostname[HOST_NAME_MAX+1] = ""; - time_t last_login_time; -# endif char *time_string; int r; if (!options.print_lastlog) return; -# ifdef CUSTOM_SYS_AUTH_GET_LASTLOGIN_MSG +#ifdef CUSTOM_SYS_AUTH_GET_LASTLOGIN_MSG time_string = sys_auth_get_lastlogin_msg(user, uid); if (time_string != NULL) { if ((r = sshbuf_put(loginmsg, time_string, strlen(time_string))) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "buffer error"); free(time_string); } -# else +#else +{ + char hostname[HOST_NAME_MAX+1] = ""; + time_t last_login_time; + last_login_time = get_last_login_time(uid, user, hostname, sizeof(hostname)); @@ -125,8 +124,8 @@ if (r != 0) fatal_fr(r, "sshbuf_putf"); } -# endif /* CUSTOM_SYS_AUTH_GET_LASTLOGIN_MSG */ -#endif /* NO_SSH_LASTLOG */ +} +#endif /* CUSTOM_SYS_AUTH_GET_LASTLOGIN_MSG */ } /* diff -ruN openssh-9.4p1/ssh-ocsp.c openssh-9.4p1+x509-14.2.1/ssh-ocsp.c --- openssh-9.4p1/ssh-ocsp.c 1970-01-01 02:00:00.000000000 +0200 +++ openssh-9.4p1+x509-14.2.1/ssh-ocsp.c 2023-08-20 10:07:01.000000000 +0300 @@ -0,0 +1,1014 @@ +/* + * Copyright (c) 2004-2021 Roumen Petrov. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "x509store.h" +#ifndef SSH_OCSP_ENABLED +# include "error: OCSP is disabled" +#endif + +#if 1 +# /* not yet fully implemented */ +# define SSH_WITH_SSLOCSP +#endif + +#include + +#include "xmalloc.h" +#include "log.h" +#include +#include +#ifdef SSH_WITH_SSLOCSP +# include +#endif + +#if defined(sk_OPENSSL_STRING_new_null) || defined(HAVE_SK_OPENSSL_STRING_NEW_NULL) +/* + * STACK_OF(OPENSSL_STRING) is defined in OpenSSL 1.0. + * NOTE: We test for definition of sk_OPENSSL_STRING_new_null + * instead OpenSSL version number! As in OpenSSL 1.1 stack functions + * are inlined we use configure check as well. + */ +#define ssh_sk_OPENSSL_STRING STACK_OF(OPENSSL_STRING) + +static inline void +OPENSSL_STRING_free(OPENSSL_STRING p) { +/* free warnings for OpenSSL 1+: +.../ssh-ocsp.c: In function 'ssh_ocsp_validate2': +.../ssh-ocsp.c:845: warning: pointer type mismatch in conditional expression +.../ssh-ocsp.c:845: warning: ISO C forbids conversion of object pointer to function pointer type +*/ + free(p); +} + +#else /* !def sk_OPENSSL_STRING_new_null */ + +#ifdef sk_STRING_new_null +/*some OpenSSL 1.0 pre and release candidate */ +# define ssh_sk_OPENSSL_STRING STACK_OF(STRING) +# define sk_OPENSSL_STRING_new_null sk_STRING_new_null +# define sk_OPENSSL_STRING_push sk_STRING_push +# define sk_OPENSSL_STRING_num sk_STRING_num +# define sk_OPENSSL_STRING_value sk_STRING_value +# define sk_OPENSSL_STRING_pop_free sk_STRING_pop_free + +static inline void +OPENSSL_STRING_free(STRING p) { + free(p); +} + +#else /* !def sk_STRING_new_null */ + +# define ssh_sk_OPENSSL_STRING STACK +# define sk_OPENSSL_STRING_new_null sk_new_null +# define sk_OPENSSL_STRING_push sk_push +# define sk_OPENSSL_STRING_num sk_num +# define sk_OPENSSL_STRING_value sk_value +# define sk_OPENSSL_STRING_pop_free sk_pop_free + +#define OPENSSL_STRING_free free + +#endif /*def sk_STRING_new_null*/ + +#endif /*def sk_OPENSSL_STRING_new_null*/ + +#ifndef HAVE_TLS_CLIENT_METHOD /* OpenSSL < 1.1 */ +/* NOTE since 18 Mar 2012 OpenSSL uses only v23 method */ +# define TLS_client_method SSLv23_client_method +#endif + +static VAOptions va = { SSHVA_NONE, NULL, NULL }; + +typedef struct va_type_map_s va_type_map; +struct va_type_map_s { + int id; + const char* code; +}; + +static va_type_map sshva_type_map[] = { + { SSHVA_NONE , "none" }, + { SSHVA_OCSP_CERT, "ocspcert" }, + { SSHVA_OCSP_SPEC, "ocspspec" }, +}; + + +int +ssh_get_default_vatype(void) { + return(SSHVA_NONE); +} + + +int +ssh_get_vatype_s(const char* type) { + int k, n; + + if (type == NULL) return(-1); + + n = sizeof(sshva_type_map) / sizeof(sshva_type_map[0]); + for (k = 0; k < n; k++) { + va_type_map *p = sshva_type_map + k; + if (strcasecmp(type, p->code) == 0) return(p->id); + } + + return(-1); +} + + +const char* +ssh_get_vatype_i(int id) { + int k, n; + + n = sizeof(sshva_type_map) / sizeof(sshva_type_map[0]); + for (k = 0; k < n; k++) { + va_type_map *p = sshva_type_map + k; + if (id == p->id) return(p->code); + } + + return("UNKNOWN"); +} + + +static void +ssh_set_vatype(int type) { + switch (type) { + case SSHVA_NONE: + case SSHVA_OCSP_CERT: + case SSHVA_OCSP_SPEC: + va.type = type; + break; + default: + fatal_f("invalid type %d", type); + break; + } +} + + +void +ssh_set_validator(const VAOptions *_va) { + if (va.certificate_file != NULL) { + free((void*)va.certificate_file); + va.certificate_file = NULL; + } + if (va.responder_url != NULL) { + free((void*)va.responder_url); + va.responder_url = NULL; + } + if (_va == NULL) { + debug_f("NULL options - set vatype to none"); + ssh_set_vatype(SSHVA_NONE); + return; + } + + ssh_set_vatype(_va->type); /*fatal on error*/ + if (_va->certificate_file != NULL) { + switch(va.type) { + case SSHVA_NONE: + case SSHVA_OCSP_CERT: + debug_f("ignore certificate file"); + break; + case SSHVA_OCSP_SPEC: + va.certificate_file = xstrdup(_va->certificate_file); /*fatal on error*/ + break; + } + } + switch(va.type) { + case SSHVA_NONE: + case SSHVA_OCSP_CERT: + debug_f("ignore responder url"); + break; + case SSHVA_OCSP_SPEC: + if (_va->responder_url == NULL) { + fatal_f("responder url is mandatory"); + } + va.responder_url = xstrdup(_va->responder_url); /*fatal on error*/ + break; + } +} + + +static char* +ssh_ASN1_GENERALIZEDTIME_2_string(ASN1_GENERALIZEDTIME *asn1_time) { + BIO *bio; + int k; + char *p = NULL; + + if (asn1_time == NULL) { + error_f("asn1_time is NULL"); + return(NULL); + } + + bio = BIO_new(BIO_s_mem()); + if (bio == NULL) { + error_f("BIO_new fail"); + return(NULL); + } + + ASN1_GENERALIZEDTIME_print(bio, asn1_time); + (void)BIO_flush(bio); + + k = BIO_pending(bio); + p = xmalloc(k + 1); /*fatal on error*/ + k = BIO_read(bio, p, k); + p[k] = '\0'; + BIO_free_all(bio); + return(p); +} + + +static STACK_OF(X509)* +ssh_load_x509certs(const char *certs_file, const char* certs_descrip) { + STACK_OF(X509) *ret_certs = NULL; + BIO *fbio = NULL; + + if (certs_file == NULL) { + error_f("file is NULL"); + goto exit; + } + + ret_certs = sk_X509_new_null(); + if (ret_certs == NULL) { + error_f("sk_X509_new_null fail"); + goto exit; + } + + fbio = BIO_new(BIO_s_file()); + if (fbio == NULL) { + error_f("BIO_new fail"); + goto exit; + } + + if (BIO_read_filename(fbio, certs_file) <= 0) { + error_crypto_fmt("BIO_read_filename", + " description '%.128s, filename '%.256s'", + certs_descrip, certs_file); + goto exit; + } + + { + int k; + STACK_OF(X509_INFO) *data; + + data = PEM_X509_INFO_read_bio(fbio, NULL, NULL, NULL); + if (data == NULL) { + error_f("no data."); + goto exit; + } + + for (k = 0; k < sk_X509_INFO_num(data); k++) { + X509_INFO *xi = sk_X509_INFO_value(data, k); + if (xi->x509) { + sk_X509_push(ret_certs, xi->x509); + xi->x509 = NULL; + } + } + sk_X509_INFO_pop_free(data, X509_INFO_free); + } + +exit: + BIO_free_all(fbio); + if (ret_certs != NULL) { + debug3_f("return %d certs", (int)sk_X509_num(ret_certs)); + } else { + debug_f("return NULL"); + } + return(ret_certs); +} + + +static int/*bool*/ +ssh_ocspreq_addcert( + X509 *cert, + X509_STORE* x509store, + OCSP_REQUEST *req, + STACK_OF(OCSP_CERTID) *ids, + ssh_sk_OPENSSL_STRING *subjs +) { + X509 *issuer = NULL; + OCSP_CERTID *id = NULL; + char *subj = NULL; + + if (cert == NULL) { + error_f("cert is NULL"); + return(0); + } + if (x509store == NULL) { + error_f("x509store is NULL"); + return(0); + } + if (req == NULL) { + error_f("req is NULL"); + return(0); + } + if (ids == NULL) { + error_f("ids is NULL"); + return(0); + } + if (subjs == NULL) { + error_f("subjs is NULL"); + return(0); + } + + issuer = ssh_x509store_get_cert_by_subject(x509store, X509_get_issuer_name(cert)); + if (issuer == NULL) { + error_f("cannot found issuer certificate"); + return(0); + } + + id = OCSP_cert_to_id(NULL, cert, issuer); + if (id == NULL) { + error_f("OCSP_cert_to_id fail"); + return(0); + } + + if (!OCSP_request_add0_id(req, id)) { + error_f("OCSP_request_add0_id fail"); + return(0); + } + if (!sk_OCSP_CERTID_push(ids, id)) { + error_f("sk_OCSP_CERTID_push fail"); + return(0); + } + subj = ssh_X509_NAME_oneline(X509_get_subject_name(cert)); /*fatal on error*/ + if (!sk_OPENSSL_STRING_push(subjs, subj)) { + error_f("sk_push(..., subj) fail"); + return(0); + } + + return(1); +} + + +struct ssh_ocsp_conn_s { + const char *url; + +#ifdef SSH_WITH_SSLOCSP + int use_ssl; +#endif + /*pointers inside data buffer*/ + /*const*/ char *host; + const char *port; + const char *path; + + /*data buffer to hold all connection info*/ + char *data; +}; + +typedef struct ssh_ocsp_conn_s ssh_ocsp_conn; + + +static void +ssh_ocsp_conn_free(ssh_ocsp_conn **pconn) { + ssh_ocsp_conn *conn = *pconn; + + if (conn == NULL) return; + *pconn = NULL; + + /* we don't need to clean items */ + if (conn->path != NULL) free((void*)conn->path); + if (conn->data != NULL) free(conn->data); + if (conn->url != NULL) free((void*)conn->url ); + free(conn); +} + + +static int/*bool*/ +ssh_ocsp_set_protocol(ssh_ocsp_conn *conn, const char *protocol) { + if (strcmp(protocol, "http") == 0) { +#ifdef SSH_WITH_SSLOCSP + conn->use_ssl = 0; +#endif + return(1); + } + +#ifdef SSH_WITH_SSLOCSP + if (strcmp(protocol, "https") == 0) { + conn->use_ssl = 1; + return(1); + } +#endif + +#ifdef SSH_WITH_SSLOCSP + conn->use_ssl = -1; +#endif + return(0); +} + + +static ssh_ocsp_conn* +ssh_ocsp_conn_new(const char *url) { + ssh_ocsp_conn *conn = NULL; + char *p = NULL; + char *q = NULL; + + if (url == NULL) { + error_f("url is NULL"); + return(NULL); + } + + conn = xmalloc(sizeof(*conn)); /*fatal on error*/ + memset(conn, 0, sizeof(*conn)); + + conn->url = xstrdup(url); /*fatal on error*/ + conn->data = xstrdup(url); /*fatal on error*/ + + /* check for protocol */ + p = conn->data; + q = strchr(p, ':'); + if (q == NULL) goto error; + *q = '\x0'; + + if (!ssh_ocsp_set_protocol(conn, p)) { + error_f("unsupported protocol '%.16s'", p); + goto error; + } + + p = q; + if (*++p != '/') { /*this symbol is inside data */ + error_f("expected first slash, got char with code %d", (int)*p); + goto error; + } + if (*++p != '/') { /*this symbol is inside data */ + error_f("expected second slash, got char with code %d", (int)*p); + goto error; + } + + /* check for host and port */ + if (*++p == '\x0') { + error_f("missing host in url '%.512s'", url); + goto error; + } + conn->host = p; + q = strchr(p, '/'); + if (q != NULL) { + if (q[1] != '\x0') conn->path = xstrdup(q); /*fatal on error*/ + *q = '\x0'; + /* now p(conn->host) point only to host{:port} */ + } + /*else q is NULL !!!*/ + + /* check for port */ + p = strrchr(conn->host, ':'); + if (p != NULL) { + *p = '\x0'; + if (*++p != '\x0') conn->port = p; + } + if (conn->port == NULL) { +#ifdef SSH_WITH_SSLOCSP + conn->port = conn->use_ssl ? "443" : "80"; +#else + conn->port = "80"; +#endif + } + +exit: + return(conn); +error: + ssh_ocsp_conn_free(&conn); + goto exit; +} + + +static OCSP_RESPONSE* +ssh_ocsp_get_response(const ssh_ocsp_conn *conn, OCSP_REQUEST *req) { + OCSP_RESPONSE *resp = NULL; + BIO *bio_conn = NULL; +#ifdef SSH_WITH_SSLOCSP + SSL_CTX *ctx = NULL; +#endif + + if (conn == NULL) { + error_f("conn is NULL"); + return(NULL); + } + if (req == NULL) { + error_f("req is NULL"); + return(NULL); + } + +#ifndef OPENSSL_NO_SOCK + bio_conn = BIO_new_connect(conn->host); + if (bio_conn == NULL) { + error_crypto("BIO_new_connect"); + goto exit; + } +#else + error_f("sockets are not supported in OpenSSL"); + goto exit; +#endif + if (conn->port != NULL) { + BIO_set_conn_port(bio_conn, conn->port); + } + +#ifdef SSH_WITH_SSLOCSP + if (conn->use_ssl == 1) { + BIO *bio_sslconn; + ctx = SSL_CTX_new(TLS_client_method()); + SSL_CTX_set_mode(ctx, SSL_MODE_AUTO_RETRY); + bio_sslconn = BIO_new_ssl(ctx, 1); + bio_conn = BIO_push(bio_sslconn, bio_conn); + } +#endif /*def SSH_WITH_SSLOCSP*/ + + if (BIO_do_connect(bio_conn) <= 0) { + error_crypto("BIO_do_connect"); + goto exit; + } + + /* + * OCSP_sendreq_bio accept null as path argument but if path + * is null http request will contain what is incorrect. + */ + resp = OCSP_sendreq_bio(bio_conn, (char*)(conn->path ? conn->path : "/") , req); + if (resp == NULL) { + error_crypto("OCSP_sendreq_bio"); + } + +exit: + BIO_free_all(bio_conn); +#ifdef SSH_WITH_SSLOCSP + SSL_CTX_free(ctx); +#endif + + return(resp); +} + + +static OCSP_BASICRESP* +ssh_ocsp_get_basicresp( + OCSP_REQUEST *req, + OCSP_RESPONSE *resp, + STACK_OF(X509) *vacrts, + X509_STORE *x509store +) { + OCSP_BASICRESP *br = NULL; + unsigned long basic_verify_flags = 0/*NO:OCSP_NOEXPLICIT*/; + int flag; + + if (req == NULL) { + error_f("req is NULL"); + return(NULL); + } + if (resp == NULL) { + error_f("resp is NULL"); + return(NULL); + } + if (x509store == NULL) { + error_f("x509store is NULL"); + return(NULL); + } + + br = OCSP_response_get1_basic(resp); + if (br == NULL) { + error_crypto("OCSP_response_get1_basic"); + return(NULL); + } + + flag = OCSP_check_nonce(req, br); + if (flag <= 0) { + if (flag == -1) { + error_f("WARNING - no nonce in response"); + } else { + error_crypto("OCSP_check_nonce"); + goto error; + } + } + +#ifdef SSHOCSPTEST +{ +int k; +error_f("VA certs num=%d", sk_X509_num(vacrts)); +for (k = 0; k < sk_X509_num(vacrts); k++) { + char *buf; + X509 *x = sk_X509_value(vacrts, k); + buf = ssh_X509_NAME_oneline(X509_get_subject_name(x)); /*fatal on error*/ + error_f("VA[%d] subject='%s'", k, buf); + free(buf); +} +} +#endif /*def SSHOCSPTEST*/ + +/* + * RFC2560: + * ... + * All definitive response messages SHALL be digitally signed. The key + * used to sign the response MUST belong to one of the following: + * + * -- the CA who issued the certificate in question + * -- a Trusted Responder whose public key is trusted by the requester + * -- a CA Designated Responder (Authorized Responder) who holds a + * specially marked certificate issued directly by the CA, indicating + * that the responder may issue OCSP responses for that CA + * ... + * + * TODO: to check OpenSSL implementation + */ + if ((vacrts == NULL) || (sk_X509_num(vacrts) <= 0)) { + flag = -1; + } else { + /* + * With flag OCSP_TRUSTOTHER: + * - we never get error 'without missing ocspsigning + * usage' for VA certificate !!! + * Without flag OCSP_TRUSTOTHER: + * - we can get OCSP_basic_verify error "root ca not trusted" + */ +#if 0 + flag = OCSP_basic_verify(br, vacrts, x509store, basic_verify_flags | OCSP_TRUSTOTHER); +#else + flag = OCSP_basic_verify(br, vacrts, x509store, basic_verify_flags); +#endif + } + if (flag < 0) { + flag = OCSP_basic_verify(br, NULL, x509store, basic_verify_flags); + } + if (flag <= 0) { + error_crypto_fmt("OCSP_basic_verify", "flag=%d", flag); + goto error; + } + + debug3_f("OK"); + return(br); + +error: + debug3_f("FAIL"); + OCSP_BASICRESP_free(br); + return(NULL); +} + + +/* + * Method return value: + * 1 - all cert.-s are good + * -1 - error or at least one cert. with status unknown + * 0 - otherwise, i.e. at least one cert. is revoked and rest are good + */ +static int +ssh_ocsp_check_validity( + OCSP_REQUEST *req, + OCSP_BASICRESP *br, + STACK_OF(OCSP_CERTID) *ids, + ssh_sk_OPENSSL_STRING *subjs +) { + int ret = 1; + /* Maximum leeway in validity period: default 5 minutes */ + const long nsec = (5 * 60); + const long maxage = -1; + + int k; + int status, reason; + ASN1_GENERALIZEDTIME *rev, *thisupd, *nextupd; + + if (req == NULL) { + error_f("req is NULL"); + return(-1); + } + if (br == NULL) { + error_f("br is NULL"); + return(-1); + } + if (sk_OCSP_CERTID_num(ids) <= 0) { + error_f("number of ids is %d", sk_OCSP_CERTID_num(ids)); + return(-1); + } + if (sk_OPENSSL_STRING_num(subjs) <= 0) { + error_f("number of subjs is %d", sk_OPENSSL_STRING_num(subjs)); + return(-1); + } + if (sk_OCSP_CERTID_num(ids) != sk_OPENSSL_STRING_num(subjs)) { + error_f("ids(%d) != subjs(%d)", sk_OCSP_CERTID_num(ids), sk_OPENSSL_STRING_num(subjs)); + return(-1); + } + + for (k = 0; k < sk_OCSP_CERTID_num(ids); k++) { + OCSP_CERTID *id = sk_OCSP_CERTID_value(ids, k); + + if (get_log_level() >= SYSLOG_LEVEL_DEBUG3) { + char *subject = sk_OPENSSL_STRING_value(subjs, k); + debug3_f("cert[%d]='%s'", k, subject); + } + + if (!OCSP_resp_find_status( + br, id, &status, &reason, + &rev, &thisupd, &nextupd) + ) { + ret = -1; + error_f("cannot found status"); + break; + } + + if (!OCSP_check_validity(thisupd, nextupd, nsec, maxage)) { + error_crypto_fmt("OCSP_check_validity", "WARNING-invalid status time"); + ret = -1; + break; + } + debug_f("status=%.32s", OCSP_cert_status_str(status)); + if (get_log_level() >= SYSLOG_LEVEL_DEBUG3) { + char *p = ssh_ASN1_GENERALIZEDTIME_2_string(thisupd); + debug3_f("This Update=%.128s", p); + free(p); + if (nextupd != NULL) { + p = ssh_ASN1_GENERALIZEDTIME_2_string(nextupd); + debug3_f("Next Update=%.128s", p); + free(p); + } + } + + if (status == V_OCSP_CERTSTATUS_GOOD) continue; + + if (status != V_OCSP_CERTSTATUS_REVOKED) { + ret = -1; + error_f("unknown certificate status"); + break; + } + + ret = 0; + if (get_log_level() >= SYSLOG_LEVEL_DEBUG3) { + char *p = ssh_ASN1_GENERALIZEDTIME_2_string(rev); + debug3_f("Revocation Time=%.128s", p); + free(p); + if (reason != -1) { + debug3_f("Revocation Reason='%.128s'", OCSP_crl_reason_str(reason)); + } + } + break; + } + debug3_f("return %d", ret); + return(ret); +} + + +static int +ssh_ocsp_validate2( + X509 *cert, + X509_STORE *x509store, + const ssh_ocsp_conn *ocsp +) { + int ret = -1; + int add_nonce = 0; + + STACK_OF(X509) *vacrts = NULL; + OCSP_REQUEST *req = OCSP_REQUEST_new(); + STACK_OF(OCSP_CERTID) *ids = sk_OCSP_CERTID_new_null(); + ssh_sk_OPENSSL_STRING *subjs = sk_OPENSSL_STRING_new_null(); + OCSP_RESPONSE *resp = NULL; + OCSP_BASICRESP *br = NULL; + + if ((va.type == SSHVA_OCSP_SPEC) && + (va.certificate_file != NULL)) { + vacrts = ssh_load_x509certs(va.certificate_file, "'OCSP Responder' trusted certificates"); + if (vacrts == NULL) goto exit; + debug_f("VA certs num=%d", sk_X509_num(vacrts)); + } + + /*NOTE: functiona fail on NULL argument*/ + if (!ssh_ocspreq_addcert(cert, x509store, req, ids, subjs)) + goto exit; + + if (add_nonce) { + if (!OCSP_request_add1_nonce(req, NULL, -1)) + goto exit; + } + + resp = ssh_ocsp_get_response(ocsp, req); + if (resp == NULL) goto exit; + + { /*check OCSP response status*/ + int flag = OCSP_response_status(resp); + if (flag != OCSP_RESPONSE_STATUS_SUCCESSFUL) { + error_f("responder error=%d(%.256s)", flag, OCSP_response_status_str((long/*???*/)flag)); + goto exit; + } + } + + br = ssh_ocsp_get_basicresp(req, resp, vacrts, x509store); + if (br == NULL) goto exit; + + ret = ssh_ocsp_check_validity(req, br, ids, subjs); + +exit: + OCSP_BASICRESP_free(br); + OCSP_RESPONSE_free(resp); + sk_OPENSSL_STRING_pop_free(subjs, OPENSSL_STRING_free); + sk_OCSP_CERTID_free(ids); + OCSP_REQUEST_free(req); + sk_X509_pop_free(vacrts, X509_free); + + return ret; +} + + +static AUTHORITY_INFO_ACCESS* +ssh_aia_get(X509_EXTENSION *ext) { + X509V3_EXT_METHOD *method = NULL; + void *ext_str = NULL; + const unsigned char *p; + int len; + + if (ext == NULL) { + error_f("ext is NULL"); + return(NULL); + } + + method = (X509V3_EXT_METHOD*) X509V3_EXT_get(ext); + if (method == NULL) { + debug_f("cannot get method"); + return(NULL); + } + +{ + ASN1_OCTET_STRING *ext_val = X509_EXTENSION_get_data(ext); + ssh_ASN1_STRING_get0_data(ext_val, &p, &len); +} + + if (method->it) { + ext_str = ASN1_item_d2i(NULL, &p, len, ASN1_ITEM_ptr(method->it)); + } else { + ext_str = method->d2i(NULL, &p, len); + } + if (ext_str == NULL) { + debug_f("null ext_str!"); + return(NULL); + } + + return((AUTHORITY_INFO_ACCESS*)ext_str); +} + + +static void +ssh_aia_free(X509_EXTENSION *ext, AUTHORITY_INFO_ACCESS* aia) { + X509V3_EXT_METHOD *method = NULL; + + if (ext == NULL) return; + + method = (X509V3_EXT_METHOD*) X509V3_EXT_get(ext); + if (method == NULL) return; + + if (method->it) { + ASN1_item_free((void*)aia, ASN1_ITEM_ptr(method->it)); + } else { + method->ext_free(aia); + } +} + + +static int +ssh_aiaocsp_validate( + X509 *cert, + X509_STORE *x509store, + AUTHORITY_INFO_ACCESS *aia, + int *has_ocsp_url +) { + int ret = -1; + int k; + if (has_ocsp_url == NULL) { + fatal_f("has_ocsp_url is NULL"); + return(-1); /*;-)*/ + } + + *has_ocsp_url = 0; + for (k = 0; k < sk_ACCESS_DESCRIPTION_num(aia); k++) { + ACCESS_DESCRIPTION *ad = sk_ACCESS_DESCRIPTION_value(aia, k); + GENERAL_NAME *gn; + ASN1_IA5STRING *uri; + ssh_ocsp_conn *conn; + + if (OBJ_obj2nid(ad->method) != NID_ad_OCSP) continue; + + gn = ad->location; +#if 0 +{ +BIO *bio = BIO_new_fp(stderr, BIO_NOCLOSE); +if (bio != NULL) { + BIO_puts(bio, "gn->type:"); + switch (gn->type) { + case GEN_OTHERNAME : BIO_puts(bio, "GEN_OTHERNAME"); break; + case GEN_EMAIL : BIO_puts(bio, "GEN_EMAIL" ); break; + case GEN_DNS : BIO_puts(bio, "GEN_DNS" ); break; + case GEN_X400 : BIO_puts(bio, "GEN_X400" ); break; + case GEN_DIRNAME : BIO_puts(bio, "GEN_DIRNAME" ); break; + case GEN_EDIPARTY : BIO_puts(bio, "GEN_EDIPARTY" ); break; + case GEN_URI : BIO_puts(bio, "GEN_URI" ); break; + case GEN_IPADD : BIO_puts(bio, "GEN_IPADD" ); break; + case GEN_RID : BIO_puts(bio, "GEN_RID" ); break; + default : BIO_puts(bio, "[unsupported]"); break; + } + BIO_puts(bio, "\n"); + BIO_free(bio); +} +} +#endif + if (gn->type != GEN_URI) continue; + + uri = gn->d.uniformResourceIdentifier; + *has_ocsp_url = 1; + + conn = ssh_ocsp_conn_new((const char*)uri->data); + if (conn == NULL) { + debug_f("cannot create ocsp connection"); + continue; + } + ret = ssh_ocsp_validate2(cert, x509store, conn); + ssh_ocsp_conn_free(&conn); + + if (ret >= 0) break; + } + + return(*has_ocsp_url ? ret : 1); +} + + +static int +ssh_ocsp_validate4cert(X509 *cert, X509_STORE *x509store) { + int found = 0; + int ret = -1; + int loc = -1; + + if (cert == NULL) return(0); + + for ( loc = X509_get_ext_by_NID(cert, NID_info_access, loc); + loc >= 0; + loc = X509_get_ext_by_NID(cert, NID_info_access, loc) + ) { + X509_EXTENSION *xe; + + xe = X509_get_ext(cert, loc); + if (xe == NULL) { + debug_f("cannot get x509 extension"); + continue; + } + + {/*validate from AIA*/ + AUTHORITY_INFO_ACCESS *aia = ssh_aia_get(xe); + if (aia == NULL) continue; + + ret = ssh_aiaocsp_validate(cert, x509store, aia, &found); + + ssh_aia_free(xe, aia); + } + + if (ret >= 0) break; + } + + if (found) { + debug3_f("validation result=%d", ret); + } else { + debug3_f("no OCSP 'Service Locator' URL"); + } + return(found ? ret : 1); +} + + +int +ssh_ocsp_validate(X509 *cert, X509_STORE *x509store) { + int ret = -1; + ssh_ocsp_conn *conn = NULL; + + if (get_log_level() >= SYSLOG_LEVEL_DEBUG3) { + char *buf = ssh_X509_NAME_oneline(X509_get_subject_name(cert)); /*fatal on error*/ + debug3_f("for '%s'", buf); + free(buf); + } + + switch (va.type) { + default: + /*when something is missing*/ + fatal_f("invalid validator type %d", va.type); + break; /*;-)*/ + case SSHVA_NONE: + debug3_f("none"); + ret = 1; + break; + case SSHVA_OCSP_CERT: + ret = ssh_ocsp_validate4cert(cert, x509store); + break; + case SSHVA_OCSP_SPEC: + conn = ssh_ocsp_conn_new(va.responder_url); + if (conn != NULL) { + ret = ssh_ocsp_validate2(cert, x509store, conn); + ssh_ocsp_conn_free(&conn); + } + break; + } + + return(ret); +} diff -ruN openssh-9.4p1/ssh-pkcs11.c openssh-9.4p1+x509-14.2.1/ssh-pkcs11.c --- openssh-9.4p1/ssh-pkcs11.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/ssh-pkcs11.c 2023-08-20 10:07:01.000000000 +0300 @@ -1,7 +1,9 @@ /* $OpenBSD: ssh-pkcs11.c,v 1.59 2023/07/27 22:26:49 djm Exp $ */ /* * Copyright (c) 2010 Markus Friedl. All rights reserved. - * Copyright (c) 2014 Pedro Martelletto. All rights reserved. + * Copyright (c) 2011 Kenneth Robinette. All rights reserved. + * Copyright (c) 2013 Andrew Cooke. All rights reserved. + * Copyright (c) 2016-2023 Roumen Petrov. All rights reserved. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -16,38 +18,95 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifndef USE_OPENSSL_PROVIDER +/* TODO: implement OpenSSL 4.0 API, as OpenSSL 3.* is quite nonfunctional */ +# define OPENSSL_SUPPRESS_DEPRECATED +#endif + +#define SSHKEY_INTERNAL #include "includes.h" #ifdef ENABLE_PKCS11 -#ifdef HAVE_SYS_TIME_H -# include +#ifndef HAVE_RSA_PKCS1_OPENSSL +# undef RSA_PKCS1_OpenSSL +# define RSA_PKCS1_OpenSSL RSA_PKCS1_SSLeay #endif #include +#ifdef HAVE_SYS_TIME_H +# include +#endif #include #include -#include #include #include #include "openbsd-compat/sys-queue.h" -#include "openbsd-compat/openssl-compat.h" -#include #include #include +#include "evp-compat.h" #define CRYPTOKI_COMPAT #include "pkcs11.h" #include "log.h" #include "misc.h" -#include "sshkey.h" +#include "ssh-x509.h" #include "ssh-pkcs11.h" #include "digest.h" #include "xmalloc.h" +#include "sshbuf.h" + +extern int X509_from_blob(const u_char *blob, size_t blen, X509 **xp); +extern struct sshkey* x509_to_key(X509 *x509); + + +#ifndef HAVE_RSA_GET0_KEY +/* opaque RSA key structure */ +static inline int +RSA_set0_key(RSA *rsa, BIGNUM *n, BIGNUM *e, BIGNUM *d) { +/* If the fields in r are NULL, the corresponding input parameters MUST + * be non-NULL for n and e. d may be left NULL (in case only the + * public key is used). + * + * It is an error to give the results from get0 on r as input + * parameters. + */ + if (n == rsa->n || e == rsa->e + || (rsa->d != NULL && d == rsa->d)) + return 0; + + if (n != NULL) { BN_free(rsa->n); rsa->n = n; } + if (e != NULL) { BN_free(rsa->e); rsa->e = e; } + if (d != NULL) { BN_free(rsa->d); rsa->d = d; } + + return 1; +} +#endif /*ndef HAVE_RSA_GET0_KEY*/ + +#ifdef OPENSSL_HAS_ECC +#ifndef HAVE_ECDSA_SIG_SET0 /* OpenSSL < 1.1 */ +static inline int/*bool*/ +ECDSA_SIG_set0(ECDSA_SIG *sig, BIGNUM *r, BIGNUM *s) { + if (r == NULL || s == NULL) return 0; + + BN_clear_free(sig->r); + BN_clear_free(sig->s); + + sig->r = r; + sig->s = s; + return 1; +} +#endif /*ndef HAVE_ECDSA_SIG_SET0 OpenSSL < 1.1 */ +#endif /*OPENSSL_HAS_ECC*/ + struct pkcs11_slotinfo { CK_TOKEN_INFO token; @@ -68,8 +127,47 @@ TAILQ_ENTRY(pkcs11_provider) next; }; +static void +pkcs11_provider_free(struct pkcs11_provider *p) { + if (p == NULL) return; + + free(p->name); + free(p->slotlist); + free(p->slotinfo); + free(p); +} + TAILQ_HEAD(, pkcs11_provider) pkcs11_providers; + +static inline void +crypto_pkcs11_error(CK_RV err) { + char buf[64]; + switch (err) { + case CKR_PIN_LEN_RANGE: + snprintf(buf, sizeof(buf), "PIN length out of range"); + break; + case CKR_PIN_INCORRECT: + snprintf(buf, sizeof(buf), "PIN incorrect"); + break; + case CKR_PIN_LOCKED: + snprintf(buf, sizeof(buf), "PIN locked"); + break; + default: + snprintf(buf, sizeof(buf), "pkcs#11 error 0x%lx", (unsigned long)err); + } + ERR_add_error_data(1, buf); +} + + +/* + * Constants used when creating the context extra data + */ +static int ssh_pkcs11_rsa_ctx_index = -1; +#ifdef OPENSSL_HAS_ECC +static int ssh_pkcs11_ec_ctx_index = -1; +#endif /*def OPENSSL_HAS_ECC*/ + struct pkcs11_key { struct pkcs11_provider *provider; CK_ULONG slotidx; @@ -77,19 +175,73 @@ int keyid_len; }; -int pkcs11_interactive = 0; +static void pkcs11_provider_unref(struct pkcs11_provider *p); + +static struct pkcs11_key * +pkcs11_key_create( + struct pkcs11_provider *provider, + CK_ULONG slotidx, + CK_ATTRIBUTE *keyid_attrib +) { + struct pkcs11_key *k11; + + k11 = xcalloc(1, sizeof(*k11)); /*fatal on error*/ + k11->provider = provider; + provider->refcount++; /* provider referenced by RSA key */ + k11->slotidx = slotidx; + /* identify key object on smartcard */ + k11->keyid_len = keyid_attrib->ulValueLen; + if (k11->keyid_len > 0) { + k11->keyid = xmalloc(k11->keyid_len); /*fatal on error*/ + memcpy(k11->keyid, keyid_attrib->pValue, k11->keyid_len); + } + + return k11; +} -#if defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW) static void -ossl_error(const char *msg) -{ - unsigned long e; +pkcs11_key_free(struct pkcs11_key *k11) { + if (k11 == NULL) return; + + if (k11->provider) + pkcs11_provider_unref(k11->provider); + free(k11->keyid); + free(k11); +} + +static void +CRYPTO_EX_pkcs11_key_free( + void *parent, void *ptr, CRYPTO_EX_DATA *ad, long argl, void *argp +) { + (void)parent; + pkcs11_key_free(ptr); + (void)ad; + (void)argl; + (void)argp; +} + +static void +CRYPTO_EX_pkcs11_rsa_free( + void *parent, void *ptr, CRYPTO_EX_DATA *ad, + int idx, long argl, void *argp +) { + if (idx == ssh_pkcs11_rsa_ctx_index) + CRYPTO_EX_pkcs11_key_free(parent, ptr, ad, argl, argp); +} - error_f("%s", msg); - while ((e = ERR_get_error()) != 0) - error_f("libcrypto error: %s", ERR_error_string(e, NULL)); +#ifdef OPENSSL_HAS_ECC +static void +CRYPTO_EX_pkcs11_ec_free( + void *parent, void *ptr, CRYPTO_EX_DATA *ad, + int idx, long argl, void *argp +) { + if (idx == ssh_pkcs11_ec_ctx_index) + CRYPTO_EX_pkcs11_key_free(parent, ptr, ad, argl, argp); } -#endif /* OPENSSL_HAS_ECC && HAVE_EC_KEY_METHOD_NEW */ +#endif /*def OPENSSL_HAS_ECC*/ + + +int pkcs11_interactive = 0; int pkcs11_init(int interactive) @@ -99,6 +251,120 @@ return (0); } +static int/*bool*/ +pkcs11_login( + struct pkcs11_slotinfo *si, + CK_FUNCTION_LIST *f +) { + char *pin = NULL; + + if (!(si->token.flags & CKF_LOGIN_REQUIRED)) return 1; + + if (si->logged_in) return 1; + + if (!pkcs11_interactive) { + error("need pin entry%s", (si->token.flags & + CKF_PROTECTED_AUTHENTICATION_PATH) ? + " on reader keypad" : ""); + return 0; + } + + if (si->token.flags & CKF_PROTECTED_AUTHENTICATION_PATH) + verbose("Deferring PIN entry to reader keypad."); + else { + char prompt[1024]; + + snprintf(prompt, sizeof(prompt), + "Enter PIN for '%s': ", si->token.label); + pin = read_passphrase(prompt, RP_ALLOW_EOF); + if (pin == NULL) return 0; + } + +{ CK_RV rv; + CK_ULONG lpin = (pin != NULL) ? strlen(pin) : 0; + + rv = f->C_Login(si->session, CKU_USER, (CK_UTF8CHAR_PTR)pin, lpin); + if (pin != NULL) + freezero(pin, strlen(pin)); + if (rv != CKR_OK && rv != CKR_USER_ALREADY_LOGGED_IN) { + error("C_Login failed: %lu", rv); + PKCS11err(PKCS11_LOGIN, PKCS11_C_LOGIN_FAIL); + crypto_pkcs11_error(rv); + return 0; + } +} + si->logged_in = 1; + + return 1; +} + +static int/*bool*/ +pkcs11_reauthenticate( + struct pkcs11_slotinfo *si, + CK_FUNCTION_LIST *f, + CK_OBJECT_HANDLE obj +) { + CK_RV rv; + char obj_label[1024]; + + if (!si->logged_in) return 0; + +{ /* check if re-authentication is required */ + CK_BBOOL always_authenticate = CK_FALSE; + CK_ATTRIBUTE attribs[1] = { + { CKA_ALWAYS_AUTHENTICATE, NULL, sizeof(always_authenticate) } + }; + + /* compiler work-around */ + attribs[0].pValue = &always_authenticate; + + rv = f->C_GetAttributeValue(si->session, obj, attribs, 1); + if (rv != CKR_OK) return 0; + + /* if re-authentication is not required */ + if (always_authenticate == CK_FALSE) return 1; +} + +{ /* get key label */ + CK_ATTRIBUTE attribs[1] = { + { CKA_LABEL, NULL, (sizeof(obj_label)-1) } + }; + + /* compiler work-around */ + attribs[0].pValue = obj_label; + + memset(obj_label, '\0', sizeof(obj_label)); + f->C_GetAttributeValue(si->session, obj, attribs, 1); +} + +{ /* context login, i.e. re-authentication */ + char *pin = NULL; + CK_ULONG lpin; + + if (si->token.flags & CKF_PROTECTED_AUTHENTICATION_PATH) + verbose("Deferring context PIN entry to reader keypad."); + else { + char prompt[1024]; + + snprintf(prompt, sizeof(prompt), + "Enter context PIN for '%s': ", obj_label); + pin = read_passphrase(prompt, RP_ALLOW_EOF); + } + lpin = (pin != NULL) ? strlen(pin) : 0; + + rv = f->C_Login(si->session, CKU_CONTEXT_SPECIFIC, (CK_UTF8CHAR_PTR)pin, lpin); + if (pin != NULL) + freezero(pin, strlen(pin)); + if (rv != CKR_OK) { + PKCS11err(PKCS11_REAUTHENTICATE, PKCS11_C_LOGIN_FAIL); + crypto_pkcs11_error(rv); + return 0; + } +} + + return 1; +} + /* * finalize a provider shared library, it's no longer usable. * however, there might still be keys referencing this provider, @@ -139,10 +405,7 @@ if (--p->refcount <= 0) { if (p->valid) error_f("provider \"%s\" still valid", p->name); - free(p->name); - free(p->slotlist); - free(p->slotinfo); - free(p); + pkcs11_provider_free(p); } } @@ -188,42 +451,18 @@ return (-1); } -static RSA_METHOD *rsa_method; -static int rsa_idx = 0; -#if defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW) -static EC_KEY_METHOD *ec_key_method; -static int ec_key_idx = 0; -#endif /* OPENSSL_HAS_ECC && HAVE_EC_KEY_METHOD_NEW */ - -/* release a wrapped object */ -static void -pkcs11_k11_free(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, - long argl, void *argp) -{ - struct pkcs11_key *k11 = ptr; - - debug_f("parent %p ptr %p idx %d", parent, ptr, idx); - if (k11 == NULL) - return; - if (k11->provider) - pkcs11_provider_unref(k11->provider); - free(k11->keyid); - free(k11); -} /* find a single 'obj' for given attributes */ static int pkcs11_find(struct pkcs11_provider *p, CK_ULONG slotidx, CK_ATTRIBUTE *attr, CK_ULONG nattr, CK_OBJECT_HANDLE *obj) { - CK_FUNCTION_LIST *f; - CK_SESSION_HANDLE session; + CK_FUNCTION_LIST *f = p->function_list; + CK_SESSION_HANDLE session = p->slotinfo[slotidx].session; CK_ULONG nfound = 0; CK_RV rv; int ret = -1; - f = p->function_list; - session = p->slotinfo[slotidx].session; if ((rv = f->C_FindObjectsInit(session, attr, nattr)) != CKR_OK) { error("C_FindObjectsInit failed (nattr %lu): %lu", nattr, rv); return (-1); @@ -239,182 +478,34 @@ return (ret); } -static int -pkcs11_login_slot(struct pkcs11_provider *provider, struct pkcs11_slotinfo *si, - CK_USER_TYPE type) -{ - char *pin = NULL, prompt[1024]; - CK_RV rv; - - if (provider == NULL || si == NULL || !provider->valid) { - error("no pkcs11 (valid) provider found"); - return (-1); - } - - if (!pkcs11_interactive) { - error("need pin entry%s", - (si->token.flags & CKF_PROTECTED_AUTHENTICATION_PATH) ? - " on reader keypad" : ""); - return (-1); - } - if (si->token.flags & CKF_PROTECTED_AUTHENTICATION_PATH) - verbose("Deferring PIN entry to reader keypad."); - else { - snprintf(prompt, sizeof(prompt), "Enter PIN for '%s': ", - si->token.label); - if ((pin = read_passphrase(prompt, RP_ALLOW_EOF)) == NULL) { - debug_f("no pin specified"); - return (-1); /* bail out */ - } - } - rv = provider->function_list->C_Login(si->session, type, (u_char *)pin, - (pin != NULL) ? strlen(pin) : 0); - if (pin != NULL) - freezero(pin, strlen(pin)); - - switch (rv) { - case CKR_OK: - case CKR_USER_ALREADY_LOGGED_IN: - /* success */ - break; - case CKR_PIN_LEN_RANGE: - error("PKCS#11 login failed: PIN length out of range"); - return -1; - case CKR_PIN_INCORRECT: - error("PKCS#11 login failed: PIN incorrect"); - return -1; - case CKR_PIN_LOCKED: - error("PKCS#11 login failed: PIN locked"); - return -1; - default: - error("PKCS#11 login failed: error %lu", rv); - return -1; - } - si->logged_in = 1; - return (0); -} - -static int -pkcs11_login(struct pkcs11_key *k11, CK_USER_TYPE type) -{ - if (k11 == NULL || k11->provider == NULL || !k11->provider->valid) { - error("no pkcs11 (valid) provider found"); - return (-1); - } - - return pkcs11_login_slot(k11->provider, - &k11->provider->slotinfo[k11->slotidx], type); -} - - -static int -pkcs11_check_obj_bool_attrib(struct pkcs11_key *k11, CK_OBJECT_HANDLE obj, - CK_ATTRIBUTE_TYPE type, int *val) -{ - struct pkcs11_slotinfo *si; - CK_FUNCTION_LIST *f; - CK_BBOOL flag = 0; - CK_ATTRIBUTE attr; - CK_RV rv; - - *val = 0; - - if (!k11->provider || !k11->provider->valid) { - error("no pkcs11 (valid) provider found"); - return (-1); - } - - f = k11->provider->function_list; - si = &k11->provider->slotinfo[k11->slotidx]; - - attr.type = type; - attr.pValue = &flag; - attr.ulValueLen = sizeof(flag); - - rv = f->C_GetAttributeValue(si->session, obj, &attr, 1); - if (rv != CKR_OK) { - error("C_GetAttributeValue failed: %lu", rv); - return (-1); - } - *val = flag != 0; - debug_f("provider \"%s\" slot %lu object %lu: attrib %lu = %d", - k11->provider->name, k11->slotidx, obj, type, *val); - return (0); -} - -static int -pkcs11_get_key(struct pkcs11_key *k11, CK_MECHANISM_TYPE mech_type) -{ - struct pkcs11_slotinfo *si; - CK_FUNCTION_LIST *f; - CK_OBJECT_HANDLE obj; - CK_RV rv; - CK_OBJECT_CLASS private_key_class; - CK_BBOOL true_val; - CK_MECHANISM mech; - CK_ATTRIBUTE key_filter[3]; - int always_auth = 0; - int did_login = 0; - - if (!k11->provider || !k11->provider->valid) { - error("no pkcs11 (valid) provider found"); - return (-1); - } - - f = k11->provider->function_list; - si = &k11->provider->slotinfo[k11->slotidx]; - - if ((si->token.flags & CKF_LOGIN_REQUIRED) && !si->logged_in) { - if (pkcs11_login(k11, CKU_USER) < 0) { - error("login failed"); - return (-1); - } - did_login = 1; - } +static int/*bool*/ +pkcs11_get_key( + struct pkcs11_key *k11, + CK_OBJECT_HANDLE *pobj +) { + CK_OBJECT_CLASS private_key_class = CKO_PRIVATE_KEY; + CK_BBOOL true_val = CK_TRUE; + CK_ATTRIBUTE key_filter[] = { + {CKA_CLASS, NULL, sizeof(private_key_class) }, + {CKA_ID, NULL, 0}, + {CKA_SIGN, NULL, sizeof(true_val) } + }; - memset(&key_filter, 0, sizeof(key_filter)); - private_key_class = CKO_PRIVATE_KEY; - key_filter[0].type = CKA_CLASS; + /* some compilers complain about non-constant initializer so we + use NULL in CK_ATTRIBUTE above and set the values here */ key_filter[0].pValue = &private_key_class; - key_filter[0].ulValueLen = sizeof(private_key_class); + key_filter[2].pValue = &true_val; - key_filter[1].type = CKA_ID; key_filter[1].pValue = k11->keyid; key_filter[1].ulValueLen = k11->keyid_len; - true_val = CK_TRUE; - key_filter[2].type = CKA_SIGN; - key_filter[2].pValue = &true_val; - key_filter[2].ulValueLen = sizeof(true_val); - /* try to find object w/CKA_SIGN first, retry w/o */ - if (pkcs11_find(k11->provider, k11->slotidx, key_filter, 3, &obj) < 0 && - pkcs11_find(k11->provider, k11->slotidx, key_filter, 2, &obj) < 0) { - error("cannot find private key"); - return (-1); - } - - memset(&mech, 0, sizeof(mech)); - mech.mechanism = mech_type; - mech.pParameter = NULL_PTR; - mech.ulParameterLen = 0; - - if ((rv = f->C_SignInit(si->session, &mech, obj)) != CKR_OK) { - error("C_SignInit failed: %lu", rv); - return (-1); - } - - pkcs11_check_obj_bool_attrib(k11, obj, CKA_ALWAYS_AUTHENTICATE, - &always_auth); /* ignore errors here */ - if (always_auth && !did_login) { - debug_f("always-auth key"); - if (pkcs11_login(k11, CKU_CONTEXT_SPECIFIC) < 0) { - error("login failed for always-auth key"); - return (-1); - } + if (pkcs11_find(k11->provider, k11->slotidx, key_filter, 3, pobj) < 0 && + pkcs11_find(k11->provider, k11->slotidx, key_filter, 2, pobj) < 0) { + PKCS11err(PKCS11_GET_KEY, PKCS11_FINDKEY_FAIL); + return 0; } - - return (0); + return 1; } /* openssl callback doing the actual signing operation */ @@ -425,31 +516,46 @@ struct pkcs11_key *k11; struct pkcs11_slotinfo *si; CK_FUNCTION_LIST *f; + CK_OBJECT_HANDLE obj; CK_ULONG tlen = 0; CK_RV rv; + CK_MECHANISM mech = { + CKM_RSA_PKCS, NULL_PTR, 0 + }; int rval = -1; - if ((k11 = RSA_get_ex_data(rsa, rsa_idx)) == NULL) { + UNUSED(padding); + + k11 = RSA_get_ex_data(rsa, ssh_pkcs11_rsa_ctx_index); + if (k11 == NULL) { error("RSA_get_ex_data failed"); return (-1); } - - if (pkcs11_get_key(k11, CKM_RSA_PKCS) == -1) { - error("pkcs11_get_key failed"); + if (!k11->provider || !k11->provider->valid) { + error_f("no pkcs11 (valid) provider"); return (-1); } - f = k11->provider->function_list; si = &k11->provider->slotinfo[k11->slotidx]; - tlen = RSA_size(rsa); - /* XXX handle CKR_BUFFER_TOO_SMALL */ - rv = f->C_Sign(si->session, (CK_BYTE *)from, flen, to, &tlen); - if (rv == CKR_OK) - rval = tlen; - else - error("C_Sign failed: %lu", rv); + if (!pkcs11_login(si, f)) return -1; + if (!pkcs11_get_key(k11, &obj)) return -1; + if ((rv = f->C_SignInit(si->session, &mech, obj)) != CKR_OK) { + PKCS11err(PKCS11_RSA_PRIVATE_ENCRYPT, PKCS11_C_SIGNINIT_FAIL); + crypto_pkcs11_error(rv); + } else { + (void)pkcs11_reauthenticate(si, f, obj); + /* XXX handle CKR_BUFFER_TOO_SMALL */ + tlen = RSA_size(rsa); + rv = f->C_Sign(si->session, (CK_BYTE *)from, flen, to, &tlen); + if (rv == CKR_OK) + rval = tlen; + else { + PKCS11err(PKCS11_RSA_PRIVATE_ENCRYPT, PKCS11_C_SIGN_FAIL); + crypto_pkcs11_error(rv); + } + } return (rval); } @@ -457,170 +563,256 @@ pkcs11_rsa_private_decrypt(int flen, const u_char *from, u_char *to, RSA *rsa, int padding) { + (void)flen; + (void)from; + (void)to; + (void)rsa; + (void)padding; return (-1); } -static int -pkcs11_rsa_start_wrapper(void) -{ - if (rsa_method != NULL) - return (0); - rsa_method = RSA_meth_dup(RSA_get_default_method()); - if (rsa_method == NULL) - return (-1); - rsa_idx = RSA_get_ex_new_index(0, "ssh-pkcs11-rsa", - NULL, NULL, pkcs11_k11_free); - if (rsa_idx == -1) - return (-1); - if (!RSA_meth_set1_name(rsa_method, "pkcs11") || - !RSA_meth_set_priv_enc(rsa_method, pkcs11_rsa_private_encrypt) || - !RSA_meth_set_priv_dec(rsa_method, pkcs11_rsa_private_decrypt)) { - error_f("setup pkcs11 method failed"); - return (-1); - } - return (0); +static RSA_METHOD* +ssh_pkcs11_rsa_method(void) { + static RSA_METHOD *meth = NULL; + + if (meth != NULL) return meth; + + meth = RSA_meth_new("SSH PKCS#11 RSA method", + #ifdef RSA_FLAG_FIPS_METHOD + RSA_FLAG_FIPS_METHOD | + #endif + 0); + if (meth == NULL) return NULL; + + if (!RSA_meth_set_priv_enc(meth, pkcs11_rsa_private_encrypt) + || !RSA_meth_set_priv_dec(meth, pkcs11_rsa_private_decrypt) + ) + goto err; + +{ const RSA_METHOD *def = RSA_PKCS1_OpenSSL(); + + if (!RSA_meth_set_pub_enc(meth, RSA_meth_get_pub_enc(def)) + || !RSA_meth_set_pub_dec(meth, RSA_meth_get_pub_dec(def)) + || !RSA_meth_set_mod_exp(meth, RSA_meth_get_mod_exp(def)) + || !RSA_meth_set_bn_mod_exp(meth, RSA_meth_get_bn_mod_exp(def)) + ) + goto err; +} + + /* ensure RSA context index */ + if (ssh_pkcs11_rsa_ctx_index < 0) + ssh_pkcs11_rsa_ctx_index = RSA_get_ex_new_index(0, + NULL, NULL, NULL, CRYPTO_EX_pkcs11_rsa_free); + if (ssh_pkcs11_rsa_ctx_index < 0) + goto err; + + return meth; + +err: + RSA_meth_free(meth); + meth = NULL; + return NULL; +} + +static inline int/*boolean*/ +set_ssh_pkcs11_rsa_method(RSA *key) { + RSA_METHOD *meth = ssh_pkcs11_rsa_method(); + if (meth == NULL) return 0;; + + return RSA_set_method(key, meth); } /* redirect private key operations for rsa key to pkcs11 token */ -static int -pkcs11_rsa_wrap(struct pkcs11_provider *provider, CK_ULONG slotidx, - CK_ATTRIBUTE *keyid_attrib, RSA *rsa) -{ - struct pkcs11_key *k11; - - if (pkcs11_rsa_start_wrapper() == -1) - return (-1); +static int/*boolean*/ +pkcs11_wrap_rsa(struct pkcs11_provider *provider, CK_ULONG slotidx, + CK_ATTRIBUTE *keyid_attrib, struct sshkey *key) +{ + RSA *rsa = EVP_PKEY_get1_RSA(key->pk); + if (rsa == NULL) return 0; + +{ struct pkcs11_key *k11; + /* fatal on error */ + k11 = pkcs11_key_create(provider, slotidx, keyid_attrib); + RSA_set_ex_data(rsa, ssh_pkcs11_rsa_ctx_index, k11); +} + key->flags |= SSHKEY_FLAG_EXT; + RSA_free(rsa); + return 1; +} - k11 = xcalloc(1, sizeof(*k11)); - k11->provider = provider; - provider->refcount++; /* provider referenced by RSA key */ - k11->slotidx = slotidx; - /* identify key object on smartcard */ - k11->keyid_len = keyid_attrib->ulValueLen; - if (k11->keyid_len > 0) { - k11->keyid = xmalloc(k11->keyid_len); - memcpy(k11->keyid, keyid_attrib->pValue, k11->keyid_len); - } - RSA_set_method(rsa, rsa_method); - RSA_set_ex_data(rsa, rsa_idx, k11); - return (0); +#ifdef OPENSSL_HAS_ECC +static ECDSA_SIG* +parse_ECDSA_SIG(char *buf, CK_ULONG blen) { + ECDSA_SIG *sig; + BIGNUM *ps, *pr; + int k = blen >> 1; + + pr = BN_bin2bn(buf , k, NULL); + ps = BN_bin2bn(buf + k, k, NULL); + if ((pr == NULL) || (ps == NULL)) goto parse_err; + + sig = ECDSA_SIG_new(); + if (sig == NULL) goto parse_err; + + if (ECDSA_SIG_set0(sig, pr, ps)) + return (sig); + +/*error*/ + ECDSA_SIG_free(sig); +parse_err: + BN_free(pr); + BN_free(ps); + return (NULL); } -#if defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW) -/* openssl callback doing the actual signing operation */ -static ECDSA_SIG * -ecdsa_do_sign(const unsigned char *dgst, int dgst_len, const BIGNUM *inv, - const BIGNUM *rp, EC_KEY *ec) -{ + +/* redirect private key operations for ec key to pkcs11 token */ +static ECDSA_SIG* +pkcs11_ecdsa_do_sign( + const unsigned char *dgst, int dlen, + const BIGNUM *inv, const BIGNUM *rp, + EC_KEY *ec +) { struct pkcs11_key *k11; struct pkcs11_slotinfo *si; CK_FUNCTION_LIST *f; - CK_ULONG siglen = 0, bnlen; + CK_OBJECT_HANDLE obj; + CK_ULONG tlen = 0; CK_RV rv; - ECDSA_SIG *ret = NULL; - u_char *sig; - BIGNUM *r = NULL, *s = NULL; - - if ((k11 = EC_KEY_get_ex_data(ec, ec_key_idx)) == NULL) { - ossl_error("EC_KEY_get_ex_data failed for ec"); - return (NULL); - } + CK_MECHANISM mech = { + CKM_ECDSA, NULL_PTR, 0 + }; + ECDSA_SIG *sig = NULL; - if (pkcs11_get_key(k11, CKM_ECDSA) == -1) { - error("pkcs11_get_key failed"); - return (NULL); - } + debug3_f("..."); + + UNUSED(inv); + UNUSED(rp); + k11 = EC_KEY_get_ex_data(ec, ssh_pkcs11_ec_ctx_index); + if (k11 == NULL) { + error("EC_KEY_get_ex_data failed"); + return NULL; + } + if (!k11->provider || !k11->provider->valid) { + error_f("no pkcs11 (valid) provider"); + return NULL; + } f = k11->provider->function_list; si = &k11->provider->slotinfo[k11->slotidx]; - siglen = ECDSA_size(ec); - sig = xmalloc(siglen); + if (!pkcs11_login(si, f)) return NULL; + if (!pkcs11_get_key(k11, &obj)) return NULL; - /* XXX handle CKR_BUFFER_TOO_SMALL */ - rv = f->C_Sign(si->session, (CK_BYTE *)dgst, dgst_len, sig, &siglen); - if (rv != CKR_OK) { - error("C_Sign failed: %lu", rv); - goto done; - } - if (siglen < 64 || siglen > 132 || siglen % 2) { - error_f("bad signature length: %lu", (u_long)siglen); - goto done; - } - bnlen = siglen/2; - if ((ret = ECDSA_SIG_new()) == NULL) { - error("ECDSA_SIG_new failed"); - goto done; - } - if ((r = BN_bin2bn(sig, bnlen, NULL)) == NULL || - (s = BN_bin2bn(sig+bnlen, bnlen, NULL)) == NULL) { - ossl_error("BN_bin2bn failed"); - ECDSA_SIG_free(ret); - ret = NULL; - goto done; + if ((rv = f->C_SignInit(si->session, &mech, obj)) != CKR_OK) { + PKCS11err(PKCS11_ECDSA_DO_SIGN, PKCS11_C_SIGNINIT_FAIL); + crypto_pkcs11_error(rv); + } else { + char rs[(1024>>2)/*> 2*[521/8]=2*66 */]; + (void)pkcs11_reauthenticate(si, f, obj); + tlen = sizeof(rs); + rv = f->C_Sign(si->session, (CK_BYTE *)dgst, dlen, rs, &tlen); + if (rv == CKR_OK) + sig = parse_ECDSA_SIG(rs, tlen); + else { + PKCS11err(PKCS11_ECDSA_DO_SIGN, PKCS11_C_SIGN_FAIL); + crypto_pkcs11_error(rv); + } } - if (!ECDSA_SIG_set0(ret, r, s)) { - error_f("ECDSA_SIG_set0 failed"); - ECDSA_SIG_free(ret); - ret = NULL; - goto done; + return (sig); +} + + +#ifdef HAVE_EC_KEY_METHOD_NEW +static int +pkcs11_ecdsa_sign(int type, + const unsigned char *dgst, int dlen, + unsigned char *sig, unsigned int *siglen, + const BIGNUM *inv, const BIGNUM *rp, + EC_KEY *ec +) { + ECDSA_SIG *s; + + debug3_f("..."); + (void)type; + + s = pkcs11_ecdsa_do_sign(dgst, dlen, inv, rp, ec); + if (s == NULL) { + *siglen = 0; + return (0); } - r = s = NULL; /* now owned by ret */ - /* success */ - done: - BN_free(r); - BN_free(s); - free(sig); - return (ret); + *siglen = i2d_ECDSA_SIG(s, &sig); + + ECDSA_SIG_free(s); + return (1); } +#endif /*def HAVE_EC_KEY_METHOD_NEW*/ -static int -pkcs11_ecdsa_start_wrapper(void) -{ - int (*orig_sign)(int, const unsigned char *, int, unsigned char *, - unsigned int *, const BIGNUM *, const BIGNUM *, EC_KEY *) = NULL; - if (ec_key_method != NULL) - return (0); - ec_key_idx = EC_KEY_get_ex_new_index(0, "ssh-pkcs11-ecdsa", - NULL, NULL, pkcs11_k11_free); - if (ec_key_idx == -1) - return (-1); - ec_key_method = EC_KEY_METHOD_new(EC_KEY_OpenSSL()); - if (ec_key_method == NULL) - return (-1); - EC_KEY_METHOD_get_sign(ec_key_method, &orig_sign, NULL, NULL); - EC_KEY_METHOD_set_sign(ec_key_method, orig_sign, NULL, ecdsa_do_sign); - return (0); +static EC_KEY_METHOD* +ssh_pkcs11_ec_method(void) { + static EC_KEY_METHOD *meth = NULL; + + if (meth != NULL) return meth; + + meth = EC_KEY_METHOD_new(EC_KEY_OpenSSL()); + if (meth == NULL) return NULL; + +#ifndef HAVE_EC_KEY_METHOD_NEW /* OpenSSL < 1.1 */ + ECDSA_METHOD_set_sign(meth, + pkcs11_ecdsa_do_sign + ); +#else + EC_KEY_METHOD_set_sign(meth, + pkcs11_ecdsa_sign, + NULL /* *sign_setup */, + pkcs11_ecdsa_do_sign + ); +#endif + + /* ensure EC context index */ + if (ssh_pkcs11_ec_ctx_index < 0) + ssh_pkcs11_ec_ctx_index = EC_KEY_get_ex_new_index(0, + NULL, NULL, NULL, CRYPTO_EX_pkcs11_ec_free); + if (ssh_pkcs11_ec_ctx_index < 0) + goto err; + + return meth; + +err: + EC_KEY_METHOD_free(meth); + meth = NULL; + return NULL; } -static int -pkcs11_ecdsa_wrap(struct pkcs11_provider *provider, CK_ULONG slotidx, - CK_ATTRIBUTE *keyid_attrib, EC_KEY *ec) -{ - struct pkcs11_key *k11; +static inline int/*boolean*/ +set_ssh_pkcs11_ec_method(EC_KEY *key) { + EC_KEY_METHOD *meth = ssh_pkcs11_ec_method(); + if (meth == NULL) return 0; - if (pkcs11_ecdsa_start_wrapper() == -1) - return (-1); + return EC_KEY_set_method(key, meth); +} - k11 = xcalloc(1, sizeof(*k11)); - k11->provider = provider; - provider->refcount++; /* provider referenced by ECDSA key */ - k11->slotidx = slotidx; - /* identify key object on smartcard */ - k11->keyid_len = keyid_attrib->ulValueLen; - if (k11->keyid_len > 0) { - k11->keyid = xmalloc(k11->keyid_len); - memcpy(k11->keyid, keyid_attrib->pValue, k11->keyid_len); - } - EC_KEY_set_method(ec, ec_key_method); - EC_KEY_set_ex_data(ec, ec_key_idx, k11); +static int/*boolean*/ +pkcs11_wrap_ec(struct pkcs11_provider *provider, CK_ULONG slotidx, + CK_ATTRIBUTE *keyid_attrib, struct sshkey *key) +{ + EC_KEY *ec = EVP_PKEY_get1_EC_KEY(key->pk); + if (ec == NULL) return 0; - return (0); +{ struct pkcs11_key *k11; + /* fatal on error */ + k11 = pkcs11_key_create(provider, slotidx, keyid_attrib); + EC_KEY_set_ex_data(ec, ssh_pkcs11_ec_ctx_index, k11); } -#endif /* OPENSSL_HAS_ECC && HAVE_EC_KEY_METHOD_NEW */ + key->flags |= SSHKEY_FLAG_EXT; + EC_KEY_free(ec); + return 1; +} +#endif /*def OPENSSL_HAS_ECC*/ + /* remove trailing spaces */ static char * @@ -646,562 +838,605 @@ */ static int pkcs11_open_session(struct pkcs11_provider *p, CK_ULONG slotidx, char *pin, - CK_ULONG user) + CK_USER_TYPE user_type) { - struct pkcs11_slotinfo *si; - CK_FUNCTION_LIST *f; CK_RV rv; + struct pkcs11_slotinfo *si = &p->slotinfo[slotidx]; + CK_FUNCTION_LIST *f = p->function_list; CK_SESSION_HANDLE session; int login_required, ret; - f = p->function_list; - si = &p->slotinfo[slotidx]; - login_required = si->token.flags & CKF_LOGIN_REQUIRED; - - /* fail early before opening session */ - if (login_required && !pkcs11_interactive && - (pin == NULL || strlen(pin) == 0)) { + if (login_required && pin != NULL && strlen(pin) == 0) { error("pin required"); - return (-SSH_PKCS11_ERR_PIN_REQUIRED); + return SSH_PKCS11_ERR_PIN_REQUIRED; } if ((rv = f->C_OpenSession(p->slotlist[slotidx], CKF_RW_SESSION| CKF_SERIAL_SESSION, NULL, NULL, &session)) != CKR_OK) { error("C_OpenSession failed: %lu", rv); - return (-1); + return SSH_PKCS11_ERR_GENERIC; } - if (login_required && pin != NULL && strlen(pin) != 0) { - rv = f->C_Login(session, user, (u_char *)pin, strlen(pin)); + if (login_required && pin != NULL) { + rv = f->C_Login(session, user_type, + (u_char *)pin, strlen(pin)); if (rv != CKR_OK && rv != CKR_USER_ALREADY_LOGGED_IN) { error("C_Login failed: %lu", rv); ret = (rv == CKR_PIN_LOCKED) ? - -SSH_PKCS11_ERR_PIN_LOCKED : - -SSH_PKCS11_ERR_LOGIN_FAIL; + SSH_PKCS11_ERR_PIN_LOCKED : + SSH_PKCS11_ERR_LOGIN_FAIL; if ((rv = f->C_CloseSession(session)) != CKR_OK) error("C_CloseSession failed: %lu", rv); - return (ret); + return ret; } si->logged_in = 1; } si->session = session; - return (0); + return 0; } -static int -pkcs11_key_included(struct sshkey ***keysp, int *nkeys, struct sshkey *key) -{ - int i; +static inline int/*boolean*/ +pkcs11_wrap(struct pkcs11_provider *provider, CK_ULONG slotidx, + CK_ATTRIBUTE *keyid_attrib, struct sshkey *key +) { + switch(key->type) { + case KEY_RSA: + return pkcs11_wrap_rsa(provider, slotidx, keyid_attrib, key); +#ifdef OPENSSL_HAS_ECC + case KEY_ECDSA: + return pkcs11_wrap_ec(provider, slotidx, keyid_attrib, key); +#endif /*def OPENSSL_HAS_ECC*/ + } + return 0; +} - for (i = 0; i < *nkeys; i++) - if (sshkey_equal(key, (*keysp)[i])) - return (1); - return (0); +static inline int/*boolean*/ +set_ssh_pkcs11_pkey_rsa_method(EVP_PKEY *pk) { + int ret; + RSA *rsa; + + rsa = EVP_PKEY_get1_RSA(pk); + if (rsa == NULL) return 0; + + ret = set_ssh_pkcs11_rsa_method(rsa); +#ifdef HAVE_EVP_KEYMGMT_GET0_PROVIDER /* OpenSSL 3+ */ + /* Implicitly throw out "key manager" in OpenSSL 3+, + * i.e. make non-provider key. + */ + if (ret) ret = EVP_PKEY_set1_RSA(pk, rsa); +#endif + RSA_free(rsa); + return ret; +} + +#ifdef OPENSSL_HAS_ECC +static inline int/*boolean*/ +set_ssh_pkcs11_pkey_ec_method(EVP_PKEY *pk) { + int ret; + EC_KEY *ec; + + ec = EVP_PKEY_get1_EC_KEY(pk); + if (ec == NULL) return 0; + + ret = set_ssh_pkcs11_ec_method(ec); +#ifdef HAVE_EVP_KEYMGMT_GET0_PROVIDER /* OpenSSL 3+ */ + /* Implicitly throw out "key manager" in OpenSSL 3+, + * i.e. make non-provider key. + */ + if (ret) ret = EVP_PKEY_set1_EC_KEY(pk, ec); +#endif + EC_KEY_free(ec); + return ret; } +#endif /*def OPENSSL_HAS_ECC*/ -#if defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW) -static struct sshkey * -pkcs11_fetch_ecdsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, - CK_OBJECT_HANDLE *obj) -{ - CK_ATTRIBUTE key_attr[3]; - CK_SESSION_HANDLE session; - CK_FUNCTION_LIST *f = NULL; - CK_RV rv; - ASN1_OCTET_STRING *octet = NULL; - EC_KEY *ec = NULL; - EC_GROUP *group = NULL; - struct sshkey *key = NULL; - const unsigned char *attrp = NULL; - int i; - int nid; - - memset(&key_attr, 0, sizeof(key_attr)); - key_attr[0].type = CKA_ID; - key_attr[1].type = CKA_EC_POINT; - key_attr[2].type = CKA_EC_PARAMS; +static inline int/*boolean*/ +set_ssh_pkcs11_pkey_method(EVP_PKEY *pk) { + switch(EVP_PKEY_base_id(pk)) { + case EVP_PKEY_RSA: + return set_ssh_pkcs11_pkey_rsa_method(pk); +#ifdef OPENSSL_HAS_ECC + case EVP_PKEY_EC: + return set_ssh_pkcs11_pkey_ec_method(pk); +#endif + } + return 0; +} - session = p->slotinfo[slotidx].session; - f = p->function_list; +static struct sshkey* +pkcs11_get_x509key( + struct pkcs11_provider *p, CK_ULONG slotidx, + CK_OBJECT_HANDLE obj +) { + CK_FUNCTION_LIST *f = p->function_list; + CK_SESSION_HANDLE session = p->slotinfo[slotidx].session; + CK_RV rv; + /* NOTE: for certificate retrieve ID, Subject(*) and Value + * (*) not used yet + */ + CK_ATTRIBUTE attribs[] = { + { CKA_ID, NULL, 0 }, + { CKA_SUBJECT, NULL, 0 }, + { CKA_VALUE, NULL, 0 } + }; + X509 *x; + struct sshkey *key = NULL; + int i; - /* figure out size of the attributes */ - rv = f->C_GetAttributeValue(session, *obj, key_attr, 3); + rv = f->C_GetAttributeValue(session, obj, attribs, 3); if (rv != CKR_OK) { - error("C_GetAttributeValue failed: %lu", rv); - return (NULL); + error_f("C_GetAttributeValue failed: %lu", rv); + return NULL; } - /* * Allow CKA_ID (always first attribute) to be empty, but * ensure that none of the others are zero length. - * XXX assumes CKA_ID is always first. */ - if (key_attr[1].ulValueLen == 0 || - key_attr[2].ulValueLen == 0) { - error("invalid attribute length"); - return (NULL); - } + if (attribs[1].ulValueLen == 0 || + attribs[2].ulValueLen == 0) + return NULL; /* allocate buffers for attributes */ - for (i = 0; i < 3; i++) - if (key_attr[i].ulValueLen > 0) - key_attr[i].pValue = xcalloc(1, key_attr[i].ulValueLen); + for (i = 0; i < 3; i++) { + if (attribs[i].ulValueLen == 0) continue; + attribs[i].pValue = xmalloc(attribs[i].ulValueLen); + } - /* retrieve ID, public point and curve parameters of EC key */ - rv = f->C_GetAttributeValue(session, *obj, key_attr, 3); + /* retrieve ID, subject and value for certificate */ + rv = f->C_GetAttributeValue(session, obj, attribs, 3); if (rv != CKR_OK) { - error("C_GetAttributeValue failed: %lu", rv); + error_f("C_GetAttributeValue failed: %lu", rv); goto fail; } - ec = EC_KEY_new(); - if (ec == NULL) { - error("EC_KEY_new failed"); +{ const u_char *blob = attribs[2].pValue; + size_t blen = attribs[2].ulValueLen; + + if (attribs[2].ulValueLen != (unsigned long) blen) { + debug3_f("invalid attribute length"); goto fail; } - attrp = key_attr[2].pValue; - group = d2i_ECPKParameters(NULL, &attrp, key_attr[2].ulValueLen); - if (group == NULL) { - ossl_error("d2i_ECPKParameters failed"); + if (X509_from_blob(blob, blen, &x) != 0) { + debug3_f("X509_from_blob fail"); goto fail; } +} - if (EC_KEY_set_group(ec, group) == 0) { - ossl_error("EC_KEY_set_group failed"); +{ EVP_PKEY *pk = X509_get_pubkey(x); + if (pk == NULL) { + debug3_f("X509_get_pubkey fail"); + X509_free(x); goto fail; } - - if (key_attr[1].ulValueLen <= 2) { - error("CKA_EC_POINT too small"); + if (!set_ssh_pkcs11_pkey_method(pk)) { + debug3_f("set_ssh_pkcs11_pkey_method fail"); + X509_free(x); + EVP_PKEY_free(pk); goto fail; } + EVP_PKEY_free(pk); +} - attrp = key_attr[1].pValue; - octet = d2i_ASN1_OCTET_STRING(NULL, &attrp, key_attr[1].ulValueLen); - if (octet == NULL) { - ossl_error("d2i_ASN1_OCTET_STRING failed"); - goto fail; + key = x509_to_key(x); + if (key == NULL) goto fail; + + if (pkcs11_wrap(p, slotidx, attribs, key)) + goto done; + +fail: + sshkey_free(key); + key = NULL; + +done: + for (i = 0; i < 3; i++) + free(attribs[i].pValue); + + return key; +} + +static void +note_key(struct pkcs11_provider *p, CK_ULONG slotidx, + struct sshkey *key) +{ + char *fp; + + if (key == NULL) return; + + fp = sshkey_fingerprint(key, SSH_FP_HASH_DEFAULT, SSH_FP_DEFAULT); + if (fp == NULL) { + error_f("sshkey_fingerprint failed"); + return; } - attrp = octet->data; - if (o2i_ECPublicKey(&ec, &attrp, octet->length) == NULL) { - ossl_error("o2i_ECPublicKey failed"); - goto fail; + debug2("provider %s slot %lu: %s %s", p->name, + (unsigned long)slotidx, sshkey_type(key), fp); + free(fp); +} + +static void +pkcs11_push_key(struct sshkey *key, char *label, + struct sshkey ***keysp, char ***labelsp, int *nkeys) +{ + if (key == NULL) return; + +{ struct sshkey **sp = *keysp; + int i; + for (i = 0; i < *nkeys; i++, sp++) + if (sshkey_equal_public(key, *sp)) { + debug("exist equal key, ignoring '%s'", label); + sshkey_free(key); + free(label); + return; + } +} + + /* expand key array and add key */ + *keysp = xreallocarray(*keysp, *nkeys + 1, sizeof(struct sshkey *)); + (*keysp)[*nkeys] = key; + + if (labelsp != NULL) { + *labelsp = xreallocarray(*labelsp, *nkeys + 1, sizeof(char *)); + (*labelsp)[*nkeys] = label; } - nid = sshkey_ecdsa_key_to_nid(ec); - if (nid < 0) { - error("couldn't get curve nid"); - goto fail; + *nkeys = *nkeys + 1; + debug("push key #%d '%s'", *nkeys, label); + if (labelsp == NULL) + free(label); +} + +/* + * lookup certificates for token in slot identified by slotidx, + * add 'wrapped' public keys to the 'keysp' array and increment nkeys. + * keysp points to an (possibly empty) array with *nkeys keys. + */ +static int +pkcs11_fetch_certs(struct pkcs11_provider *p, CK_ULONG slotidx, + struct sshkey ***keysp, char ***labelsp, int *nkeys) +{ + CK_FUNCTION_LIST *f = p->function_list; + CK_SESSION_HANDLE session = p->slotinfo[slotidx].session; + CK_RV rv; + +{ /* setup a filter that looks for certificates */ + /* Find objects with cert class and X.509 cert type. */ + CK_OBJECT_CLASS cert_class = CKO_CERTIFICATE; + CK_CERTIFICATE_TYPE type = CKC_X_509; + CK_ATTRIBUTE filter[] = { + { CKA_CLASS, NULL, sizeof(cert_class) } + , { CKA_CERTIFICATE_TYPE, NULL, sizeof(type) } + }; + /* some compilers complain about non-constant initializer so we + use NULL in CK_ATTRIBUTE above and set the value here */ + filter[0].pValue = &cert_class; + filter[1].pValue = &type; + + rv = f->C_FindObjectsInit(session, filter, 2); + if (rv != CKR_OK) { + error_f("C_FindObjectsInit failed: %lu", rv); + return -1; } +} - if (pkcs11_ecdsa_wrap(p, slotidx, &key_attr[0], ec)) - goto fail; + while (1) { + CK_OBJECT_HANDLE obj; + CK_ULONG nfound; + struct sshkey *key; + char *label = NULL; - key = sshkey_new(KEY_UNSPEC); - if (key == NULL) { - error("sshkey_new failed"); - goto fail; + rv = f->C_FindObjects(session, &obj, 1, &nfound); + if (rv != CKR_OK) { + error_f("C_FindObjects failed: %lu", rv); + break; + } + if (nfound == 0) + break; + + key = pkcs11_get_x509key(p, slotidx, obj); + if (key == NULL) { + error_f("pkcs11_get_x509key failed"); + continue; + } + label = x509key_subject(key); + note_key(p, slotidx, key); + pkcs11_push_key(key, label, keysp, labelsp, nkeys); } - key->ecdsa = ec; - key->ecdsa_nid = nid; - key->type = KEY_ECDSA; - key->flags |= SSHKEY_FLAG_EXT; - ec = NULL; /* now owned by key */ + rv = f->C_FindObjectsFinal(session); + if (rv != CKR_OK) + error_f("C_FindObjectsFinal failed: %lu", rv); -fail: - for (i = 0; i < 3; i++) - free(key_attr[i].pValue); - if (ec) - EC_KEY_free(ec); - if (group) - EC_GROUP_free(group); - if (octet) - ASN1_OCTET_STRING_free(octet); - - return (key); -} -#endif /* OPENSSL_HAS_ECC && HAVE_EC_KEY_METHOD_NEW */ - -static struct sshkey * -pkcs11_fetch_rsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, - CK_OBJECT_HANDLE *obj) -{ - CK_ATTRIBUTE key_attr[3]; - CK_SESSION_HANDLE session; - CK_FUNCTION_LIST *f = NULL; - CK_RV rv; - RSA *rsa = NULL; - BIGNUM *rsa_n, *rsa_e; - struct sshkey *key = NULL; - int i; - - memset(&key_attr, 0, sizeof(key_attr)); - key_attr[0].type = CKA_ID; - key_attr[1].type = CKA_MODULUS; - key_attr[2].type = CKA_PUBLIC_EXPONENT; + return 0; +} - session = p->slotinfo[slotidx].session; - f = p->function_list; +static struct sshkey* +pkcs11_get_pubkey_rsa( + struct pkcs11_provider *p, CK_ULONG slotidx, + CK_OBJECT_HANDLE obj) +{ + CK_FUNCTION_LIST *f = p->function_list; + CK_SESSION_HANDLE session = p->slotinfo[slotidx].session; + CK_RV rv; + /* NOTE: for RSA public key retrieve ID, + * modulus "m" and public exponent "e" + */ + CK_ATTRIBUTE attribs[3] = { + { CKA_ID, NULL, 0 }, + { CKA_MODULUS, NULL, 0 }, + { CKA_PUBLIC_EXPONENT, NULL, 0 } + }; + struct sshkey *key = NULL; + int i; - /* figure out size of the attributes */ - rv = f->C_GetAttributeValue(session, *obj, key_attr, 3); + rv = f->C_GetAttributeValue(session, obj, attribs, 3); if (rv != CKR_OK) { - error("C_GetAttributeValue failed: %lu", rv); - return (NULL); + error_f("C_GetAttributeValue failed: %lu", rv); + return NULL; } - /* * Allow CKA_ID (always first attribute) to be empty, but * ensure that none of the others are zero length. - * XXX assumes CKA_ID is always first. */ - if (key_attr[1].ulValueLen == 0 || - key_attr[2].ulValueLen == 0) { - error("invalid attribute length"); - return (NULL); - } + if (attribs[1].ulValueLen == 0 || + attribs[2].ulValueLen == 0) + return NULL; /* allocate buffers for attributes */ - for (i = 0; i < 3; i++) - if (key_attr[i].ulValueLen > 0) - key_attr[i].pValue = xcalloc(1, key_attr[i].ulValueLen); + for (i = 0; i < 3; i++) { + if (attribs[i].ulValueLen == 0) continue; + attribs[i].pValue = xmalloc(attribs[i].ulValueLen); + } /* retrieve ID, modulus and public exponent of RSA key */ - rv = f->C_GetAttributeValue(session, *obj, key_attr, 3); + rv = f->C_GetAttributeValue(session, obj, attribs, 3); if (rv != CKR_OK) { - error("C_GetAttributeValue failed: %lu", rv); - goto fail; + error_f("C_GetAttributeValue failed: %lu", rv); + goto done; } + key = sshkey_new(KEY_UNSPEC); + if (key == NULL) { + error_f("sshkey_new failed"); + goto done; + } + key->type = KEY_RSA; + key->pk = EVP_PKEY_new(); + if (key->pk == NULL) + goto fail; + +{ BIGNUM *rsa_n = NULL, *rsa_e = NULL; + RSA *rsa; + rsa = RSA_new(); if (rsa == NULL) { - error("RSA_new failed"); + error_f("RSA_new failed"); + goto fail; + } + if (!set_ssh_pkcs11_rsa_method(rsa)) { + RSA_free(rsa); goto fail; } - rsa_n = BN_bin2bn(key_attr[1].pValue, key_attr[1].ulValueLen, NULL); - rsa_e = BN_bin2bn(key_attr[2].pValue, key_attr[2].ulValueLen, NULL); + rsa_n = BN_bin2bn(attribs[1].pValue, attribs[1].ulValueLen, NULL); + rsa_e = BN_bin2bn(attribs[2].pValue, attribs[2].ulValueLen, NULL); if (rsa_n == NULL || rsa_e == NULL) { - error("BN_bin2bn failed"); - goto fail; + error_f("BN_bin2bn failed"); + goto key_fail; } - if (!RSA_set0_key(rsa, rsa_n, rsa_e, NULL)) - fatal_f("set key"); - rsa_n = rsa_e = NULL; /* transferred */ - if (pkcs11_rsa_wrap(p, slotidx, &key_attr[0], rsa)) - goto fail; + if (!RSA_set0_key(rsa, rsa_n, rsa_e, NULL)) { + RSA_free(rsa); + goto key_fail; + } - key = sshkey_new(KEY_UNSPEC); - if (key == NULL) { - error("sshkey_new failed"); + if (!EVP_PKEY_set1_RSA(key->pk, rsa)) { + RSA_free(rsa); goto fail; } + RSA_free(rsa); + goto key_done; - key->rsa = rsa; - key->type = KEY_RSA; - key->flags |= SSHKEY_FLAG_EXT; - rsa = NULL; /* now owned by key */ +key_fail: + BN_free(rsa_n); + BN_free(rsa_e); + goto fail; +} +key_done: + + if (pkcs11_wrap_rsa(p, slotidx, attribs, key)) + goto done; fail: + sshkey_free(key); + key = NULL; + +done: for (i = 0; i < 3; i++) - free(key_attr[i].pValue); - RSA_free(rsa); + free(attribs[i].pValue); - return (key); + return key; } -static int -pkcs11_fetch_x509_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, - CK_OBJECT_HANDLE *obj, struct sshkey **keyp, char **labelp) -{ - CK_ATTRIBUTE cert_attr[3]; - CK_SESSION_HANDLE session; - CK_FUNCTION_LIST *f = NULL; - CK_RV rv; - X509 *x509 = NULL; - X509_NAME *x509_name = NULL; - EVP_PKEY *evp; - RSA *rsa = NULL; #ifdef OPENSSL_HAS_ECC - EC_KEY *ec = NULL; -#endif - struct sshkey *key = NULL; - int i; -#if defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW) - int nid; -#endif - const u_char *cp; - char *subject = NULL; - - *keyp = NULL; - *labelp = NULL; - - memset(&cert_attr, 0, sizeof(cert_attr)); - cert_attr[0].type = CKA_ID; - cert_attr[1].type = CKA_SUBJECT; - cert_attr[2].type = CKA_VALUE; - - session = p->slotinfo[slotidx].session; - f = p->function_list; +static struct sshkey* +pkcs11_get_pubkey_ec( + struct pkcs11_provider *p, CK_ULONG slotidx, + CK_OBJECT_HANDLE obj +) { + CK_FUNCTION_LIST *f = p->function_list; + CK_SESSION_HANDLE session = p->slotinfo[slotidx].session; + CK_RV rv; + /* NOTE: for EC public key retrieve ID, + * point "q" and curve parameters + */ + CK_ATTRIBUTE attribs[3] = { + { CKA_ID, NULL, 0 }, + { CKA_EC_PARAMS, NULL, 0 }, + { CKA_EC_POINT, NULL, 0 } + }; + struct sshkey *key = NULL; + int i; - /* figure out size of the attributes */ - rv = f->C_GetAttributeValue(session, *obj, cert_attr, 3); + rv = f->C_GetAttributeValue(session, obj, attribs, 3); if (rv != CKR_OK) { - error("C_GetAttributeValue failed: %lu", rv); - return -1; + error_f("C_GetAttributeValue failed: %lu", rv); + return NULL; } - /* * Allow CKA_ID (always first attribute) to be empty, but * ensure that none of the others are zero length. - * XXX assumes CKA_ID is always first. */ - if (cert_attr[1].ulValueLen == 0 || - cert_attr[2].ulValueLen == 0) { - error("invalid attribute length"); - return -1; - } + if (attribs[1].ulValueLen == 0 || + attribs[2].ulValueLen == 0) + return NULL; /* allocate buffers for attributes */ - for (i = 0; i < 3; i++) - if (cert_attr[i].ulValueLen > 0) - cert_attr[i].pValue = xcalloc(1, cert_attr[i].ulValueLen); + for (i = 0; i < 3; i++) { + if (attribs[i].ulValueLen == 0) continue; + attribs[i].pValue = xmalloc(attribs[i].ulValueLen); + } - /* retrieve ID, subject and value of certificate */ - rv = f->C_GetAttributeValue(session, *obj, cert_attr, 3); + /* retrieve ID, point and curve parameters of EC key */ + rv = f->C_GetAttributeValue(session, obj, attribs, 3); if (rv != CKR_OK) { - error("C_GetAttributeValue failed: %lu", rv); - goto out; + error_f("C_GetAttributeValue failed: %lu", rv); + goto done; } - /* Decode DER-encoded cert subject */ - cp = cert_attr[1].pValue; - if ((x509_name = d2i_X509_NAME(NULL, &cp, - cert_attr[1].ulValueLen)) == NULL || - (subject = X509_NAME_oneline(x509_name, NULL, 0)) == NULL) - subject = xstrdup("invalid subject"); - X509_NAME_free(x509_name); - - cp = cert_attr[2].pValue; - if ((x509 = d2i_X509(NULL, &cp, cert_attr[2].ulValueLen)) == NULL) { - error("d2i_x509 failed"); - goto out; + key = sshkey_new(KEY_UNSPEC); + if (key == NULL) { + error_f("sshkey_new failed"); + goto done; } - - if ((evp = X509_get_pubkey(x509)) == NULL) { - error("X509_get_pubkey failed"); - goto out; + key->type = KEY_ECDSA; + key->pk = EVP_PKEY_new(); + if (key->pk == NULL) { + error_f("EVP_PKEY_new failed"); + goto fail; } - if (EVP_PKEY_base_id(evp) == EVP_PKEY_RSA) { - if (EVP_PKEY_get0_RSA(evp) == NULL) { - error("invalid x509; no rsa key"); - goto out; - } - if ((rsa = RSAPublicKey_dup(EVP_PKEY_get0_RSA(evp))) == NULL) { - error("RSAPublicKey_dup failed"); - goto out; - } - - if (pkcs11_rsa_wrap(p, slotidx, &cert_attr[0], rsa)) - goto out; +{ const unsigned char *q; + EC_KEY *ec; + /* DER-encoding of an ANSI X9.62 Parameters value */ - key = sshkey_new(KEY_UNSPEC); - if (key == NULL) { - error("sshkey_new failed"); - goto out; - } + q = attribs[1].pValue; + ec = d2i_ECParameters(NULL, &q, attribs[1].ulValueLen); + if (ec == NULL) { + error_f("d2i_ECParameters failed"); + goto fail; + } + if (!set_ssh_pkcs11_ec_method(ec)) { + EC_KEY_free(ec); + goto fail; + } + key->ecdsa_nid = ssh_EC_KEY_preserve_nid(ec); + if (key->ecdsa_nid < 0) { + error_f("unsupported elliptic curve"); + EC_KEY_free(ec); + goto fail; + } + if (!EVP_PKEY_set1_EC_KEY(key->pk, ec)) { + EC_KEY_free(ec); + goto fail; + } + EC_KEY_free(ec); +} +{ const unsigned char *q; + /* "DER-encoding of ANSI X9.62 ECPoint value Q" */ + EC_KEY *ec, *pk_ec; - key->rsa = rsa; - key->type = KEY_RSA; - key->flags |= SSHKEY_FLAG_EXT; - rsa = NULL; /* now owned by key */ -#if defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW) - } else if (EVP_PKEY_base_id(evp) == EVP_PKEY_EC) { - if (EVP_PKEY_get0_EC_KEY(evp) == NULL) { - error("invalid x509; no ec key"); - goto out; - } - if ((ec = EC_KEY_dup(EVP_PKEY_get0_EC_KEY(evp))) == NULL) { - error("EC_KEY_dup failed"); - goto out; - } + pk_ec = EVP_PKEY_get1_EC_KEY(key->pk); + if (pk_ec == NULL) goto fail; - nid = sshkey_ecdsa_key_to_nid(ec); - if (nid < 0) { - error("couldn't get curve nid"); - goto out; - } + q = attribs[2].pValue; +{ ASN1_OCTET_STRING *point; - if (pkcs11_ecdsa_wrap(p, slotidx, &cert_attr[0], ec)) - goto out; + point = d2i_ASN1_OCTET_STRING(NULL, &q, attribs[2].ulValueLen); + if (point == NULL) { + error_f("d2i_ASN1_OCTET_STRING failed"); + goto try_raw_ec_point; + } - key = sshkey_new(KEY_UNSPEC); - if (key == NULL) { - error("sshkey_new failed"); - goto out; - } + q = point->data; + ec = o2i_ECPublicKey(&pk_ec, &q, point->length); + if (ec == NULL) + error_f("o2i_ECPublicKey failed for EC point"); - key->ecdsa = ec; - key->ecdsa_nid = nid; - key->type = KEY_ECDSA; - key->flags |= SSHKEY_FLAG_EXT; - ec = NULL; /* now owned by key */ -#endif /* OPENSSL_HAS_ECC && HAVE_EC_KEY_METHOD_NEW */ - } else { - error("unknown certificate key type"); - goto out; - } - out: - for (i = 0; i < 3; i++) - free(cert_attr[i].pValue); - X509_free(x509); - RSA_free(rsa); -#ifdef OPENSSL_HAS_ECC - EC_KEY_free(ec); -#endif - if (key == NULL) { - free(subject); - return -1; - } - /* success */ - *keyp = key; - *labelp = subject; - return 0; + ASN1_STRING_free(point); + if (ec != NULL) goto done_ecpub; } -#if 0 -static int -have_rsa_key(const RSA *rsa) -{ - const BIGNUM *rsa_n, *rsa_e; +try_raw_ec_point: + /* try raw data (broken PKCS#11 module) */ + q = attribs[2].pValue; + ec = o2i_ECPublicKey(&pk_ec, &q, attribs[2].ulValueLen); + if (ec == NULL) + error_f("o2i_ECPublicKey failed for raw EC point too"); - RSA_get0_key(rsa, &rsa_n, &rsa_e, NULL); - return rsa_n != NULL && rsa_e != NULL; +done_ecpub: + EC_KEY_free(pk_ec); + if (ec == NULL) goto fail; } -#endif + if (pkcs11_wrap_ec(p, slotidx, attribs, key)) + goto done; -static void -note_key(struct pkcs11_provider *p, CK_ULONG slotidx, const char *context, - struct sshkey *key) -{ - char *fp; +fail: + sshkey_free(key); + key = NULL; - if ((fp = sshkey_fingerprint(key, SSH_FP_HASH_DEFAULT, - SSH_FP_DEFAULT)) == NULL) { - error_f("sshkey_fingerprint failed"); - return; - } - debug2("%s: provider %s slot %lu: %s %s", context, p->name, - (u_long)slotidx, sshkey_type(key), fp); - free(fp); +done: + for (i = 0; i < 3; i++) + free(attribs[i].pValue); + + return key; } +#endif /* OPENSSL_HAS_ECC */ -/* - * lookup certificates for token in slot identified by slotidx, - * add 'wrapped' public keys to the 'keysp' array and increment nkeys. - * keysp points to an (possibly empty) array with *nkeys keys. - */ -static int -pkcs11_fetch_certs(struct pkcs11_provider *p, CK_ULONG slotidx, - struct sshkey ***keysp, char ***labelsp, int *nkeys) +static struct sshkey* +pkcs11_get_pubkey( + struct pkcs11_provider *p, CK_ULONG slotidx, + CK_OBJECT_HANDLE obj, char **labelp) { - struct sshkey *key = NULL; - CK_OBJECT_CLASS key_class; - CK_ATTRIBUTE key_attr[1]; - CK_SESSION_HANDLE session; - CK_FUNCTION_LIST *f = NULL; - CK_RV rv; - CK_OBJECT_HANDLE obj; - CK_ULONG n = 0; - int ret = -1; - char *label; - - memset(&key_attr, 0, sizeof(key_attr)); - memset(&obj, 0, sizeof(obj)); - - key_class = CKO_CERTIFICATE; - key_attr[0].type = CKA_CLASS; - key_attr[0].pValue = &key_class; - key_attr[0].ulValueLen = sizeof(key_class); + CK_FUNCTION_LIST *f = p->function_list; + CK_SESSION_HANDLE session = p->slotinfo[slotidx].session; + CK_RV rv; + CK_KEY_TYPE type; + CK_UTF8CHAR label[4096]; + CK_ATTRIBUTE attribs[] = { + { CKA_KEY_TYPE, NULL, sizeof(type) }, + { CKA_LABEL, NULL, sizeof(label) } + }; - session = p->slotinfo[slotidx].session; - f = p->function_list; + /* some compilers complain about non-constant initializer so we + use NULL in CK_ATTRIBUTE above and set the value here */ + attribs[0].pValue = &type; + attribs[1].pValue = &label; - rv = f->C_FindObjectsInit(session, key_attr, 1); + rv = f->C_GetAttributeValue(session, obj, attribs, 2); if (rv != CKR_OK) { - error("C_FindObjectsInit failed: %lu", rv); - goto fail; + error_f("C_GetAttributeValue failed: %lu", rv); + return NULL; } - while (1) { - CK_CERTIFICATE_TYPE ck_cert_type; - - rv = f->C_FindObjects(session, &obj, 1, &n); - if (rv != CKR_OK) { - error("C_FindObjects failed: %lu", rv); - goto fail; - } - if (n == 0) - break; - - memset(&ck_cert_type, 0, sizeof(ck_cert_type)); - memset(&key_attr, 0, sizeof(key_attr)); - key_attr[0].type = CKA_CERTIFICATE_TYPE; - key_attr[0].pValue = &ck_cert_type; - key_attr[0].ulValueLen = sizeof(ck_cert_type); - - rv = f->C_GetAttributeValue(session, obj, key_attr, 1); - if (rv != CKR_OK) { - error("C_GetAttributeValue failed: %lu", rv); - goto fail; - } - - key = NULL; - label = NULL; - switch (ck_cert_type) { - case CKC_X_509: - if (pkcs11_fetch_x509_pubkey(p, slotidx, &obj, - &key, &label) != 0) { - error("failed to fetch key"); - continue; - } - break; - default: - error("skipping unsupported certificate type %lu", - ck_cert_type); - continue; - } - note_key(p, slotidx, __func__, key); - if (pkcs11_key_included(keysp, nkeys, key)) { - debug2_f("key already included");; - sshkey_free(key); - } else { - /* expand key array and add key */ - *keysp = xrecallocarray(*keysp, *nkeys, - *nkeys + 1, sizeof(struct sshkey *)); - (*keysp)[*nkeys] = key; - if (labelsp != NULL) { - *labelsp = xrecallocarray(*labelsp, *nkeys, - *nkeys + 1, sizeof(char *)); - (*labelsp)[*nkeys] = xstrdup((char *)label); - } - *nkeys = *nkeys + 1; - debug("have %d keys", *nkeys); - } + if (labelp != NULL) { + if (attribs[1].ulValueLen > 0) { + label[attribs[1].ulValueLen] = '\0'; + *labelp = xstrdup(label); + } else + xasprintf(labelp, "pub[%s]", p->name); } - ret = 0; -fail: - rv = f->C_FindObjectsFinal(session); - if (rv != CKR_OK) { - error("C_FindObjectsFinal failed: %lu", rv); - ret = -1; + switch (type) { + case CKK_RSA: + return pkcs11_get_pubkey_rsa(p, slotidx, obj); +#ifdef OPENSSL_HAS_ECC + case CKK_ECDSA: + return pkcs11_get_pubkey_ec(p, slotidx, obj); +#endif /* OPENSSL_HAS_ECC */ + default: + error_f("unsupported key type: %lu", type); } - return (ret); + return NULL; } /* @@ -1213,295 +1448,68 @@ pkcs11_fetch_keys(struct pkcs11_provider *p, CK_ULONG slotidx, struct sshkey ***keysp, char ***labelsp, int *nkeys) { - struct sshkey *key = NULL; - CK_OBJECT_CLASS key_class; - CK_ATTRIBUTE key_attr[2]; - CK_SESSION_HANDLE session; - CK_FUNCTION_LIST *f = NULL; - CK_RV rv; - CK_OBJECT_HANDLE obj; - CK_ULONG n = 0; - int ret = -1; - - memset(&key_attr, 0, sizeof(key_attr)); - memset(&obj, 0, sizeof(obj)); - - key_class = CKO_PUBLIC_KEY; - key_attr[0].type = CKA_CLASS; - key_attr[0].pValue = &key_class; - key_attr[0].ulValueLen = sizeof(key_class); + CK_FUNCTION_LIST *f = p->function_list; + CK_SESSION_HANDLE session = p->slotinfo[slotidx].session; + CK_RV rv; - session = p->slotinfo[slotidx].session; - f = p->function_list; +{ /* setup a filter that looks for public keys */ + /* Find objects with public key class. */ + CK_OBJECT_CLASS key_class = CKO_PUBLIC_KEY; + CK_ATTRIBUTE filter[] = { + { CKA_CLASS, NULL, sizeof(key_class) } + }; + /* some compilers complain about non-constant initializer so we + use NULL in CK_ATTRIBUTE above and set the value here */ + filter[0].pValue = &key_class; - rv = f->C_FindObjectsInit(session, key_attr, 1); + rv = f->C_FindObjectsInit(session, filter, 1); if (rv != CKR_OK) { - error("C_FindObjectsInit failed: %lu", rv); - goto fail; + error_f("C_FindObjectsInit failed: %lu", rv); + return -1; } +} while (1) { - CK_KEY_TYPE ck_key_type; - CK_UTF8CHAR label[256]; + CK_OBJECT_HANDLE obj; + CK_ULONG nfound; + struct sshkey *key; + char *label; - rv = f->C_FindObjects(session, &obj, 1, &n); + rv = f->C_FindObjects(session, &obj, 1, &nfound); if (rv != CKR_OK) { - error("C_FindObjects failed: %lu", rv); - goto fail; - } - if (n == 0) + error_f("C_FindObjects failed: %lu", rv); break; - - memset(&ck_key_type, 0, sizeof(ck_key_type)); - memset(&key_attr, 0, sizeof(key_attr)); - key_attr[0].type = CKA_KEY_TYPE; - key_attr[0].pValue = &ck_key_type; - key_attr[0].ulValueLen = sizeof(ck_key_type); - key_attr[1].type = CKA_LABEL; - key_attr[1].pValue = &label; - key_attr[1].ulValueLen = sizeof(label) - 1; - - rv = f->C_GetAttributeValue(session, obj, key_attr, 2); - if (rv != CKR_OK) { - error("C_GetAttributeValue failed: %lu", rv); - goto fail; } - - label[key_attr[1].ulValueLen] = '\0'; - - switch (ck_key_type) { - case CKK_RSA: - key = pkcs11_fetch_rsa_pubkey(p, slotidx, &obj); - break; -#if defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW) - case CKK_ECDSA: - key = pkcs11_fetch_ecdsa_pubkey(p, slotidx, &obj); + if (nfound == 0) break; -#endif /* OPENSSL_HAS_ECC && HAVE_EC_KEY_METHOD_NEW */ - default: - /* XXX print key type? */ - key = NULL; - error("skipping unsupported key type"); - } - if (key == NULL) { - error("failed to fetch key"); - continue; - } - note_key(p, slotidx, __func__, key); - if (pkcs11_key_included(keysp, nkeys, key)) { - debug2_f("key already included");; - sshkey_free(key); - } else { - /* expand key array and add key */ - *keysp = xrecallocarray(*keysp, *nkeys, - *nkeys + 1, sizeof(struct sshkey *)); - (*keysp)[*nkeys] = key; - if (labelsp != NULL) { - *labelsp = xrecallocarray(*labelsp, *nkeys, - *nkeys + 1, sizeof(char *)); - (*labelsp)[*nkeys] = xstrdup((char *)label); - } - *nkeys = *nkeys + 1; - debug("have %d keys", *nkeys); - } + key = pkcs11_get_pubkey(p, slotidx, obj, &label); + note_key(p, slotidx, key); + pkcs11_push_key(key, label, keysp, labelsp, nkeys); } - ret = 0; -fail: rv = f->C_FindObjectsFinal(session); - if (rv != CKR_OK) { - error("C_FindObjectsFinal failed: %lu", rv); - ret = -1; - } - - return (ret); -} - -#ifdef WITH_PKCS11_KEYGEN -#define FILL_ATTR(attr, idx, typ, val, len) \ - { (attr[idx]).type=(typ); (attr[idx]).pValue=(val); (attr[idx]).ulValueLen=len; idx++; } - -static struct sshkey * -pkcs11_rsa_generate_private_key(struct pkcs11_provider *p, CK_ULONG slotidx, - char *label, CK_ULONG bits, CK_BYTE keyid, u_int32_t *err) -{ - struct pkcs11_slotinfo *si; - char *plabel = label ? label : ""; - int npub = 0, npriv = 0; - CK_RV rv; - CK_FUNCTION_LIST *f; - CK_SESSION_HANDLE session; - CK_BBOOL true_val = CK_TRUE, false_val = CK_FALSE; - CK_OBJECT_HANDLE pubKey, privKey; - CK_ATTRIBUTE tpub[16], tpriv[16]; - CK_MECHANISM mech = { - CKM_RSA_PKCS_KEY_PAIR_GEN, NULL_PTR, 0 - }; - CK_BYTE pubExponent[] = { - 0x01, 0x00, 0x01 /* RSA_F4 in bytes */ - }; - pubkey_filter[0].pValue = &pubkey_class; - cert_filter[0].pValue = &cert_class; - - *err = 0; - - FILL_ATTR(tpub, npub, CKA_TOKEN, &true_val, sizeof(true_val)); - FILL_ATTR(tpub, npub, CKA_LABEL, plabel, strlen(plabel)); - FILL_ATTR(tpub, npub, CKA_ENCRYPT, &false_val, sizeof(false_val)); - FILL_ATTR(tpub, npub, CKA_VERIFY, &true_val, sizeof(true_val)); - FILL_ATTR(tpub, npub, CKA_VERIFY_RECOVER, &false_val, - sizeof(false_val)); - FILL_ATTR(tpub, npub, CKA_WRAP, &false_val, sizeof(false_val)); - FILL_ATTR(tpub, npub, CKA_DERIVE, &false_val, sizeof(false_val)); - FILL_ATTR(tpub, npub, CKA_MODULUS_BITS, &bits, sizeof(bits)); - FILL_ATTR(tpub, npub, CKA_PUBLIC_EXPONENT, pubExponent, - sizeof(pubExponent)); - FILL_ATTR(tpub, npub, CKA_ID, &keyid, sizeof(keyid)); - - FILL_ATTR(tpriv, npriv, CKA_TOKEN, &true_val, sizeof(true_val)); - FILL_ATTR(tpriv, npriv, CKA_LABEL, plabel, strlen(plabel)); - FILL_ATTR(tpriv, npriv, CKA_PRIVATE, &true_val, sizeof(true_val)); - FILL_ATTR(tpriv, npriv, CKA_SENSITIVE, &true_val, sizeof(true_val)); - FILL_ATTR(tpriv, npriv, CKA_DECRYPT, &false_val, sizeof(false_val)); - FILL_ATTR(tpriv, npriv, CKA_SIGN, &true_val, sizeof(true_val)); - FILL_ATTR(tpriv, npriv, CKA_SIGN_RECOVER, &false_val, - sizeof(false_val)); - FILL_ATTR(tpriv, npriv, CKA_UNWRAP, &false_val, sizeof(false_val)); - FILL_ATTR(tpriv, npriv, CKA_DERIVE, &false_val, sizeof(false_val)); - FILL_ATTR(tpriv, npriv, CKA_ID, &keyid, sizeof(keyid)); - - f = p->function_list; - si = &p->slotinfo[slotidx]; - session = si->session; - - if ((rv = f->C_GenerateKeyPair(session, &mech, tpub, npub, tpriv, npriv, - &pubKey, &privKey)) != CKR_OK) { - error_f("key generation failed: error 0x%lx", rv); - *err = rv; - return NULL; - } - - return pkcs11_fetch_rsa_pubkey(p, slotidx, &pubKey); -} - -static int -pkcs11_decode_hex(const char *hex, unsigned char **dest, size_t *rlen) -{ - size_t i, len; - char ptr[3]; - - if (dest) - *dest = NULL; - if (rlen) - *rlen = 0; - - if ((len = strlen(hex)) % 2) - return -1; - len /= 2; - - *dest = xmalloc(len); - - ptr[2] = '\0'; - for (i = 0; i < len; i++) { - ptr[0] = hex[2 * i]; - ptr[1] = hex[(2 * i) + 1]; - if (!isxdigit(ptr[0]) || !isxdigit(ptr[1])) - return -1; - (*dest)[i] = (unsigned char)strtoul(ptr, NULL, 16); - } - - if (rlen) - *rlen = len; + if (rv != CKR_OK) + error_f("C_FindObjectsFinal failed: %lu", rv); return 0; } -static struct ec_curve_info { - const char *name; - const char *oid; - const char *oid_encoded; - size_t size; -} ec_curve_infos[] = { - {"prime256v1", "1.2.840.10045.3.1.7", "06082A8648CE3D030107", 256}, - {"secp384r1", "1.3.132.0.34", "06052B81040022", 384}, - {"secp521r1", "1.3.132.0.35", "06052B81040023", 521}, - {NULL, NULL, NULL, 0}, -}; - -static struct sshkey * -pkcs11_ecdsa_generate_private_key(struct pkcs11_provider *p, CK_ULONG slotidx, - char *label, CK_ULONG bits, CK_BYTE keyid, u_int32_t *err) -{ - struct pkcs11_slotinfo *si; - char *plabel = label ? label : ""; - int i; - size_t ecparams_size; - unsigned char *ecparams = NULL; - int npub = 0, npriv = 0; - CK_RV rv; - CK_FUNCTION_LIST *f; - CK_SESSION_HANDLE session; - CK_BBOOL true_val = CK_TRUE, false_val = CK_FALSE; - CK_OBJECT_HANDLE pubKey, privKey; - CK_MECHANISM mech = { - CKM_EC_KEY_PAIR_GEN, NULL_PTR, 0 - }; - CK_ATTRIBUTE tpub[16], tpriv[16]; - - *err = 0; - - for (i = 0; ec_curve_infos[i].name; i++) { - if (ec_curve_infos[i].size == bits) - break; - } - if (!ec_curve_infos[i].name) { - error_f("invalid key size %lu", bits); - return NULL; - } - if (pkcs11_decode_hex(ec_curve_infos[i].oid_encoded, &ecparams, - &ecparams_size) == -1) { - error_f("invalid oid"); - return NULL; - } +static int/*boolean*/ +dlsym_getfunctionlist(void *handle, + CK_RV (**getfunctionlist)(CK_FUNCTION_LIST **)) +{ + union { + CK_RV (*dlfun)(CK_FUNCTION_LIST **); + void *dlret; + } u; - FILL_ATTR(tpub, npub, CKA_TOKEN, &true_val, sizeof(true_val)); - FILL_ATTR(tpub, npub, CKA_LABEL, plabel, strlen(plabel)); - FILL_ATTR(tpub, npub, CKA_ENCRYPT, &false_val, sizeof(false_val)); - FILL_ATTR(tpub, npub, CKA_VERIFY, &true_val, sizeof(true_val)); - FILL_ATTR(tpub, npub, CKA_VERIFY_RECOVER, &false_val, - sizeof(false_val)); - FILL_ATTR(tpub, npub, CKA_WRAP, &false_val, sizeof(false_val)); - FILL_ATTR(tpub, npub, CKA_DERIVE, &false_val, sizeof(false_val)); - FILL_ATTR(tpub, npub, CKA_EC_PARAMS, ecparams, ecparams_size); - FILL_ATTR(tpub, npub, CKA_ID, &keyid, sizeof(keyid)); - - FILL_ATTR(tpriv, npriv, CKA_TOKEN, &true_val, sizeof(true_val)); - FILL_ATTR(tpriv, npriv, CKA_LABEL, plabel, strlen(plabel)); - FILL_ATTR(tpriv, npriv, CKA_PRIVATE, &true_val, sizeof(true_val)); - FILL_ATTR(tpriv, npriv, CKA_SENSITIVE, &true_val, sizeof(true_val)); - FILL_ATTR(tpriv, npriv, CKA_DECRYPT, &false_val, sizeof(false_val)); - FILL_ATTR(tpriv, npriv, CKA_SIGN, &true_val, sizeof(true_val)); - FILL_ATTR(tpriv, npriv, CKA_SIGN_RECOVER, &false_val, - sizeof(false_val)); - FILL_ATTR(tpriv, npriv, CKA_UNWRAP, &false_val, sizeof(false_val)); - FILL_ATTR(tpriv, npriv, CKA_DERIVE, &false_val, sizeof(false_val)); - FILL_ATTR(tpriv, npriv, CKA_ID, &keyid, sizeof(keyid)); - - f = p->function_list; - si = &p->slotinfo[slotidx]; - session = si->session; - - if ((rv = f->C_GenerateKeyPair(session, &mech, tpub, npub, tpriv, npriv, - &pubKey, &privKey)) != CKR_OK) { - error_f("key generation failed: error 0x%lx", rv); - *err = rv; - return NULL; - } + u.dlret = dlsym(handle, "C_GetFunctionList"); + if (u.dlret == NULL) return 0; - return pkcs11_fetch_ecdsa_pubkey(p, slotidx, &pubKey); + *getfunctionlist = u.dlfun; + return 1; } -#endif /* WITH_PKCS11_KEYGEN */ /* * register a new provider, fails if provider already exists. if @@ -1513,7 +1521,7 @@ struct pkcs11_provider **providerp, CK_ULONG user) { int nkeys, need_finalize = 0; - int ret = -1; + int ret = SSH_PKCS11_ERR_GENERIC; struct pkcs11_provider *p = NULL; void *handle = NULL; CK_RV (*getfunctionlist)(CK_FUNCTION_LIST **); @@ -1526,26 +1534,28 @@ goto fail; *providerp = NULL; - if (keyp != NULL) - *keyp = NULL; - if (labelsp != NULL) - *labelsp = NULL; - if (pkcs11_provider_lookup(provider_id) != NULL) { debug_f("provider already registered: %s", provider_id); goto fail; } - if (lib_contains_symbol(provider_id, "C_GetFunctionList") != 0) { - error("provider %s is not a PKCS11 library", provider_id); - goto fail; - } /* open shared pkcs11-library */ - if ((handle = dlopen(provider_id, RTLD_NOW)) == NULL) { + if ((handle = dlopen(provider_id, + #ifdef RTLD_LOCAL + RTLD_LOCAL | + #endif + #ifdef RTLD_LAZY + RTLD_LAZY + #else + RTLD_NOW + #endif + )) == NULL) { error("dlopen %s failed: %s", provider_id, dlerror()); goto fail; } - if ((getfunctionlist = dlsym(handle, "C_GetFunctionList")) == NULL) - fatal("dlsym(C_GetFunctionList) failed: %s", dlerror()); + if (!dlsym_getfunctionlist(handle, &getfunctionlist)) { + error("dlsym(C_GetFunctionList) failed: %s", dlerror()); + goto fail; + } p = xcalloc(1, sizeof(*p)); p->name = xstrdup(provider_id); p->handle = handle; @@ -1578,11 +1588,12 @@ p->info.libraryVersion.minor); if ((rv = f->C_GetSlotList(CK_TRUE, NULL, &p->nslots)) != CKR_OK) { error("C_GetSlotList failed: %lu", rv); + ret = SSH_PKCS11_ERR_NO_SLOTS; goto fail; } if (p->nslots == 0) { debug_f("provider %s returned no slots", provider_id); - ret = -SSH_PKCS11_ERR_NO_SLOTS; + ret = SSH_PKCS11_ERR_NO_SLOTS; goto fail; } p->slotlist = xcalloc(p->nslots, sizeof(CK_SLOT_ID)); @@ -1590,6 +1601,7 @@ != CKR_OK) { error("C_GetSlotList for provider %s failed: %lu", provider_id, rv); + ret = SSH_PKCS11_ERR_NO_SLOTS; goto fail; } p->slotinfo = xcalloc(p->nslots, sizeof(struct pkcs11_slotinfo)); @@ -1600,12 +1612,12 @@ if ((rv = f->C_GetTokenInfo(p->slotlist[i], token)) != CKR_OK) { error("C_GetTokenInfo for provider %s slot %lu " - "failed: %lu", provider_id, (u_long)i, rv); + "failed: %lu", provider_id, (unsigned long)i, rv); continue; } if ((token->flags & CKF_TOKEN_INITIALIZED) == 0) { debug2_f("ignoring uninitialised token in " - "provider %s slot %lu", provider_id, (u_long)i); + "provider %s slot %lu", provider_id, (unsigned long)i); continue; } debug("provider %s slot %lu: label <%.*s> " @@ -1616,28 +1628,34 @@ RMSPACE(token->model), RMSPACE(token->serialNumber), token->flags); /* - * open session, login with pin and retrieve public - * keys (if keyp is provided) + * open session, login with pin if required and + * retrieve public keys */ - if ((ret = pkcs11_open_session(p, i, pin, user)) != 0 || - keyp == NULL) + { int r = pkcs11_open_session(p, i, pin, user); + if (r != 0) { + error_r(r, "pkcs11_open_session for provider %s slot %lu " + "failed", provider_id, (unsigned long)i); continue; + } + } + pkcs11_fetch_certs(p, i, keyp, labelsp, &nkeys); pkcs11_fetch_keys(p, i, keyp, labelsp, &nkeys); + + /* + * Some tokens could mark public keys as private object. + * Usually certificates are marked as public object. + * So if no key are loaded above and if session is + * interactive try to login and fetch "private" objects. + */ + if (nkeys != 0 || !pkcs11_interactive || p->slotinfo[i].logged_in) + continue; + + if (!pkcs11_login(&p->slotinfo[i], f)) + continue; + + /*try to fetch certificate just in case*/ pkcs11_fetch_certs(p, i, keyp, labelsp, &nkeys); - if (nkeys == 0 && !p->slotinfo[i].logged_in && - pkcs11_interactive) { - /* - * Some tokens require login before they will - * expose keys. - */ - if (pkcs11_login_slot(p, &p->slotinfo[i], - CKU_USER) < 0) { - error("login failed"); - continue; - } - pkcs11_fetch_keys(p, i, keyp, labelsp, &nkeys); - pkcs11_fetch_certs(p, i, keyp, labelsp, &nkeys); - } + pkcs11_fetch_keys(p, i, keyp, labelsp, &nkeys); } /* now owned by caller */ @@ -1646,22 +1664,15 @@ TAILQ_INSERT_TAIL(&pkcs11_providers, p, next); p->refcount++; /* add to provider list */ - return (nkeys); + return nkeys; fail: if (need_finalize && (rv = f->C_Finalize(NULL)) != CKR_OK) error("C_Finalize for provider %s failed: %lu", provider_id, rv); - if (p) { - free(p->name); - free(p->slotlist); - free(p->slotinfo); - free(p); - } + pkcs11_provider_free(p); if (handle) dlclose(handle); - if (ret > 0) - ret = -1; - return (ret); + return ret; } /* @@ -1675,8 +1686,14 @@ struct pkcs11_provider *p = NULL; int nkeys; - nkeys = pkcs11_register_provider(provider_id, pin, keyp, labelsp, - &p, CKU_USER); + if (keyp == NULL) + return -1; + + *keyp = NULL; + if (labelsp != NULL) + *labelsp = NULL; + + nkeys = pkcs11_register_provider(provider_id, pin, keyp, labelsp, &p, CKU_USER); /* no keys found or some other error, de-register provider */ if (nkeys <= 0 && p != NULL) { @@ -1687,202 +1704,11 @@ if (nkeys == 0) debug_f("provider %s returned no keys", provider_id); - return (nkeys); + return nkeys; } -#ifdef WITH_PKCS11_KEYGEN -struct sshkey * -pkcs11_gakp(char *provider_id, char *pin, unsigned int slotidx, char *label, - unsigned int type, unsigned int bits, unsigned char keyid, u_int32_t *err) -{ - struct pkcs11_provider *p = NULL; - struct pkcs11_slotinfo *si; - CK_FUNCTION_LIST *f; - CK_SESSION_HANDLE session; - struct sshkey *k = NULL; - int ret = -1, reset_pin = 0, reset_provider = 0; - CK_RV rv; - - *err = 0; - - if ((p = pkcs11_provider_lookup(provider_id)) != NULL) - debug_f("provider \"%s\" available", provider_id); - else if ((ret = pkcs11_register_provider(provider_id, pin, NULL, NULL, - &p, CKU_SO)) < 0) { - debug_f("could not register provider %s", provider_id); - goto out; - } else - reset_provider = 1; - - f = p->function_list; - si = &p->slotinfo[slotidx]; - session = si->session; - - if ((rv = f->C_SetOperationState(session , pin, strlen(pin), - CK_INVALID_HANDLE, CK_INVALID_HANDLE)) != CKR_OK) { - debug_f("could not supply SO pin: %lu", rv); - reset_pin = 0; - } else - reset_pin = 1; - - switch (type) { - case KEY_RSA: - if ((k = pkcs11_rsa_generate_private_key(p, slotidx, label, - bits, keyid, err)) == NULL) { - debug_f("failed to generate RSA key"); - goto out; - } - break; - case KEY_ECDSA: - if ((k = pkcs11_ecdsa_generate_private_key(p, slotidx, label, - bits, keyid, err)) == NULL) { - debug_f("failed to generate ECDSA key"); - goto out; - } - break; - default: - *err = SSH_PKCS11_ERR_GENERIC; - debug_f("unknown type %d", type); - goto out; - } - -out: - if (reset_pin) - f->C_SetOperationState(session , NULL, 0, CK_INVALID_HANDLE, - CK_INVALID_HANDLE); - - if (reset_provider) - pkcs11_del_provider(provider_id); - - return (k); -} - -struct sshkey * -pkcs11_destroy_keypair(char *provider_id, char *pin, unsigned long slotidx, - unsigned char keyid, u_int32_t *err) -{ - struct pkcs11_provider *p = NULL; - struct pkcs11_slotinfo *si; - struct sshkey *k = NULL; - int reset_pin = 0, reset_provider = 0; - CK_ULONG nattrs; - CK_FUNCTION_LIST *f; - CK_SESSION_HANDLE session; - CK_ATTRIBUTE attrs[16]; - CK_OBJECT_CLASS key_class; - CK_KEY_TYPE key_type; - CK_OBJECT_HANDLE obj = CK_INVALID_HANDLE; - CK_RV rv; - - *err = 0; - - if ((p = pkcs11_provider_lookup(provider_id)) != NULL) { - debug_f("using provider \"%s\"", provider_id); - } else if (pkcs11_register_provider(provider_id, pin, NULL, NULL, &p, - CKU_SO) < 0) { - debug_f("could not register provider %s", - provider_id); - goto out; - } else - reset_provider = 1; - - f = p->function_list; - si = &p->slotinfo[slotidx]; - session = si->session; - - if ((rv = f->C_SetOperationState(session , pin, strlen(pin), - CK_INVALID_HANDLE, CK_INVALID_HANDLE)) != CKR_OK) { - debug_f("could not supply SO pin: %lu", rv); - reset_pin = 0; - } else - reset_pin = 1; - - /* private key */ - nattrs = 0; - key_class = CKO_PRIVATE_KEY; - FILL_ATTR(attrs, nattrs, CKA_CLASS, &key_class, sizeof(key_class)); - FILL_ATTR(attrs, nattrs, CKA_ID, &keyid, sizeof(keyid)); - - if (pkcs11_find(p, slotidx, attrs, nattrs, &obj) == 0 && - obj != CK_INVALID_HANDLE) { - if ((rv = f->C_DestroyObject(session, obj)) != CKR_OK) { - debug_f("could not destroy private key 0x%hhx", - keyid); - *err = rv; - goto out; - } - } - - /* public key */ - nattrs = 0; - key_class = CKO_PUBLIC_KEY; - FILL_ATTR(attrs, nattrs, CKA_CLASS, &key_class, sizeof(key_class)); - FILL_ATTR(attrs, nattrs, CKA_ID, &keyid, sizeof(keyid)); - - if (pkcs11_find(p, slotidx, attrs, nattrs, &obj) == 0 && - obj != CK_INVALID_HANDLE) { - - /* get key type */ - nattrs = 0; - FILL_ATTR(attrs, nattrs, CKA_KEY_TYPE, &key_type, - sizeof(key_type)); - rv = f->C_GetAttributeValue(session, obj, attrs, nattrs); - if (rv != CKR_OK) { - debug_f("could not get key type of public key 0x%hhx", - keyid); - *err = rv; - key_type = -1; - } - if (key_type == CKK_RSA) - k = pkcs11_fetch_rsa_pubkey(p, slotidx, &obj); - else if (key_type == CKK_ECDSA) - k = pkcs11_fetch_ecdsa_pubkey(p, slotidx, &obj); - - if ((rv = f->C_DestroyObject(session, obj)) != CKR_OK) { - debug_f("could not destroy public key 0x%hhx", keyid); - *err = rv; - goto out; - } - } - -out: - if (reset_pin) - f->C_SetOperationState(session , NULL, 0, CK_INVALID_HANDLE, - CK_INVALID_HANDLE); - - if (reset_provider) - pkcs11_del_provider(provider_id); - - return (k); -} -#endif /* WITH_PKCS11_KEYGEN */ #else /* ENABLE_PKCS11 */ -#include -#include -#include - -#include "log.h" -#include "sshkey.h" - -int -pkcs11_init(int interactive) -{ - error("%s: dlopen() not supported", __func__); - return (-1); -} +typedef int ssh_pkcs11_empty_translation_unit; -int -pkcs11_add_provider(char *provider_id, char *pin, struct sshkey ***keyp, - char ***labelsp) -{ - error("%s: dlopen() not supported", __func__); - return (-1); -} - -void -pkcs11_terminate(void) -{ - error("%s: dlopen() not supported", __func__); -} #endif /* ENABLE_PKCS11 */ diff -ruN openssh-9.4p1/ssh-pkcs11-client.c openssh-9.4p1+x509-14.2.1/ssh-pkcs11-client.c --- openssh-9.4p1/ssh-pkcs11-client.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/ssh-pkcs11-client.c 2023-08-20 10:07:01.000000000 +0300 @@ -1,7 +1,7 @@ -/* $OpenBSD: ssh-pkcs11-client.c,v 1.18 2023/07/19 14:03:45 djm Exp $ */ +/* $OpenBSD: ssh-pkcs11-client.c,v 1.17 2020/10/18 11:32:02 djm Exp $ */ /* * Copyright (c) 2010 Markus Friedl. All rights reserved. - * Copyright (c) 2014 Pedro Martelletto. All rights reserved. + * Copyright (c) 2016-2023 Roumen Petrov. All rights reserved. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -16,10 +16,25 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifndef USE_OPENSSL_PROVIDER +/* TODO: implement OpenSSL 4.0 API, as OpenSSL 3.* is quite nonfunctional */ +# define OPENSSL_SUPPRESS_DEPRECATED +#endif + +#define SSHKEY_INTERNAL #include "includes.h" #ifdef ENABLE_PKCS11 +#ifndef HAVE_RSA_PKCS1_OPENSSL +# undef RSA_PKCS1_OpenSSL +# define RSA_PKCS1_OpenSSL RSA_PKCS1_SSLeay +#endif + #include #ifdef HAVE_SYS_TIME_H # include @@ -30,165 +45,62 @@ #include #include #include -#include -#include #include +#include "evp-compat.h" #include "pathnames.h" #include "xmalloc.h" #include "sshbuf.h" #include "log.h" #include "misc.h" -#include "sshkey.h" +#include "sshxkey.h" #include "authfd.h" #include "atomicio.h" #include "ssh-pkcs11.h" -#include "ssherr.h" - -#include "openbsd-compat/openssl-compat.h" - -#if !defined(OPENSSL_HAS_ECC) || !defined(HAVE_EC_KEY_METHOD_NEW) -#define EC_KEY_METHOD void -#define EC_KEY void -#endif /* borrows code from sftp-server and ssh-agent */ -/* - * Maintain a list of ssh-pkcs11-helper subprocesses. These may be looked up - * by provider path or their unique EC/RSA METHOD pointers. - */ -struct helper { - char *path; - pid_t pid; - int fd; - RSA_METHOD *rsa_meth; - EC_KEY_METHOD *ec_meth; - int (*rsa_finish)(RSA *rsa); - void (*ec_finish)(EC_KEY *key); - size_t nrsa, nec; /* number of active keys of each type */ -}; -static struct helper **helpers; -static size_t nhelpers; - -static struct helper * -helper_by_provider(const char *path) -{ - size_t i; - - for (i = 0; i < nhelpers; i++) { - if (helpers[i] == NULL || helpers[i]->path == NULL || - helpers[i]->fd == -1) - continue; - if (strcmp(helpers[i]->path, path) == 0) - return helpers[i]; - } - return NULL; -} - -static struct helper * -helper_by_rsa(const RSA *rsa) -{ - size_t i; - const RSA_METHOD *meth; - - if ((meth = RSA_get_method(rsa)) == NULL) - return NULL; - for (i = 0; i < nhelpers; i++) { - if (helpers[i] != NULL && helpers[i]->rsa_meth == meth) - return helpers[i]; - } - return NULL; - -} - -#if defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW) -static struct helper * -helper_by_ec(const EC_KEY *ec) -{ - size_t i; - const EC_KEY_METHOD *meth; +static int fd = -1; +static pid_t pid = -1; - if ((meth = EC_KEY_get_method(ec)) == NULL) - return NULL; - for (i = 0; i < nhelpers; i++) { - if (helpers[i] != NULL && helpers[i]->ec_meth == meth) - return helpers[i]; - } - return NULL; +static int +helper_msg_sign_request( + struct sshbuf *buf, struct sshkey *key, + const unsigned char *dgst, int dlen +) { + int r = 0; + u_char *blob = NULL; + size_t blen; +{ /* Use method with algorithm nevertheless that sign request + * to helper is only with pure plain keys! Actually key-blob + * below is used by helper only to find key. + */ + const char *pkalg = sshkey_ssh_name(key); + r = Xkey_to_blob(pkalg, key, &blob, &blen); + if (r != 0) goto done; } -#endif /* defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW) */ -static void -helper_free(struct helper *helper) -{ - size_t i; - int found = 0; + if ((r = sshbuf_put_u8(buf, SSH2_AGENTC_SIGN_REQUEST)) != 0 || + (r = sshbuf_put_string(buf, blob, blen)) != 0 || + (r = sshbuf_put_string(buf, dgst, (size_t) dlen)) != 0 || + (r = sshbuf_put_u32(buf, 0)) != 0 + ) goto done; - if (helper == NULL) - return; - if (helper->path == NULL || helper->ec_meth == NULL || - helper->rsa_meth == NULL) - fatal_f("inconsistent helper"); - debug3_f("free helper for provider %s", helper->path); - for (i = 0; i < nhelpers; i++) { - if (helpers[i] == helper) { - if (found) - fatal_f("helper recorded more than once"); - found = 1; - } - else if (found) - helpers[i - 1] = helpers[i]; - } - if (found) { - helpers = xrecallocarray(helpers, nhelpers, - nhelpers - 1, sizeof(*helpers)); - nhelpers--; - } - free(helper->path); -#if defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW) - EC_KEY_METHOD_free(helper->ec_meth); -#endif - RSA_meth_free(helper->rsa_meth); - free(helper); -} +done: + free(blob); -static void -helper_terminate(struct helper *helper) -{ - if (helper == NULL) { - return; - } else if (helper->fd == -1) { - debug3_f("already terminated"); - } else { - debug3_f("terminating helper for %s; " - "remaining %zu RSA %zu ECDSA", - helper->path, helper->nrsa, helper->nec); - close(helper->fd); - /* XXX waitpid() */ - helper->fd = -1; - helper->pid = -1; - } - /* - * Don't delete the helper entry until there are no remaining keys - * that reference it. Otherwise, any signing operation would call - * a free'd METHOD pointer and that would be bad. - */ - if (helper->nrsa == 0 && helper->nec == 0) - helper_free(helper); + return r; } static void -send_msg(int fd, struct sshbuf *m) +send_msg(struct sshbuf *m) { u_char buf[4]; size_t mlen = sshbuf_len(m); int r; - if (fd == -1) - return; POKE_U32(buf, mlen); if (atomicio(vwrite, fd, buf, 4) != 4 || atomicio(vwrite, fd, sshbuf_mutable_ptr(m), @@ -199,15 +111,12 @@ } static int -recv_msg(int fd, struct sshbuf *m) +recv_msg(struct sshbuf *m) { u_int l, len; u_char c, buf[1024]; int r; - sshbuf_reset(m); - if (fd == -1) - return 0; /* XXX */ if ((len = atomicio(read, fd, buf, 4)) != 4) { error("read from helper failed: %u", len); return (0); /* XXX */ @@ -216,6 +125,7 @@ if (len > 256 * 1024) fatal("response too long: %u", len); /* read len bytes into m */ + sshbuf_reset(m); while (len > 0) { l = len; if (l > sizeof(buf)) @@ -229,271 +139,283 @@ len -= l; } if ((r = sshbuf_get_u8(m, &c)) != 0) - fatal_fr(r, "parse type"); + fatal_fr(r, "parse"); return c; } int pkcs11_init(int interactive) { - return 0; + (void)interactive; + return (0); } void pkcs11_terminate(void) { - size_t i; - - debug3_f("terminating %zu helpers", nhelpers); - for (i = 0; i < nhelpers; i++) - helper_terminate(helpers[i]); + if (fd >= 0) + close(fd); } static int -rsa_encrypt(int flen, const u_char *from, u_char *to, RSA *rsa, int padding) +pkcs11_rsa_private_encrypt(int flen, const u_char *from, u_char *to, RSA *rsa, + int padding) { - struct sshkey *key = NULL; + struct sshkey *key; struct sshbuf *msg = NULL; - u_char *blob = NULL, *signature = NULL; - size_t blen, slen = 0; - int r, ret = -1; - struct helper *helper; + u_char *signature = NULL; + size_t slen = 0; + int r; + int ret = -1; + + if (padding != RSA_PKCS1_PADDING) return -1; - if ((helper = helper_by_rsa(rsa)) == NULL || helper->fd == -1) - fatal_f("no helper for PKCS11 key"); - debug3_f("signing with PKCS11 provider %s", helper->path); - if (padding != RSA_PKCS1_PADDING) - goto fail; key = sshkey_new(KEY_UNSPEC); if (key == NULL) { error_f("sshkey_new failed"); - goto fail; + goto done; } key->type = KEY_RSA; - RSA_up_ref(rsa); - key->rsa = rsa; - if ((r = sshkey_to_blob(key, &blob, &blen)) != 0) { - error_fr(r, "encode key"); - goto fail; - } + key->pk = EVP_PKEY_new(); + if (key->pk == NULL) + goto done; + if (!EVP_PKEY_set1_RSA(key->pk, rsa)) + goto done; + if ((msg = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); - if ((r = sshbuf_put_u8(msg, SSH2_AGENTC_SIGN_REQUEST)) != 0 || - (r = sshbuf_put_string(msg, blob, blen)) != 0 || - (r = sshbuf_put_string(msg, from, flen)) != 0 || - (r = sshbuf_put_u32(msg, 0)) != 0) - fatal_fr(r, "compose"); - send_msg(helper->fd, msg); + if (helper_msg_sign_request(msg, key, from, flen) != 0) + goto done; + send_msg(msg); sshbuf_reset(msg); - if (recv_msg(helper->fd, msg) == SSH2_AGENT_SIGN_RESPONSE) { + if (recv_msg(msg) == SSH2_AGENT_SIGN_RESPONSE) { if ((r = sshbuf_get_string(msg, &signature, &slen)) != 0) - fatal_fr(r, "parse"); + goto done; if (slen <= (size_t)RSA_size(rsa)) { memcpy(to, signature, slen); ret = slen; } - free(signature); } - fail: - free(blob); + +done: + if (ret == -1) + PKCS11err(PKCS11_RSA_PRIVATE_ENCRYPT, PKCS11_SIGNREQ_FAIL); + + free(signature); sshkey_free(key); sshbuf_free(msg); - return (ret); + return ret; } -static int -rsa_finish(RSA *rsa) -{ - struct helper *helper; - - if ((helper = helper_by_rsa(rsa)) == NULL) - fatal_f("no helper for PKCS11 key"); - debug3_f("free PKCS11 RSA key for provider %s", helper->path); - if (helper->rsa_finish != NULL) - helper->rsa_finish(rsa); - if (helper->nrsa == 0) - fatal_f("RSA refcount error"); - helper->nrsa--; - debug3_f("provider %s remaining keys: %zu RSA %zu ECDSA", - helper->path, helper->nrsa, helper->nec); - if (helper->nrsa == 0 && helper->nec == 0) - helper_terminate(helper); - return 1; -} - -#if defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW) -static ECDSA_SIG * -ecdsa_do_sign(const unsigned char *dgst, int dgst_len, const BIGNUM *inv, - const BIGNUM *rp, EC_KEY *ec) -{ - struct sshkey *key = NULL; +#ifdef OPENSSL_HAS_ECC +static ECDSA_SIG* +pkcs11_ecdsa_do_sign( + const unsigned char *dgst, int dlen, + const BIGNUM *inv, const BIGNUM *rp, + EC_KEY *ec +) { + struct sshkey *key; struct sshbuf *msg = NULL; + u_char *signature = NULL; + size_t slen = 0; + int r; ECDSA_SIG *ret = NULL; - const u_char *cp; - u_char *blob = NULL, *signature = NULL; - size_t blen, slen = 0; - int r, nid; - struct helper *helper; - - if ((helper = helper_by_ec(ec)) == NULL || helper->fd == -1) - fatal_f("no helper for PKCS11 key"); - debug3_f("signing with PKCS11 provider %s", helper->path); - nid = sshkey_ecdsa_key_to_nid(ec); - if (nid < 0) { - error_f("couldn't get curve nid"); - goto fail; - } + + UNUSED(inv); + UNUSED(rp); key = sshkey_new(KEY_UNSPEC); if (key == NULL) { error_f("sshkey_new failed"); - goto fail; + goto done; + } + key->ecdsa_nid = ssh_EC_KEY_preserve_nid(ec); + if (key->ecdsa_nid < 0) { + error_f("unsupported elliptic curve"); + goto done; } - key->ecdsa = ec; - key->ecdsa_nid = nid; key->type = KEY_ECDSA; - EC_KEY_up_ref(ec); + key->pk = EVP_PKEY_new(); + if (key->pk == NULL) + goto done; + if (!EVP_PKEY_set1_EC_KEY(key->pk, ec)) + goto done; - if ((r = sshkey_to_blob(key, &blob, &blen)) != 0) { - error_fr(r, "encode key"); - goto fail; - } if ((msg = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); - if ((r = sshbuf_put_u8(msg, SSH2_AGENTC_SIGN_REQUEST)) != 0 || - (r = sshbuf_put_string(msg, blob, blen)) != 0 || - (r = sshbuf_put_string(msg, dgst, dgst_len)) != 0 || - (r = sshbuf_put_u32(msg, 0)) != 0) - fatal_fr(r, "compose"); - send_msg(helper->fd, msg); + if (helper_msg_sign_request(msg, key, dgst, dlen) != 0) + goto done; + send_msg(msg); sshbuf_reset(msg); - if (recv_msg(helper->fd, msg) == SSH2_AGENT_SIGN_RESPONSE) { + if (recv_msg(msg) == SSH2_AGENT_SIGN_RESPONSE) { if ((r = sshbuf_get_string(msg, &signature, &slen)) != 0) - fatal_fr(r, "parse"); - cp = signature; - ret = d2i_ECDSA_SIG(NULL, &cp, slen); - free(signature); + goto done; + + { /* decode ECDSA signature */ + const unsigned char *p = signature; + ret = d2i_ECDSA_SIG(NULL, &p, slen); + } } - fail: - free(blob); +done: + if (ret == NULL) + PKCS11err(PKCS11_ECDSA_DO_SIGN, PKCS11_SIGNREQ_FAIL); + + free(signature); sshkey_free(key); sshbuf_free(msg); - return (ret); + return ret; } -static void -ecdsa_do_finish(EC_KEY *ec) -{ - struct helper *helper; +#ifdef HAVE_EC_KEY_METHOD_NEW +static int +pkcs11_ecdsa_sign(int type, + const unsigned char *dgst, int dlen, + unsigned char *sig, unsigned int *siglen, + const BIGNUM *inv, const BIGNUM *rp, + EC_KEY *ec +) { + ECDSA_SIG *s; + + debug3_f("..."); + (void)type; + + s = pkcs11_ecdsa_do_sign(dgst, dlen, inv, rp, ec); + if (s == NULL) { + *siglen = 0; + return (0); + } + + *siglen = i2d_ECDSA_SIG(s, &sig); - if ((helper = helper_by_ec(ec)) == NULL) - fatal_f("no helper for PKCS11 key"); - debug3_f("free PKCS11 ECDSA key for provider %s", helper->path); - if (helper->ec_finish != NULL) - helper->ec_finish(ec); - if (helper->nec == 0) - fatal_f("ECDSA refcount error"); - helper->nec--; - debug3_f("provider %s remaining keys: %zu RSA %zu ECDSA", - helper->path, helper->nrsa, helper->nec); - if (helper->nrsa == 0 && helper->nec == 0) - helper_terminate(helper); + ECDSA_SIG_free(s); + return (1); } -#endif /* defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW) */ +#endif /*def HAVE_EC_KEY_METHOD_NEW*/ +#endif /*def OPENSSL_HAS_ECC*/ -/* redirect private key crypto operations to the ssh-pkcs11-helper */ -static void -wrap_key(struct helper *helper, struct sshkey *k) +/* redirect the private key encrypt operation to the ssh-pkcs11-helper */ +static RSA_METHOD* +ssh_pkcs11helper_rsa_method(void) { + static RSA_METHOD *meth = NULL; + + if (meth != NULL) return meth; + + meth = RSA_meth_dup(RSA_PKCS1_OpenSSL()); + if (meth == NULL) return NULL; + + if (!RSA_meth_set1_name(meth, "ssh-pkcs11-rsa-helper") + || !RSA_meth_set_priv_enc(meth, pkcs11_rsa_private_encrypt) + ) + goto err; + + return meth; + +err: + RSA_meth_free(meth); + meth = NULL; + return NULL; +} + +#ifdef OPENSSL_HAS_ECC +static EC_KEY_METHOD* +ssh_pkcs11helper_ec_method(void) { + static EC_KEY_METHOD *meth = NULL; + + if (meth != NULL) return meth; + + meth = EC_KEY_METHOD_new(EC_KEY_OpenSSL()); + if (meth == NULL) return NULL; + +#ifndef HAVE_EC_KEY_METHOD_NEW /* OpenSSL < 1.1 */ + ECDSA_METHOD_set_sign(meth, + pkcs11_ecdsa_do_sign); +#else + EC_KEY_METHOD_set_sign(meth, + pkcs11_ecdsa_sign, + NULL /* *sign_setup */, + pkcs11_ecdsa_do_sign); +#endif + + return meth; +} +#endif /*def OPENSSL_HAS_ECC*/ + + +static inline int +wrap_key_rsa(struct sshkey *key) { - debug3_f("wrap %s for provider %s", sshkey_type(k), helper->path); - if (k->type == KEY_RSA) { - RSA_set_method(k->rsa, helper->rsa_meth); - if (helper->nrsa++ >= INT_MAX) - fatal_f("RSA refcount error"); -#if defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW) - } else if (k->type == KEY_ECDSA) { - EC_KEY_set_method(k->ecdsa, helper->ec_meth); - if (helper->nec++ >= INT_MAX) - fatal_f("EC refcount error"); + int ret; + + RSA_METHOD *meth = ssh_pkcs11helper_rsa_method(); + if (meth == NULL) return -1; + +{ RSA *rsa = EVP_PKEY_get1_RSA(key->pk); + ret = RSA_set_method(rsa, meth) ? 0 : -1; +#ifdef HAVE_EVP_KEYMGMT_GET0_PROVIDER /* OpenSSL 3+ */ + /* Throw out misfunctional "key manager" in OpenSSL 3+, + * i.e. make non-provider key. + */ + EVP_PKEY_set1_RSA(key->pk, rsa); #endif - } else - fatal_f("unknown key type"); - k->flags |= SSHKEY_FLAG_EXT; - debug3_f("provider %s remaining keys: %zu RSA %zu ECDSA", - helper->path, helper->nrsa, helper->nec); + RSA_free(rsa); +} + return ret; } -static int -pkcs11_start_helper_methods(struct helper *helper) +#ifdef OPENSSL_HAS_ECC +static inline int +wrap_key_ecdsa(struct sshkey *key) { - RSA_METHOD *rsa_meth; - EC_KEY_METHOD *ec_meth = NULL; -#if defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW) - int (*ec_init)(EC_KEY *key); - int (*ec_copy)(EC_KEY *dest, const EC_KEY *src); - int (*ec_set_group)(EC_KEY *key, const EC_GROUP *grp); - int (*ec_set_private)(EC_KEY *key, const BIGNUM *priv_key); - int (*ec_set_public)(EC_KEY *key, const EC_POINT *pub_key); - int (*ec_sign)(int, const unsigned char *, int, unsigned char *, - unsigned int *, const BIGNUM *, const BIGNUM *, EC_KEY *) = NULL; + int ret; - if ((ec_meth = EC_KEY_METHOD_new(EC_KEY_OpenSSL())) == NULL) - return -1; - EC_KEY_METHOD_get_sign(ec_meth, &ec_sign, NULL, NULL); - EC_KEY_METHOD_set_sign(ec_meth, ec_sign, NULL, ecdsa_do_sign); - EC_KEY_METHOD_get_init(ec_meth, &ec_init, &helper->ec_finish, - &ec_copy, &ec_set_group, &ec_set_private, &ec_set_public); - EC_KEY_METHOD_set_init(ec_meth, ec_init, ecdsa_do_finish, - ec_copy, ec_set_group, ec_set_private, ec_set_public); -#endif /* defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW) */ - - if ((rsa_meth = RSA_meth_dup(RSA_get_default_method())) == NULL) - fatal_f("RSA_meth_dup failed"); - helper->rsa_finish = RSA_meth_get_finish(rsa_meth); - if (!RSA_meth_set1_name(rsa_meth, "ssh-pkcs11-helper") || - !RSA_meth_set_priv_enc(rsa_meth, rsa_encrypt) || - !RSA_meth_set_finish(rsa_meth, rsa_finish)) - fatal_f("failed to prepare method"); - - helper->ec_meth = ec_meth; - helper->rsa_meth = rsa_meth; - return 0; + EC_KEY_METHOD *meth = ssh_pkcs11helper_ec_method(); + if (meth == NULL) return -1; + +{ EC_KEY *ec = EVP_PKEY_get1_EC_KEY(key->pk); + ret = EC_KEY_set_method(ec, meth) ? 0 : -1; +#ifdef HAVE_EVP_KEYMGMT_GET0_PROVIDER /* OpenSSL 3+ */ + /* Throw out misfunctional "key manager" in OpenSSL 3+, + * i.e. make non-provider key. + */ + EVP_PKEY_set1_EC_KEY(key->pk, ec); +#endif + EC_KEY_free(ec); } + return ret; +} +#endif /*def OPENSSL_HAS_ECC*/ -static struct helper * -pkcs11_start_helper(const char *path) +static inline int +wrap_key(struct sshkey *key) { + switch(key->type) { + case KEY_RSA: return wrap_key_rsa(key); +#ifdef OPENSSL_HAS_ECC + case KEY_ECDSA: return wrap_key_ecdsa(key); +#endif + } + return -1; +} + + +static int +pkcs11_start_helper(void) { int pair[2]; - char *prog, *verbosity = NULL; - struct helper *helper; - pid_t pid; - - if (nhelpers >= INT_MAX) - fatal_f("too many helpers"); - debug3_f("start helper for %s", path); + char *helper, *verbosity = NULL; + + if (get_log_level() >= SYSLOG_LEVEL_DEBUG1) + verbosity = "-vvv"; + if (socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == -1) { - error_f("socketpair: %s", strerror(errno)); - return NULL; - } - helper = xcalloc(1, sizeof(*helper)); - if (pkcs11_start_helper_methods(helper) == -1) { - error_f("pkcs11_start_helper_methods failed"); - goto fail; + error("socketpair: %s", strerror(errno)); + return (-1); } if ((pid = fork()) == -1) { - error_f("fork: %s", strerror(errno)); - fail: - close(pair[0]); - close(pair[1]); - RSA_meth_free(helper->rsa_meth); -#if defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW) - EC_KEY_METHOD_free(helper->ec_meth); -#endif - free(helper); - return NULL; + error("fork: %s", strerror(errno)); + return (-1); } else if (pid == 0) { if ((dup2(pair[1], STDIN_FILENO) == -1) || (dup2(pair[1], STDOUT_FILENO) == -1)) { @@ -502,99 +424,127 @@ } close(pair[0]); close(pair[1]); - prog = getenv("SSH_PKCS11_HELPER"); - if (prog == NULL || strlen(prog) == 0) - prog = _PATH_SSH_PKCS11_HELPER; - if (log_level_get() >= SYSLOG_LEVEL_DEBUG1) - verbosity = "-vvv"; - debug_f("starting %s %s", prog, + helper = getenv("SSH_PKCS11_HELPER"); + if (helper == NULL || strlen(helper) == 0) + helper = _PATH_SSH_PKCS11_HELPER; + debug_f("starting %s %s", helper, verbosity == NULL ? "" : verbosity); - execlp(prog, prog, verbosity, (char *)NULL); - fprintf(stderr, "exec: %s: %s\n", prog, strerror(errno)); + execlp(helper, helper, verbosity, (char *)NULL); + fprintf(stderr, "exec: %s: %s\n", helper, strerror(errno)); _exit(1); } close(pair[1]); - helper->fd = pair[0]; - helper->path = xstrdup(path); - helper->pid = pid; - debug3_f("helper %zu for \"%s\" on fd %d pid %ld", nhelpers, - helper->path, helper->fd, (long)helper->pid); - helpers = xrecallocarray(helpers, nhelpers, - nhelpers + 1, sizeof(*helpers)); - helpers[nhelpers++] = helper; - return helper; + fd = pair[0]; + return (0); } int -pkcs11_add_provider(char *name, char *pin, struct sshkey ***keysp, - char ***labelsp) +pkcs11_add_provider(char *name, char *pin, + struct sshkey ***keysp, char ***labelsp) { - struct sshkey *k; - int r, type; - u_char *blob; - char *label; - size_t blen; - u_int nkeys, i; + int ret = -1, r, type; + u_int32_t nkeys, i; struct sshbuf *msg; - struct helper *helper; - if ((helper = helper_by_provider(name)) == NULL && - (helper = pkcs11_start_helper(name)) == NULL) + if (fd < 0 && pkcs11_start_helper() < 0) + return (-1); + if (keysp == NULL) return -1; + *keysp = NULL; + if (labelsp != NULL) + *labelsp = NULL; + if ((msg = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); if ((r = sshbuf_put_u8(msg, SSH_AGENTC_ADD_SMARTCARD_KEY)) != 0 || (r = sshbuf_put_cstring(msg, name)) != 0 || (r = sshbuf_put_cstring(msg, pin)) != 0) fatal_fr(r, "compose"); - send_msg(helper->fd, msg); + send_msg(msg); sshbuf_reset(msg); - type = recv_msg(helper->fd, msg); - if (type == SSH2_AGENT_IDENTITIES_ANSWER) { - if ((r = sshbuf_get_u32(msg, &nkeys)) != 0) - fatal_fr(r, "parse nkeys"); + type = recv_msg(msg); + switch (type) { + case SSH2_AGENT_IDENTITIES_ANSWER: { + if ((r = sshbuf_get_u32(msg, &nkeys)) != 0) { + error_fr(r, "parse nkeys"); + goto done; + } *keysp = xcalloc(nkeys, sizeof(struct sshkey *)); if (labelsp) *labelsp = xcalloc(nkeys, sizeof(char *)); for (i = 0; i < nkeys; i++) { - /* XXX clean up properly instead of fatal() */ + u_char *blob; + size_t blen; + char *label = NULL; + struct sshkey *k; + if ((r = sshbuf_get_string(msg, &blob, &blen)) != 0 || - (r = sshbuf_get_cstring(msg, &label, NULL)) != 0) - fatal_fr(r, "parse key"); - if ((r = sshkey_from_blob(blob, blen, &k)) != 0) - fatal_fr(r, "decode key"); - wrap_key(helper, k); - (*keysp)[i] = k; + (r = sshbuf_get_cstring(msg, &label, NULL)) != 0) { + error_fr(r, "parse key"); + k = NULL; + goto set_key; + } + if ((r = Akey_from_blob(blob, blen, &k)) != 0) { + error_fr(r, "decode key"); + k = NULL; + goto set_key; + } + if (wrap_key(k) != 0) { + sshkey_free(k); + k = NULL; + } +set_key: + if (label && (*label == '\0')) { + free(label); + label = NULL; + } if (labelsp) (*labelsp)[i] = label; else free(label); + (*keysp)[i] = k; free(blob); } - } else if (type == SSH2_AGENT_FAILURE) { + ret = nkeys; + } break; + case SSH2_AGENT_FAILURE: { if ((r = sshbuf_get_u32(msg, &nkeys)) != 0) - nkeys = -1; - } else { - nkeys = -1; + error_fr(r, "parse nkeys"); + else { + ret = -nkeys; + error_f("helper fail to add provider: %d", ret); + } + } break; + default: + error_f("unknown message: %d", type); } + +done: sshbuf_free(msg); - return (nkeys); + return ret; } int pkcs11_del_provider(char *name) { - struct helper *helper; + int r, ret = -1; + struct sshbuf *msg; - /* - * ssh-agent deletes keys before calling this, so the helper entry - * should be gone before we get here. - */ - debug3_f("delete %s", name); - if ((helper = helper_by_provider(name)) != NULL) - helper_terminate(helper); - return 0; + if ((msg = sshbuf_new()) == NULL) + fatal_f("sshbuf_new failed"); + if ((r = sshbuf_put_u8(msg, SSH_AGENTC_REMOVE_SMARTCARD_KEY)) != 0 || + (r = sshbuf_put_cstring(msg, name)) != 0 || + (r = sshbuf_put_cstring(msg, "")) != 0) + fatal_fr(r, "compose"); + send_msg(msg); + sshbuf_reset(msg); + + if (recv_msg(msg) == SSH_AGENT_SUCCESS) + ret = 0; + sshbuf_free(msg); + return (ret); } + #endif /* ENABLE_PKCS11 */ diff -ruN openssh-9.4p1/ssh-pkcs11-err.c openssh-9.4p1+x509-14.2.1/ssh-pkcs11-err.c --- openssh-9.4p1/ssh-pkcs11-err.c 1970-01-01 02:00:00.000000000 +0200 +++ openssh-9.4p1+x509-14.2.1/ssh-pkcs11-err.c 2023-08-20 10:07:01.000000000 +0300 @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2018-2019 Roumen Petrov. All rights reserved. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "includes.h" + +#ifdef ENABLE_PKCS11 + +#include + +#include "ssh-pkcs11.h" + + +#ifndef OPENSSL_NO_ERR + +static ERR_STRING_DATA PKCS11_str_functs[] = { + { ERR_PACK(0, PKCS11_LOGIN, 0) , "login" }, + { ERR_PACK(0, PKCS11_REAUTHENTICATE, 0) , "reauthenticate" }, + { ERR_PACK(0, PKCS11_GET_KEY, 0) , "get_key" }, + { ERR_PACK(0, PKCS11_RSA_PRIVATE_ENCRYPT, 0) , "rsa_private_encrypt" }, + { ERR_PACK(0, PKCS11_DSA_DO_SIGN, 0) , "dsa_do_sign" }, + { ERR_PACK(0, PKCS11_ECDSA_DO_SIGN, 0) , "ecdsa_do_sign" }, + { 0, NULL } +}; + +static ERR_STRING_DATA PKCS11_str_reasons[] = { + { ERR_PACK(0, 0, PKCS11_SIGNREQ_FAIL) , "sign request fail" }, + { ERR_PACK(0, 0, PKCS11_C_SIGNINIT_FAIL) , "C_SignInit fail" }, + { ERR_PACK(0, 0, PKCS11_C_SIGN_FAIL) , "C_Sign fail" }, + { ERR_PACK(0, 0, PKCS11_C_LOGIN_FAIL) , "C_Login fail" }, + { ERR_PACK(0, 0, PKCS11_FINDKEY_FAIL) , "find key fail" }, + { 0, NULL } +}; + +static ERR_STRING_DATA PKCS11_lib_name[] = { + {0, "SSH PKCS#11"}, + {0, NULL} +}; + +#endif /*ndef OPENSSL_NO_ERR*/ + + +static int ERR_LIB_PKCS11 = 0; + +void +ERR_PKCS11_PUT_error(int function, int reason, char *file, int line, const char* funcname) { + if (ERR_LIB_PKCS11 == 0) + ERR_LIB_PKCS11 = ERR_get_next_error_library(); + +#ifdef OPENSSL_NO_FILENAMES /* OpenSSL 1.1+ */ + file = NULL; + line = 0; +#endif +#ifdef ERR_raise_data + UNUSED(function); + ERR_new(); + ERR_set_debug(file, line, funcname); + ERR_set_error(ERR_LIB_PKCS11, reason, NULL); +#else +# ifdef OPENSSL_NO_ERR + /* If ERR_PUT_error macro ignores file and line */ + UNUSED(file); + UNUSED(line); +# endif + UNUSED(funcname); + ERR_PUT_error(ERR_LIB_PKCS11, function, reason, file, line); +#endif /*ndef ERR_raise_data*/ +} + + +void +ERR_load_PKCS11_strings(void) { +#ifndef OPENSSL_NO_ERR +{ static int loaded = 0; + if (loaded) return; + loaded = 1; +} + if (ERR_LIB_PKCS11 == 0) + ERR_LIB_PKCS11 = ERR_get_next_error_library(); + + ERR_load_strings(ERR_LIB_PKCS11, PKCS11_str_functs); + ERR_load_strings(ERR_LIB_PKCS11, PKCS11_str_reasons); + + PKCS11_lib_name[0].error = ERR_PACK(ERR_LIB_PKCS11, 0, 0); + ERR_load_strings(0, PKCS11_lib_name); +#endif /*ndef OPENSSL_NO_ERR*/ +} + +#else /*def ENABLE_PKCS11*/ + +typedef int ssh_pkcs11_err_empty_translation_unit; + +#endif diff -ruN openssh-9.4p1/ssh-pkcs11.h openssh-9.4p1+x509-14.2.1/ssh-pkcs11.h --- openssh-9.4p1/ssh-pkcs11.h 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/ssh-pkcs11.h 2023-08-20 10:07:00.000000000 +0300 @@ -1,6 +1,9 @@ +#ifndef SSH_PKCS11_H +#define SSH_PKCS11_H /* $OpenBSD: ssh-pkcs11.h,v 1.6 2020/01/25 00:03:36 djm Exp $ */ /* * Copyright (c) 2010 Markus Friedl. All rights reserved. + * Copyright (c) 2018-2021 Roumen Petrov. All rights reserved. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -15,26 +18,297 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* Errors for pkcs11_add_provider() */ -#define SSH_PKCS11_ERR_GENERIC 1 -#define SSH_PKCS11_ERR_LOGIN_FAIL 2 -#define SSH_PKCS11_ERR_NO_SLOTS 3 -#define SSH_PKCS11_ERR_PIN_REQUIRED 4 -#define SSH_PKCS11_ERR_PIN_LOCKED 5 +#include "includes.h" int pkcs11_init(int); void pkcs11_terminate(void); + +#ifdef ENABLE_PKCS11 +#include "sshkey.h" +#include "evp-compat.h" + +#include /*for memset*/ + +/* Errors for pkcs11_add_provider() */ +#define SSH_PKCS11_ERR_GENERIC -1 +#define SSH_PKCS11_ERR_LOGIN_FAIL -2 +#define SSH_PKCS11_ERR_NO_SLOTS -3 +#define SSH_PKCS11_ERR_PIN_REQUIRED -4 +#define SSH_PKCS11_ERR_PIN_LOCKED -5 + int pkcs11_add_provider(char *, char *, struct sshkey ***, char ***); int pkcs11_del_provider(char *); -#ifdef WITH_PKCS11_KEYGEN -struct sshkey * - pkcs11_gakp(char *, char *, unsigned int, char *, unsigned int, - unsigned int, unsigned char, u_int32_t *); -struct sshkey * - pkcs11_destroy_keypair(char *, char *, unsigned long, unsigned char, - u_int32_t *); -#endif - -#if !defined(WITH_OPENSSL) && defined(ENABLE_PKCS11) -#undef ENABLE_PKCS11 -#endif + +/* crypto library errors */ +/* Function codes. */ +#define PKCS11_LOGIN 100 +#define PKCS11_REAUTHENTICATE 101 +#define PKCS11_RSA_PRIVATE_ENCRYPT 110 +#define PKCS11_DSA_DO_SIGN 111 +#define PKCS11_ECDSA_DO_SIGN 112 +#define PKCS11_GET_KEY 113 +/* Reason codes. */ +#define PKCS11_SIGNREQ_FAIL 100 +#define PKCS11_C_SIGNINIT_FAIL 101 +#define PKCS11_C_SIGN_FAIL 102 +#define PKCS11_C_LOGIN_FAIL 103 +#define PKCS11_FINDKEY_FAIL 104 + +void ERR_PKCS11_PUT_error(int function, int reason, char *file, int line, const char* funcname); +#define PKCS11err(f,r) ERR_PKCS11_PUT_error((f),(r),__FILE__,__LINE__, __func__) + +void ERR_load_PKCS11_strings(void); + + +/* Unlike OPENSSL_strdup (0.8.k+), BUF_strdup is defined in + * all OpenSSL versions (SSLeay 0.8.1) until 1.1.0. + * As is always available at run-time in compatible + * functions below it is preferred function. + * Used in compatible functions below only if OpenSSL < 1.1.0. + */ +#include /*for BUF_strdup*/ + + +#ifdef USE_RSA_METHOD +#ifndef HAVE_RSA_METH_NEW /* OpenSSL < 1.1 */ +/* Partial backport of opaque RSA from OpenSSL >= 1.1 by commits + * "Make the RSA_METHOD structure opaque", "RSA, DSA, DH: Allow some + * given input to be NULL on already initialised keys" and etc. + */ + +/* opaque RSA method structure */ +static inline RSA_METHOD* +RSA_meth_new(const char *name, int flags) { + RSA_METHOD *meth; + + meth = OPENSSL_malloc(sizeof(RSA_METHOD)); + if (meth == NULL) return NULL; + + memset(meth, 0, sizeof(*meth)); + meth->name = BUF_strdup(name); + meth->flags = flags; + + return(meth); +} + + +static inline void +RSA_meth_free(RSA_METHOD *meth) { + if (meth == NULL) return; + + if (meth->name != NULL) + OPENSSL_free((char*)meth->name); + OPENSSL_free(meth); +} + + +static inline RSA_METHOD* +RSA_meth_dup(const RSA_METHOD *meth) { + RSA_METHOD *ret; + + if (meth == NULL) return NULL; + + ret = OPENSSL_malloc(sizeof(RSA_METHOD)); + if (ret == NULL) return NULL; + + memcpy(ret, meth, sizeof(*meth)); + ret->name = BUF_strdup(meth->name); + + return(ret); +} +#endif /*ndef HAVE_RSA_METH_NEW*/ + + +#ifndef HAVE_RSA_METH_SET1_NAME +static inline int +RSA_meth_set1_name(RSA_METHOD *meth, const char *name) { + if (meth->name != NULL) + OPENSSL_free((char*)meth->name); + meth->name = BUF_strdup(name); + + return meth->name != NULL; +} +#endif /*ndef HAVE_RSA_METH_SET1_NAME*/ + + +#ifndef HAVE_RSA_METH_SET_PRIV_ENC +typedef int (*priv_enc_f) (int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding); + +static inline int +RSA_meth_set_priv_enc(RSA_METHOD *meth, priv_enc_f priv_enc) { + meth->rsa_priv_enc = priv_enc; + return 1; +} + + +typedef int (*priv_dec_f) (int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding); + +static inline int +RSA_meth_set_priv_dec(RSA_METHOD *meth, priv_dec_f priv_dec) { + meth->rsa_priv_dec = priv_dec; + return 1; +} +#endif /*ndef HAVE_RSA_METH_SET_PRIV_ENC*/ + + +#ifndef HAVE_RSA_METH_GET_PUB_ENC +typedef int (*pub_enc_f) (int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding); + +static inline pub_enc_f +RSA_meth_get_pub_enc(const RSA_METHOD *meth) { return meth->rsa_pub_enc; } + +static inline int +RSA_meth_set_pub_enc(RSA_METHOD *meth, pub_enc_f pub_enc) { + meth->rsa_pub_enc = pub_enc; + return 1; +} + + +typedef int (*pub_dec_f) (int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding); + +static inline pub_dec_f +RSA_meth_get_pub_dec(const RSA_METHOD *meth) { return meth->rsa_pub_dec; } + +static inline int +RSA_meth_set_pub_dec(RSA_METHOD *meth, pub_dec_f pub_dec) { + meth->rsa_pub_dec = pub_dec; + return 1; +} + + +typedef int (*rsa_mod_exp_f) (BIGNUM *r0, const BIGNUM *I, RSA *rsa, + BN_CTX *ctx); + +static inline rsa_mod_exp_f +RSA_meth_get_mod_exp(const RSA_METHOD *meth) { return meth->rsa_mod_exp; } + +static inline int +RSA_meth_set_mod_exp(RSA_METHOD *meth, rsa_mod_exp_f rsa_mod_exp ) { + meth->rsa_mod_exp = rsa_mod_exp; + return 1; +} + + +typedef int (*rsa_bn_mod_exp_f) (BIGNUM *r, const BIGNUM *a, + const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx, + BN_MONT_CTX *m_ctx); + +static inline rsa_bn_mod_exp_f +RSA_meth_get_bn_mod_exp(const RSA_METHOD *meth) { return meth->bn_mod_exp; } + +static inline int +RSA_meth_set_bn_mod_exp(RSA_METHOD *meth, rsa_bn_mod_exp_f bn_mod_exp) { + meth->bn_mod_exp = bn_mod_exp; + return 1; +} +#endif /*ndef HAVE_RSA_METH_GET_PUB_ENC*/ +#endif /*def USE_RSA_METHOD*/ + + +#ifdef OPENSSL_HAS_ECC +# ifndef HAVE_EC_KEY_METHOD_NEW /* OpenSSL < 1.1 */ +# include + + +#ifndef HAVE_ECDSA_METHOD_NEW /* OpenSSL < 1.0.2 */ + +#ifndef HAVE_ECDSA_METHOD_NAME +/*declared in some OpenSSL compatible headers*/ +struct ecdsa_method { + const char *name; + ECDSA_SIG *(*ecdsa_do_sign) (const unsigned char *dgst, int dgst_len, + const BIGNUM *inv, const BIGNUM *rp, + EC_KEY *eckey); + int (*ecdsa_sign_setup) (EC_KEY *eckey, BN_CTX *ctx, BIGNUM **kinv, + BIGNUM **r); + int (*ecdsa_do_verify) (const unsigned char *dgst, int dgst_len, + const ECDSA_SIG *sig, EC_KEY *eckey); +# if 0 + int (*init) (EC_KEY *eckey); + int (*finish) (EC_KEY *eckey); +# endif + int flags; + void *app_data; +}; +#endif /*ndef HAVE_ECDSA_METHOD_NAME*/ + + +static inline ECDSA_METHOD* +ECDSA_METHOD_new(const ECDSA_METHOD *ecdsa_method) +{ + UNUSED(ecdsa_method); + return OPENSSL_malloc(sizeof(ECDSA_METHOD)); +} + +static inline void +ECDSA_METHOD_free(ECDSA_METHOD *ecdsa_method) +{ + OPENSSL_free(ecdsa_method); +} + +static inline void +ECDSA_METHOD_set_sign( + ECDSA_METHOD *ecdsa_method, + ECDSA_SIG *(*ecdsa_do_sign) ( + const unsigned char *dgst, int dgst_len, + const BIGNUM *inv, const BIGNUM *rp, EC_KEY *eckey) +) { + ecdsa_method->ecdsa_do_sign = ecdsa_do_sign; +} +#endif /*ndef HAVE_ECDSA_METHOD_NEW OpenSSL < 1.0.2 */ + + +/* mimic some ECDSA functions in OpenSSL API v1.1 style */ +typedef ECDSA_METHOD EC_KEY_METHOD; + +static inline const EC_KEY_METHOD* +EC_KEY_OpenSSL(void) { + return /*ECDSA_METHOD*/ECDSA_OpenSSL(); +} + +static inline EC_KEY_METHOD* +EC_KEY_METHOD_new(const EC_KEY_METHOD *meth) { + return ECDSA_METHOD_new(/*ECDSA_METHOD*/meth); +} + +static inline void +EC_KEY_METHOD_free(EC_KEY_METHOD *meth) { + ECDSA_METHOD_free(/*ECDSA_METHOD*/meth); +} + +static inline int +EC_KEY_set_method(EC_KEY *key, const EC_KEY_METHOD *meth) { + return ECDSA_set_method(key, /*ECDSA_METHOD*/meth); +} + +/* NOTE: In OpenSSL 1.1 EC_KEY_get_ex_new_index(...) is define to + * CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_EC_KEY, ...) + */ +static inline int +EC_KEY_get_ex_new_index(long argl, void *argp, + CRYPTO_EX_new *new_func, + CRYPTO_EX_dup *dup_func, + CRYPTO_EX_free *free_func +) { + return ECDSA_get_ex_new_index(argl, argp, new_func, dup_func, free_func); +} + +static inline void* +EC_KEY_get_ex_data(const EC_KEY *key, int idx) { + return ECDSA_get_ex_data((EC_KEY *)key, idx); +} + +static inline int +EC_KEY_set_ex_data(EC_KEY *key, int idx, void *arg) { + return ECDSA_set_ex_data(key, idx, arg); +} + +# endif /*def HAVE_EC_KEY_METHOD_NEW*/ +#endif /*def OPENSSL_HAS_ECC*/ + +#endif /*def ENABLE_PKCS11*/ +#endif /*ndef SSH_PKCS11_H*/ diff -ruN openssh-9.4p1/ssh-pkcs11-helper.0 openssh-9.4p1+x509-14.2.1/ssh-pkcs11-helper.0 --- openssh-9.4p1/ssh-pkcs11-helper.0 2023-08-10 04:11:19.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/ssh-pkcs11-helper.0 2023-08-20 10:07:00.000000000 +0300 @@ -1,35 +1,31 @@ -SSH-PKCS11-HELPER(8) System Manager's Manual SSH-PKCS11-HELPER(8) +SSH-PKCS11-HELPER(8) BSD System Manager's Manual SSH-PKCS11-HELPER(8) NAME - ssh-pkcs11-helper M-bM-^@M-^S OpenSSH helper for PKCS#11 support + ssh-pkcs11-helper -- Helper for PKCS#11 support SYNOPSIS ssh-pkcs11-helper [-v] DESCRIPTION - ssh-pkcs11-helper is used by ssh(1), ssh-agent(1), and ssh-keygen(1) to - access keys provided by a PKCS#11 token. + ssh-pkcs11-helper is used by ssh-agent(1) to access keys provided by a + PKCS#11 token. - ssh-pkcs11-helper is not intended to be invoked directly by the user. + ssh-pkcs11-helper is not intended to be invoked by the user, but from + ssh-agent(1). A single option is supported: - -v Verbose mode. Causes ssh-pkcs11-helper to print debugging - messages about its progress. This is helpful in debugging - problems. Multiple -v options increase the verbosity. The - maximum is 3. - - Note that ssh(1), ssh-agent(1), and ssh-keygen(1) will - automatically pass the -v flag to ssh-pkcs11-helper when they - have themselves been placed in debug mode. + -v Verbose mode. Causes ssh-pkcs11-helper to print debugging mes- + sages about its progress. This is helpful in debugging problems. + Multiple -v options increase the verbosity. The maximum is 3. -SEE ALSO - ssh(1), ssh-agent(1), ssh-keygen(1) + Note that ssh-agent(1) will automatically pass the -v flag to + ssh-pkcs11-helper when it has itself been placed in debug mode. -HISTORY - ssh-pkcs11-helper first appeared in OpenBSD 4.7. +SEE ALSO + ssh(1), ssh-add(1), ssh-agent(1) AUTHORS Markus Friedl -OpenBSD 7.3 April 29, 2022 OpenBSD 7.3 +BSD 30 November 2019 BSD diff -ruN openssh-9.4p1/ssh-pkcs11-helper.8 openssh-9.4p1+x509-14.2.1/ssh-pkcs11-helper.8 --- openssh-9.4p1/ssh-pkcs11-helper.8 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/ssh-pkcs11-helper.8 2023-08-20 10:07:00.000000000 +0300 @@ -1,4 +1,4 @@ -.\" $OpenBSD: ssh-pkcs11-helper.8,v 1.7 2022/04/29 03:24:30 djm Exp $ +.\" $OpenBSD: ssh-pkcs11-helper.8,v 1.6 2019/11/30 07:07:59 jmc Exp $ .\" .\" Copyright (c) 2010 Markus Friedl. All rights reserved. .\" @@ -14,26 +14,32 @@ .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" -.Dd $Mdocdate: April 29 2022 $ +.\" Implement .Dd with the Mdocdate RCS keyword +.rn Dd xD +.de Dd +.ie \\$1$Mdocdate: \{\ +. xD \\$3 \\$2 \\$4 +.\} +.el .xD \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 +.. +.Dd $Mdocdate: November 30 2019 $ .Dt SSH-PKCS11-HELPER 8 .Os .Sh NAME .Nm ssh-pkcs11-helper -.Nd OpenSSH helper for PKCS#11 support +.Nd Helper for PKCS#11 support .Sh SYNOPSIS .Nm .Op Fl v .Sh DESCRIPTION .Nm is used by -.Xr ssh 1 , -.Xr ssh-agent 1 , -and -.Xr ssh-keygen 1 +.Xr ssh-agent 1 to access keys provided by a PKCS#11 token. .Pp .Nm -is not intended to be invoked directly by the user. +is not intended to be invoked by the user, but from +.Xr ssh-agent 1 . .Pp A single option is supported: .Bl -tag -width Ds @@ -49,23 +55,16 @@ The maximum is 3. .Pp Note that -.Xr ssh 1 , -.Xr ssh-agent 1 , -and -.Xr ssh-keygen 1 +.Xr ssh-agent 1 will automatically pass the .Fl v flag to .Nm -when they have themselves been placed in debug mode. +when it has itself been placed in debug mode. .El .Sh SEE ALSO .Xr ssh 1 , -.Xr ssh-agent 1 , -.Xr ssh-keygen 1 -.Sh HISTORY -.Nm -first appeared in -.Ox 4.7 . +.Xr ssh-add 1 , +.Xr ssh-agent 1 .Sh AUTHORS .An Markus Friedl Aq Mt markus@openbsd.org diff -ruN openssh-9.4p1/ssh-pkcs11-helper.c openssh-9.4p1+x509-14.2.1/ssh-pkcs11-helper.c --- openssh-9.4p1/ssh-pkcs11-helper.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/ssh-pkcs11-helper.c 2023-08-20 10:07:01.000000000 +0300 @@ -1,6 +1,8 @@ /* $OpenBSD: ssh-pkcs11-helper.c,v 1.26 2021/11/18 03:31:44 djm Exp $ */ /* * Copyright (c) 2010 Markus Friedl. All rights reserved. + * Copyright (c) 2011 Kenneth Robinette. All rights reserved. + * Copyright (c) 2016-2023 Roumen Petrov. All rights reserved. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -15,19 +17,38 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifndef USE_OPENSSL_PROVIDER +/* TODO: implement OpenSSL 4.0 API, as OpenSSL 3.* is quite nonfunctional */ +# define OPENSSL_SUPPRESS_DEPRECATED +#endif + #include "includes.h" +#ifdef ENABLE_PKCS11 /* implies WITH_OPENSSL */ + #include #ifdef HAVE_SYS_TIME_H # include #endif +#ifdef OPENSSL_HAS_ECC +# include +#endif + #include "openbsd-compat/sys-queue.h" #include #include #ifdef HAVE_POLL_H -#include +# include +#else +# ifdef HAVE_SYS_POLL_H +# include +# endif #endif #include #include @@ -37,20 +58,17 @@ #include "sshbuf.h" #include "log.h" #include "misc.h" -#include "sshkey.h" +#include "sshxkey.h" #include "authfd.h" #include "ssh-pkcs11.h" #include "ssherr.h" -#ifdef ENABLE_PKCS11 - -#ifdef WITH_OPENSSL - /* borrows code from sftp-server and ssh-agent */ struct pkcs11_keyinfo { struct sshkey *key; - char *providername, *label; + char *label; + char *providername; TAILQ_ENTRY(pkcs11_keyinfo) next; }; @@ -63,14 +81,14 @@ struct sshbuf *oqueue; static void -add_key(struct sshkey *k, char *name, char *label) +add_key(struct sshkey *k, char *label, char *name) { struct pkcs11_keyinfo *ki; ki = xcalloc(1, sizeof(*ki)); - ki->providername = xstrdup(name); ki->key = k; - ki->label = xstrdup(label); + ki->label = label; + ki->providername = xstrdup(name); TAILQ_INSERT_TAIL(&pkcs11_keylist, ki, next); } @@ -98,9 +116,8 @@ struct pkcs11_keyinfo *ki; TAILQ_FOREACH(ki, &pkcs11_keylist, next) { - debug("check %s %s %s", sshkey_type(ki->key), - ki->providername, ki->label); - if (sshkey_equal(k, ki->key)) + debug3("check '%s'-'%s'", ki->providername, ki->label); + if (sshkey_equal_public(k, ki->key)) return (ki->key); } return (NULL); @@ -119,12 +136,12 @@ process_add(void) { char *name, *pin; - struct sshkey **keys = NULL; + struct sshkey **keys; + char **labels; int r, i, nkeys; u_char *blob; size_t blen; struct sshbuf *msg; - char **labels = NULL; if ((msg = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); @@ -137,22 +154,22 @@ (r = sshbuf_put_u32(msg, nkeys)) != 0) fatal_fr(r, "compose"); for (i = 0; i < nkeys; i++) { - if ((r = sshkey_to_blob(keys[i], &blob, &blen)) != 0) { - debug_fr(r, "encode key"); + if ((r = Akey_to_blob(keys[i], &blob, &blen)) != 0) { + error_fr(r, "encode key"); continue; } if ((r = sshbuf_put_string(msg, blob, blen)) != 0 || (r = sshbuf_put_cstring(msg, labels[i])) != 0) fatal_fr(r, "compose key"); free(blob); - add_key(keys[i], name, labels[i]); - free(labels[i]); + add_key(keys[i], labels[i], name); } } else if ((r = sshbuf_put_u8(msg, SSH_AGENT_FAILURE)) != 0 || (r = sshbuf_put_u32(msg, -nkeys)) != 0) fatal_fr(r, "compose"); + /* keys and lebels themselves are transferred to pkcs11_keylist */ free(labels); - free(keys); /* keys themselves are transferred to pkcs11_keylist */ + free(keys); free(pin); free(name); send_msg(msg); @@ -181,6 +198,56 @@ sshbuf_free(msg); } +static int +process_key_sign( + u_int dlen, u_char *data, + struct sshkey *key, + u_char **signature, size_t *slen +) { + int ret; + + switch(key->type) { + case KEY_RSA: { + ret = EVP_PKEY_size(key->pk); + *signature = xmalloc(ret); + + { RSA *rsa = EVP_PKEY_get1_RSA(key->pk); + ret = RSA_private_encrypt(dlen, data, *signature, rsa, RSA_PKCS1_PADDING); + RSA_free(rsa); + } + if (ret != -1) { + *slen = ret; + ret = 0; + } + } break; +#ifdef OPENSSL_HAS_ECC + case KEY_ECDSA: { + ECDSA_SIG *sig = NULL; + + { EC_KEY *ec = EVP_PKEY_get1_EC_KEY(key->pk); + sig = ECDSA_do_sign(data, dlen, ec); + EC_KEY_free(ec); + } + if (sig == NULL) return (-1); + + /* encode ECDSA signature */ + ret = i2d_ECDSA_SIG(sig, signature); + if (ret > 0) { + *slen = ret; + ret = 0; + } else + ret = -1; + ECDSA_SIG_free(sig); + } break; +#endif /*def OPENSSL_HAS_ECC*/ + default: + ret = -1; + break; + } + + return (ret); +} + static void process_sign(void) { @@ -198,41 +265,14 @@ if ((r = sshkey_from_blob(blob, blen, &key)) != 0) fatal_fr(r, "decode key"); - else { - if ((found = lookup_key(key)) != NULL) { -#ifdef WITH_OPENSSL - int ret; - - if (key->type == KEY_RSA) { - slen = RSA_size(key->rsa); - signature = xmalloc(slen); - ret = RSA_private_encrypt(dlen, data, signature, - found->rsa, RSA_PKCS1_PADDING); - if (ret != -1) { - slen = ret; - ok = 0; - } -#ifdef OPENSSL_HAS_ECC - } else if (key->type == KEY_ECDSA) { - u_int xslen = ECDSA_size(key->ecdsa); - signature = xmalloc(xslen); - /* "The parameter type is ignored." */ - ret = ECDSA_sign(-1, data, dlen, signature, - &xslen, found->ecdsa); - if (ret != 0) - ok = 0; - else - error_f("ECDSA_sign returned %d", ret); - slen = xslen; -#endif /* OPENSSL_HAS_ECC */ - } else - error_f("don't know how to sign with key " - "type %d", (int)key->type); -#endif /* WITH_OPENSSL */ - } - sshkey_free(key); + if ((found = lookup_key(key)) != NULL) { + ok = process_key_sign(dlen, data, found, &signature, &slen); + if (ok != 0) + do_log_crypto_errors(SYSLOG_LEVEL_ERROR); } + sshkey_free(key); + if ((msg = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); if (ok == 0) { @@ -308,14 +348,6 @@ } } -void -cleanup_exit(int i) -{ - /* XXX */ - _exit(i); -} - - int main(int argc, char **argv) { @@ -327,6 +359,8 @@ extern char *__progname; struct pollfd pfd[2]; + (void)argc; + ssh_malloc_init(); /* must be called before any mallocs */ __progname = ssh_get_progname(argv[0]); seed_rng(); TAILQ_INIT(&pkcs11_keylist); @@ -337,7 +371,7 @@ switch (ch) { case 'v': log_stderr = 1; - if (log_level == SYSLOG_LEVEL_ERROR) + if (log_level < SYSLOG_LEVEL_DEBUG1) log_level = SYSLOG_LEVEL_DEBUG1; else if (log_level < SYSLOG_LEVEL_DEBUG3) log_level++; @@ -348,9 +382,12 @@ } } + ERR_load_PKCS11_strings(); + log_init(__progname, log_level, log_facility, log_stderr); pkcs11_init(0); + in = STDIN_FILENO; out = STDOUT_FILENO; @@ -390,7 +427,7 @@ if (len == 0) { debug("read eof"); cleanup_exit(0); - } else if (len < 0) { + } else if (len == -1) { error("read: %s", strerror(errno)); cleanup_exit(1); } else if ((r = sshbuf_put(iqueue, buf, len)) != 0) @@ -400,7 +437,7 @@ if ((pfd[1].revents & (POLLOUT|POLLHUP)) != 0) { len = write(out, sshbuf_ptr(oqueue), sshbuf_len(oqueue)); - if (len < 0) { + if (len == -1) { error("write: %s", strerror(errno)); cleanup_exit(1); } else if ((r = sshbuf_consume(oqueue, len)) != 0) @@ -418,27 +455,15 @@ fatal_fr(r, "reserve"); } } - -#else /* WITH_OPENSSL */ -void -cleanup_exit(int i) -{ - _exit(i); -} - -int -main(int argc, char **argv) -{ - fprintf(stderr, "PKCS#11 code is not enabled\n"); - return 1; -} -#endif /* WITH_OPENSSL */ #else /* ENABLE_PKCS11 */ +#include "log.h" + int main(int argc, char **argv) { extern char *__progname; + (void)argc; __progname = ssh_get_progname(argv[0]); log_init(__progname, SYSLOG_LEVEL_ERROR, SYSLOG_FACILITY_AUTH, 0); fatal("PKCS#11 support disabled at compile time"); diff -ruN openssh-9.4p1/ssh-prngd.c openssh-9.4p1+x509-14.2.1/ssh-prngd.c --- openssh-9.4p1/ssh-prngd.c 1970-01-01 02:00:00.000000000 +0200 +++ openssh-9.4p1+x509-14.2.1/ssh-prngd.c 2023-08-20 10:07:01.000000000 +0300 @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2021 Roumen Petrov. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* NOTE: + * Move prngd to compatibily library is not correct as the source is part of + * ssh functionality. It is not compatibily source. + * Also move adds cyclic dependency to atomicio. To avoid this lets keep + * prngd source as part of libssh and in same time to minimise source + * code differences. + */ +#include "openbsd-compat/port-prngd.c" diff -ruN openssh-9.4p1/ssh-pselect.c openssh-9.4p1+x509-14.2.1/ssh-pselect.c --- openssh-9.4p1/ssh-pselect.c 1970-01-01 02:00:00.000000000 +0200 +++ openssh-9.4p1+x509-14.2.1/ssh-pselect.c 2023-08-20 10:07:01.000000000 +0300 @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2021 Roumen Petrov. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* NOTE: + * Source of bsd-pselect.c adds cyclic dependency to some functions from + * libssh. To avoid this lets keep source as part of secsh code and in same + * time to minimise source code differences. + */ +#include "openbsd-compat/bsd-pselect.c" diff -ruN openssh-9.4p1/sshpty.c openssh-9.4p1+x509-14.2.1/sshpty.c --- openssh-9.4p1/sshpty.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/sshpty.c 2023-08-20 10:07:01.000000000 +0300 @@ -27,7 +27,6 @@ #endif #include #include -#include #include #include #ifdef HAVE_UTIL_H @@ -91,6 +90,8 @@ error("chown %.100s 0 0 failed: %.100s", tty, strerror(errno)); if (chmod(tty, (mode_t) 0666) == -1) error("chmod %.100s 0666 failed: %.100s", tty, strerror(errno)); +#else + UNUSED(tty); #endif /* !__APPLE_PRIVPTY__ && !HAVE_OPENPTY */ } @@ -117,14 +118,14 @@ * tty. */ fd = open(_PATH_TTY, O_RDWR | O_NOCTTY); - if (fd >= 0) { + if (fd != -1) { error("Failed to disconnect from controlling tty."); close(fd); } /* Make it our controlling tty. */ #ifdef TIOCSCTTY debug("Setting controlling tty using TIOCSCTTY."); - if (ioctl(*ttyfd, TIOCSCTTY, NULL) < 0) + if (ioctl(*ttyfd, TIOCSCTTY, NULL) == -1) error("ioctl(TIOCSCTTY): %.100s", strerror(errno)); #endif /* TIOCSCTTY */ #ifdef NEED_SETPGRP @@ -172,8 +173,6 @@ /* Determine the group to make the owner of the tty. */ grp = getgrnam("tty"); - if (grp == NULL) - debug("%s: no tty group", __func__); gid = (grp != NULL) ? grp->gr_gid : pw->pw_gid; mode = (grp != NULL) ? 0620 : 0600; @@ -224,7 +223,7 @@ #ifdef TIOCNOTTY int fd; - if ((fd = open(_PATH_TTY, O_RDWR | O_NOCTTY)) >= 0) { + if ((fd = open(_PATH_TTY, O_RDWR | O_NOCTTY)) != -1) { (void) ioctl(fd, TIOCNOTTY, NULL); close(fd); } diff -ruN openssh-9.4p1/ssh-rsa.c openssh-9.4p1+x509-14.2.1/ssh-rsa.c --- openssh-9.4p1/ssh-rsa.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/ssh-rsa.c 2023-08-20 10:07:01.000000000 +0300 @@ -1,6 +1,8 @@ /* $OpenBSD: ssh-rsa.c,v 1.79 2023/03/05 05:34:09 dtucker Exp $ */ /* * Copyright (c) 2000, 2003 Markus Friedl + * Copyright (c) 2011 Dr. Stephen Henson. All rights reserved. + * Copyright (c) 2011-2023 Roumen Petrov. All rights reserved. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -15,14 +17,23 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifndef USE_OPENSSL_PROVIDER +/* TODO: implement OpenSSL 4.0 API, as OpenSSL 3.* is quite nonfunctional */ +# define OPENSSL_SUPPRESS_DEPRECATED +#endif + #include "includes.h" #ifdef WITH_OPENSSL #include -#include -#include +#include "evp-compat.h" +#include #include #include @@ -30,466 +41,853 @@ #include "sshbuf.h" #include "ssherr.h" #define SSHKEY_INTERNAL -#include "sshkey.h" -#include "digest.h" +#include "sshxkey.h" +#include "xmalloc.h" #include "log.h" -#include "openbsd-compat/openssl-compat.h" -static int openssh_RSA_verify(int, u_char *, size_t, u_char *, size_t, RSA *); +struct ssh_rsa_alg_st { + const char *name; + const char *signame; + const int id; +}; -static u_int -ssh_rsa_size(const struct sshkey *key) -{ - const BIGNUM *rsa_n; +static struct ssh_rsa_alg_st +ssh_rsa_algs[] = { +#ifdef HAVE_EVP_SHA256 + { "rsa-sha2-256", "rsa-sha2-256", SSH_MD_RSA_SHA256 }, + { "rsa-sha2-512", "rsa-sha2-512", SSH_MD_RSA_SHA512 }, +#endif + { "ssh-rsa", "ssh-rsa", SSH_MD_RSA_SHA1 }, +#ifdef HAVE_EVP_SHA256 + { "rsa-sha2-256-cert-v01@openssh.com", "rsa-sha2-256", SSH_MD_RSA_SHA256 }, + { "rsa-sha2-512-cert-v01@openssh.com", "rsa-sha2-512", SSH_MD_RSA_SHA512 }, +#endif + { "ssh-rsa-cert-v01@openssh.com", "ssh-rsa", SSH_MD_RSA_SHA1 }, + { NULL, NULL, -1 } +}; - if (key->rsa == NULL) - return 0; - RSA_get0_key(key->rsa, &rsa_n, NULL, NULL); - return BN_num_bits(rsa_n); -} +static struct ssh_rsa_alg_st* ssh_rsa_alg_info(const char *alg); -static int -ssh_rsa_alloc(struct sshkey *k) -{ - if ((k->rsa = RSA_new()) == NULL) - return SSH_ERR_ALLOC_FAIL; - return 0; +struct ssh_rsa_alg_st* +ssh_rsa_alg_info(const char *alg) { + struct ssh_rsa_alg_st* p; + + if (alg == NULL || *alg == '\0') + return ssh_rsa_alg_info("ssh-rsa"); + + for (p = ssh_rsa_algs; p->name != NULL; p++) + if (strcmp(alg, p->name) == 0) + return p; + + return NULL; } -static void -ssh_rsa_cleanup(struct sshkey *k) -{ - RSA_free(k->rsa); - k->rsa = NULL; +/* global option overridable by configuration */ +int required_rsa_size = SSH_RSA_MINIMUM_MODULUS_SIZE; + +int +sshrsa_verify_length(int bits) { + return bits < required_rsa_size + ? SSH_ERR_KEY_LENGTH : 0; } + +#ifdef WITH_OPENSSL_4_0_API +/* TODO: new methods compatible with OpenSSL 4.0 API. + * Remark: OpenSSL 3* is too buggy - almost each release fail + * or crash in regression tests. + */ +#else +/* management of elementary RSA key */ + +#ifndef HAVE_RSA_GENERATE_KEY_EX /* OpenSSL < 0.9.8 */ static int -ssh_rsa_equal(const struct sshkey *a, const struct sshkey *b) +RSA_generate_key_ex(RSA *rsa, int bits, BIGNUM *bn_e, void *cb) { - const BIGNUM *rsa_e_a, *rsa_n_a; - const BIGNUM *rsa_e_b, *rsa_n_b; + RSA *new_rsa, tmp_rsa; + unsigned long e; - if (a->rsa == NULL || b->rsa == NULL) - return 0; - RSA_get0_key(a->rsa, &rsa_n_a, &rsa_e_a, NULL); - RSA_get0_key(b->rsa, &rsa_n_b, &rsa_e_b, NULL); - if (rsa_e_a == NULL || rsa_e_b == NULL) + if (cb != NULL) + fatal_f("callback args not supported"); + e = BN_get_word(bn_e); + if (e == 0xffffffffL) + fatal_f("value of e too large"); + new_rsa = RSA_generate_key(bits, e, NULL, NULL); + if (new_rsa == NULL) return 0; - if (rsa_n_a == NULL || rsa_n_b == NULL) + /* swap rsa/new_rsa then free new_rsa */ + tmp_rsa = *rsa; + *rsa = *new_rsa; + *new_rsa = tmp_rsa; + RSA_free(new_rsa); + return 1; +} +#endif + +#ifndef HAVE_RSA_GET0_KEY +/* opaque RSA key structure */ +static inline void +RSA_get0_key(const RSA *rsa, const BIGNUM **n, const BIGNUM **e, const BIGNUM **d) { + if (n != NULL) *n = rsa->n; + if (e != NULL) *e = rsa->e; + if (d != NULL) *d = rsa->d; +} + +static inline int +RSA_set0_key(RSA *rsa, BIGNUM *n, BIGNUM *e, BIGNUM *d) { +/* If the fields in r are NULL, the corresponding input parameters MUST + * be non-NULL for n and e. d may be left NULL (in case only the + * public key is used). + * + * It is an error to give the results from get0 on r as input + * parameters. + */ + if (n == rsa->n || e == rsa->e + || (rsa->d != NULL && d == rsa->d)) return 0; - if (BN_cmp(rsa_e_a, rsa_e_b) != 0) + + if (n != NULL) { BN_free(rsa->n); rsa->n = n; } + if (e != NULL) { BN_free(rsa->e); rsa->e = e; } + if (d != NULL) { BN_free(rsa->d); rsa->d = d; } + + return 1; +} + + +static inline void +RSA_get0_crt_params(const RSA *rsa, const BIGNUM **dmp1, const BIGNUM **dmq1, const BIGNUM **iqmp) { + if (dmp1 != NULL) *dmp1 = rsa->dmp1; + if (dmq1 != NULL) *dmq1 = rsa->dmq1; + if (iqmp != NULL) *iqmp = rsa->iqmp; +} + +static inline int +RSA_set0_crt_params(RSA *rsa, BIGNUM *dmp1, BIGNUM *dmq1, BIGNUM *iqmp) { +/* If the fields in r are NULL, the corresponding input parameters MUST + * be non-NULL. + * + * It is an error to give the results from get0 on r as input + * parameters. + */ + if (dmp1 == rsa->dmp1 || dmq1 == rsa->dmq1 || iqmp == rsa->iqmp) return 0; - if (BN_cmp(rsa_n_a, rsa_n_b) != 0) + + if (dmp1 != NULL) { BN_free(rsa->dmp1); rsa->dmp1 = dmp1; } + if (dmq1 != NULL) { BN_free(rsa->dmq1); rsa->dmq1 = dmq1; } + if (iqmp != NULL) { BN_free(rsa->iqmp); rsa->iqmp = iqmp; } + + return 1; +} + + +static inline void +RSA_get0_factors(const RSA *rsa, const BIGNUM **p, const BIGNUM **q) { + if (p != NULL) *p = rsa->p; + if (q != NULL) *q = rsa->q; +} + + +static inline int +RSA_set0_factors(RSA *rsa, BIGNUM *p, BIGNUM *q) { +/* If the fields in r are NULL, the corresponding input parameters MUST + * be non-NULL. + * + * It is an error to give the results from get0 on r as input + * parameters. + */ + if (p == rsa->p || q == rsa->q) return 0; + + if (p != NULL) { BN_free(rsa->p); rsa->p = p; } + if (q != NULL) { BN_free(rsa->q); rsa->q = q; } + return 1; } +#endif /* ndef HAVE_RSA_GET0_KEY */ + +#ifndef HAVE_EVP_PKEY_CMP /* OpenSSL < 0.9.8 */ +extern int /* see sshkey-crypto.c */ +ssh_EVP_PKEY_cmp_rsa(const EVP_PKEY *ka, const EVP_PKEY *kb); + +int +ssh_EVP_PKEY_cmp_rsa(const EVP_PKEY *ka, const EVP_PKEY *kb) { + int ret = -1; + RSA *a, *b; + const BIGNUM *a_n, *a_e; + const BIGNUM *b_n, *b_e; + + a = EVP_PKEY_get1_RSA((EVP_PKEY*)ka); + b = EVP_PKEY_get1_RSA((EVP_PKEY*)kb); + if (a == NULL || b == NULL) goto err; + + RSA_get0_key(a, &a_n, &a_e, NULL); + RSA_get0_key(b, &b_n, &b_e, NULL); + + ret = + BN_cmp(a_n, b_n) == 0 && + BN_cmp(a_e, b_e) == 0; + +err: + RSA_free(b); + RSA_free(a); + return ret; +} +#endif + static int -ssh_rsa_serialize_public(const struct sshkey *key, struct sshbuf *b, - enum sshkey_serialize_rep opts) -{ +sshkey_init_rsa_key(struct sshkey *key, BIGNUM *n, BIGNUM *e, BIGNUM *d) { + int r; + EVP_PKEY *pk = NULL; + RSA *rsa = NULL; + + pk = EVP_PKEY_new(); + if (pk == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto err; + } + rsa = RSA_new(); + if (rsa == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto err; + } + + if (!EVP_PKEY_set1_RSA(pk, rsa)) { + r = SSH_ERR_LIBCRYPTO_ERROR; + goto err; + } + + /* transfer to key must be last operation - + if fail then caller could free arguments */ + if (!RSA_set0_key(rsa, n, e, d)) { + r = SSH_ERR_LIBCRYPTO_ERROR; + goto err; + } + + /* success */ + key->pk = pk; + pk = NULL; + r = 0; + +err: + RSA_free(rsa); + EVP_PKEY_free(pk); + return r; +} + + +static int +sshkey_validate_rsa_pub(const RSA *rsa) { + int r; + const BIGNUM *n = NULL; + + RSA_get0_key(rsa, &n, NULL, NULL); + + r = sshrsa_verify_length(BN_num_bits(n)); + if (r != 0) return r; + + /* other checks ? */ + return 0; +} + +int +sshkey_validate_public_rsa(const struct sshkey *key) { int r; - const BIGNUM *rsa_n, *rsa_e; - if (key->rsa == NULL) + if (key == NULL) return SSH_ERR_INVALID_ARGUMENT; + +{ RSA *rsa = EVP_PKEY_get1_RSA(key->pk); + if (rsa == NULL) return SSH_ERR_INVALID_ARGUMENT; - RSA_get0_key(key->rsa, &rsa_n, &rsa_e, NULL); - if ((r = sshbuf_put_bignum2(b, rsa_e)) != 0 || - (r = sshbuf_put_bignum2(b, rsa_n)) != 0) - return r; + r = sshkey_validate_rsa_pub(rsa); + RSA_free(rsa); +} + return r; +} + + +extern int /* see sshkey-crypto.c */ +ssh_EVP_PKEY_complete_pub_rsa(EVP_PKEY *pk); +int +ssh_EVP_PKEY_complete_pub_rsa(EVP_PKEY *pk) { + int r; + RSA *rsa; + + rsa = EVP_PKEY_get1_RSA(pk); + if (rsa == NULL) + return SSH_ERR_INVALID_ARGUMENT; + + r = sshkey_validate_rsa_pub(rsa); + if (r != 0) goto err; + + if (RSA_blinding_on(rsa, NULL) != 1) { + r = SSH_ERR_LIBCRYPTO_ERROR; + goto err; + } + + /* success */ + r = 0; +err: + RSA_free(rsa); + return r; +} + + +static int +sshbuf_read_pub_rsa(struct sshbuf *buf, struct sshkey *key) { + int r; + BIGNUM *n = NULL, *e = NULL; + + if ((r = sshbuf_get_bignum2(buf, &e)) != 0 || + (r = sshbuf_get_bignum2(buf, &n)) != 0) + goto err; + + /* key attribute allocation */ + r = sshkey_init_rsa_key(key, n, e, NULL); + if (r != 0) goto err; + n = e = NULL; /* transferred */ + + r = ssh_EVP_PKEY_complete_pub_rsa(key->pk); + if (r != 0) goto err; + + /* success */ + SSHKEY_DUMP(key); return 0; + +err: + BN_clear_free(n); + BN_clear_free(e); + sshkey_clear_pkey(key); + return r; } static int -ssh_rsa_serialize_private(const struct sshkey *key, struct sshbuf *b, - enum sshkey_serialize_rep opts) -{ +sshbuf_write_pub_rsa(struct sshbuf *buf, const struct sshkey *key) { int r; - const BIGNUM *rsa_n, *rsa_e, *rsa_d, *rsa_iqmp, *rsa_p, *rsa_q; + const BIGNUM *n = NULL, *e = NULL; - RSA_get0_key(key->rsa, &rsa_n, &rsa_e, &rsa_d); - RSA_get0_factors(key->rsa, &rsa_p, &rsa_q); - RSA_get0_crt_params(key->rsa, NULL, NULL, &rsa_iqmp); + if (key->pk == NULL) + return SSH_ERR_INVALID_ARGUMENT; - if (!sshkey_is_cert(key)) { - /* Note: can't reuse ssh_rsa_serialize_public: e, n vs. n, e */ - if ((r = sshbuf_put_bignum2(b, rsa_n)) != 0 || - (r = sshbuf_put_bignum2(b, rsa_e)) != 0) - return r; - } - if ((r = sshbuf_put_bignum2(b, rsa_d)) != 0 || - (r = sshbuf_put_bignum2(b, rsa_iqmp)) != 0 || - (r = sshbuf_put_bignum2(b, rsa_p)) != 0 || - (r = sshbuf_put_bignum2(b, rsa_q)) != 0) +{ RSA *rsa = EVP_PKEY_get1_RSA(key->pk); + if (rsa == NULL) + return SSH_ERR_INVALID_ARGUMENT; + RSA_get0_key(rsa, &n, &e, NULL); + RSA_free(rsa); +} + if ((r = sshbuf_put_bignum2(buf, e)) != 0 || + (r = sshbuf_put_bignum2(buf, n)) != 0) return r; - return 0; } static int -ssh_rsa_generate(struct sshkey *k, int bits) -{ - RSA *private = NULL; - BIGNUM *f4 = NULL; - int ret = SSH_ERR_INTERNAL_ERROR; +sshbuf_read_pub_rsa_priv(struct sshbuf *buf, struct sshkey *key) { + int r; + BIGNUM *n = NULL, *e = NULL; - if (bits < SSH_RSA_MINIMUM_MODULUS_SIZE || - bits > SSHBUF_MAX_BIGNUM * 8) - return SSH_ERR_KEY_LENGTH; - if ((private = RSA_new()) == NULL || (f4 = BN_new()) == NULL) { - ret = SSH_ERR_ALLOC_FAIL; - goto out; - } - if (!BN_set_word(f4, RSA_F4) || - !RSA_generate_key_ex(private, bits, f4, NULL)) { - ret = SSH_ERR_LIBCRYPTO_ERROR; - goto out; - } - k->rsa = private; - private = NULL; - ret = 0; - out: - RSA_free(private); - BN_free(f4); - return ret; + if ((r = sshbuf_get_bignum2(buf, &n)) != 0 || + (r = sshbuf_get_bignum2(buf, &e)) != 0) + goto err; + + /* key attribute allocation */ + r = sshkey_init_rsa_key(key, n, e, NULL); + if (r != 0) goto err; + n = e = NULL; /* transferred */ + + r = ssh_EVP_PKEY_complete_pub_rsa(key->pk); + if (r != 0) goto err; + + /* success */ + SSHKEY_DUMP(key); + return 0; + +err: + BN_clear_free(n); + BN_clear_free(e); + sshkey_clear_pkey(key); + return r; } + +#ifndef BN_FLG_CONSTTIME +# define BN_FLG_CONSTTIME 0x0 /* OpenSSL < 0.9.8 */ +#endif + static int -ssh_rsa_copy_public(const struct sshkey *from, struct sshkey *to) +sshrsa_complete_crt_parameters(RSA *rsa, const BIGNUM *rsa_iqmp) { - const BIGNUM *rsa_n, *rsa_e; - BIGNUM *rsa_n_dup = NULL, *rsa_e_dup = NULL; - int r = SSH_ERR_INTERNAL_ERROR; - - RSA_get0_key(from->rsa, &rsa_n, &rsa_e, NULL); - if ((rsa_n_dup = BN_dup(rsa_n)) == NULL || - (rsa_e_dup = BN_dup(rsa_e)) == NULL) { + BN_CTX *ctx; + BIGNUM *aux = NULL, *d = NULL; + BIGNUM *dmq1 = NULL, *dmp1 = NULL, *iqmp = NULL; + int r; + + ctx = BN_CTX_new(); + if (ctx == NULL) + return SSH_ERR_ALLOC_FAIL; + if ((aux = BN_new()) == NULL || + (iqmp = BN_dup(rsa_iqmp)) == NULL || + (dmq1 = BN_new()) == NULL || + (dmp1 = BN_new()) == NULL) { r = SSH_ERR_ALLOC_FAIL; - goto out; + goto err; + } + BN_set_flags(aux, BN_FLG_CONSTTIME); + +{ const BIGNUM *p, *q; + RSA_get0_factors(rsa, &p, &q); + { const BIGNUM *key_d; + RSA_get0_key(rsa, NULL, NULL, &key_d); + if ((d = BN_dup(key_d)) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto err; + } + BN_set_flags(d, BN_FLG_CONSTTIME); } - if (!RSA_set0_key(to->rsa, rsa_n_dup, rsa_e_dup, NULL)) { + + if ((BN_sub(aux, q, BN_value_one()) == 0) || + (BN_mod(dmq1, d, aux, ctx) == 0) || + (BN_sub(aux, p, BN_value_one()) == 0) || + (BN_mod(dmp1, d, aux, ctx) == 0)) { r = SSH_ERR_LIBCRYPTO_ERROR; - goto out; + goto err; } - rsa_n_dup = rsa_e_dup = NULL; /* transferred */ +} + if (!RSA_set0_crt_params(rsa, dmp1, dmq1, iqmp)) { + r = SSH_ERR_LIBCRYPTO_ERROR; + goto err; + } + dmp1 = dmq1 = iqmp = NULL; /* transferred */ + /* success */ r = 0; - out: - BN_clear_free(rsa_n_dup); - BN_clear_free(rsa_e_dup); + +err: + BN_clear_free(aux); + BN_clear_free(d); + BN_clear_free(dmp1); + BN_clear_free(dmq1); + BN_clear_free(iqmp); + BN_CTX_free(ctx); return r; } + static int -ssh_rsa_deserialize_public(const char *ktype, struct sshbuf *b, - struct sshkey *key) -{ - int ret = SSH_ERR_INTERNAL_ERROR; - BIGNUM *rsa_n = NULL, *rsa_e = NULL; +sshbuf_write_pub_rsa_priv(struct sshbuf *buf, const struct sshkey *key) { + int r; + const BIGNUM *n = NULL, *e = NULL; - if (sshbuf_get_bignum2(b, &rsa_e) != 0 || - sshbuf_get_bignum2(b, &rsa_n) != 0) { - ret = SSH_ERR_INVALID_FORMAT; - goto out; +{ RSA *rsa = EVP_PKEY_get1_RSA(key->pk); + if (rsa == NULL) + return SSH_ERR_INVALID_ARGUMENT; + RSA_get0_key(rsa, &n, &e, NULL); + RSA_free(rsa); +} + if ((r = sshbuf_put_bignum2(buf, n)) != 0 || + (r = sshbuf_put_bignum2(buf, e)) != 0) + return r; + + return 0; +} + + +static int +sshbuf_read_priv_rsa(struct sshbuf *buf, struct sshkey *key) { + int r; + RSA *rsa = NULL; + BIGNUM *d = NULL, *iqmp = NULL, *p = NULL, *q = NULL; + + if ((r = sshbuf_get_bignum2(buf, &d)) != 0 || + (r = sshbuf_get_bignum2(buf, &iqmp)) != 0 || + (r = sshbuf_get_bignum2(buf, &p)) != 0 || + (r = sshbuf_get_bignum2(buf, &q)) != 0) + goto err; + + rsa = EVP_PKEY_get1_RSA(key->pk); + if (rsa == NULL) { + r = SSH_ERR_INVALID_ARGUMENT; + goto err; } - if (!RSA_set0_key(key->rsa, rsa_n, rsa_e, NULL)) { - ret = SSH_ERR_LIBCRYPTO_ERROR; - goto out; + + if (!RSA_set0_key(rsa, NULL, NULL, d)) { + r = SSH_ERR_LIBCRYPTO_ERROR; + goto err; } - rsa_n = rsa_e = NULL; /* transferred */ - if ((ret = sshkey_check_rsa_length(key, 0)) != 0) - goto out; -#ifdef DEBUG_PK - RSA_print_fp(stderr, key->rsa, 8); -#endif + d = NULL; /* transferred */ + + if (!RSA_set0_factors(rsa, p, q)) { + r = SSH_ERR_LIBCRYPTO_ERROR; + goto err; + } + p = q = NULL; /* transferred */ + + r = sshrsa_complete_crt_parameters(rsa, iqmp); + if (r != 0) goto err; + /* success */ - ret = 0; - out: - BN_clear_free(rsa_n); - BN_clear_free(rsa_e); - return ret; + SSHKEY_DUMP(key); + BN_clear_free(iqmp); + RSA_free(rsa); + return 0; + +err: + BN_clear_free(d); + BN_clear_free(p); + BN_clear_free(q); + BN_clear_free(iqmp); + RSA_free(rsa); + return r; } static int -ssh_rsa_deserialize_private(const char *ktype, struct sshbuf *b, - struct sshkey *key) -{ +sshbuf_write_priv_rsa(struct sshbuf *buf, const struct sshkey *key) { int r; - BIGNUM *rsa_n = NULL, *rsa_e = NULL, *rsa_d = NULL; - BIGNUM *rsa_iqmp = NULL, *rsa_p = NULL, *rsa_q = NULL; + const BIGNUM *d = NULL, *iqmp = NULL, *p = NULL, *q = NULL; - /* Note: can't reuse ssh_rsa_deserialize_public: e, n vs. n, e */ - if (!sshkey_is_cert(key)) { - if ((r = sshbuf_get_bignum2(b, &rsa_n)) != 0 || - (r = sshbuf_get_bignum2(b, &rsa_e)) != 0) - goto out; - if (!RSA_set0_key(key->rsa, rsa_n, rsa_e, NULL)) { - r = SSH_ERR_LIBCRYPTO_ERROR; - goto out; - } - rsa_n = rsa_e = NULL; /* transferred */ +{ RSA *rsa = EVP_PKEY_get1_RSA(key->pk); + if (rsa == NULL) + return SSH_ERR_INVALID_ARGUMENT; + RSA_get0_key(rsa, NULL, NULL, &d); + RSA_get0_crt_params(rsa, NULL, NULL, &iqmp); + RSA_get0_factors(rsa, &p, &q); + RSA_free(rsa); +} + if ((r = sshbuf_put_bignum2(buf, d)) != 0 || + (r = sshbuf_put_bignum2(buf, iqmp)) != 0 || + (r = sshbuf_put_bignum2(buf, p)) != 0 || + (r = sshbuf_put_bignum2(buf, q)) != 0) + return r; + + return 0; +} + + +extern int /* method used localy only in ssh-keygen.c */ +sshbuf_read_custom_rsa(struct sshbuf *buf, struct sshkey *key); + +int +sshbuf_read_custom_rsa(struct sshbuf *buf, struct sshkey *key) { + int r; + RSA *rsa = NULL; + BIGNUM *n = NULL, *e; + BIGNUM *d = NULL, *iqmp = NULL, *p = NULL, *q = NULL; + + e = BN_new(); + if (e == NULL) + return SSH_ERR_ALLOC_FAIL; + +{ BN_ULONG rsa_e; + u_char e1, e2, e3; + + if ((r = sshbuf_get_u8(buf, &e1)) != 0 || + (e1 < 30 && (r = sshbuf_get_u8(buf, &e2)) != 0) || + (e1 < 30 && (r = sshbuf_get_u8(buf, &e3)) != 0)) { + r = SSH_ERR_INVALID_FORMAT; + goto err; + } + + rsa_e = e1; + debug3("e %lx", (unsigned long)rsa_e); + if (rsa_e < 30) { + rsa_e <<= 8; + rsa_e += e2; + debug3("e %lx", (unsigned long)rsa_e); + rsa_e <<= 8; + rsa_e += e3; + debug3("e %lx", (unsigned long)rsa_e); } - if ((r = sshbuf_get_bignum2(b, &rsa_d)) != 0 || - (r = sshbuf_get_bignum2(b, &rsa_iqmp)) != 0 || - (r = sshbuf_get_bignum2(b, &rsa_p)) != 0 || - (r = sshbuf_get_bignum2(b, &rsa_q)) != 0) - goto out; - if (!RSA_set0_key(key->rsa, NULL, NULL, rsa_d)) { + + if (!BN_set_word(e, rsa_e)) { r = SSH_ERR_LIBCRYPTO_ERROR; - goto out; + goto err; } - rsa_d = NULL; /* transferred */ - if (!RSA_set0_factors(key->rsa, rsa_p, rsa_q)) { - r = SSH_ERR_LIBCRYPTO_ERROR; - goto out; +} + + if ((r = sshbuf_get_bignum1x(buf, &d)) != 0 || + (r = sshbuf_get_bignum1x(buf, &n)) != 0 || + (r = sshbuf_get_bignum1x(buf, &iqmp)) != 0 || + (r = sshbuf_get_bignum1x(buf, &q)) != 0 || + (r = sshbuf_get_bignum1x(buf, &p)) != 0) + goto err; + + /* key attribute allocation */ + r = sshkey_init_rsa_key(key, n, e, d); + if (r != 0) goto err; + n = e = d = NULL; /* transferred */ + + r = ssh_EVP_PKEY_complete_pub_rsa(key->pk); + if (r != 0) goto err; + + rsa = EVP_PKEY_get1_RSA(key->pk); + if (rsa == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto err; } - rsa_p = rsa_q = NULL; /* transferred */ - if ((r = sshkey_check_rsa_length(key, 0)) != 0) - goto out; - if ((r = ssh_rsa_complete_crt_parameters(key, rsa_iqmp)) != 0) - goto out; - if (RSA_blinding_on(key->rsa, NULL) != 1) { + + if (!RSA_set0_factors(rsa, p, q)) { r = SSH_ERR_LIBCRYPTO_ERROR; - goto out; + goto err; } + p = q = NULL; /* transferred */ + + r = sshrsa_complete_crt_parameters(rsa, iqmp); + if (r != 0) goto err; + /* success */ - r = 0; - out: - BN_clear_free(rsa_n); - BN_clear_free(rsa_e); - BN_clear_free(rsa_d); - BN_clear_free(rsa_p); - BN_clear_free(rsa_q); - BN_clear_free(rsa_iqmp); + key->type = KEY_RSA; + SSHKEY_DUMP(key); + BN_clear_free(iqmp); + RSA_free(rsa); + return 0; + +err: + BN_clear_free(n); + BN_clear_free(e); + BN_clear_free(d); + BN_clear_free(p); + BN_clear_free(q); + BN_clear_free(iqmp); + RSA_free(rsa); + sshkey_clear_pkey(key); return r; } +#endif /* def WITH_OPENSSL_3_1_API */ -static const char * -rsa_hash_alg_ident(int hash_alg) + +/* key implementation */ + +static u_int +ssh_rsa_size(const struct sshkey *key) { - switch (hash_alg) { - case SSH_DIGEST_SHA1: - return "ssh-rsa"; - case SSH_DIGEST_SHA256: - return "rsa-sha2-256"; - case SSH_DIGEST_SHA512: - return "rsa-sha2-512"; - } - return NULL; + return (key->pk != NULL) ? EVP_PKEY_bits(key->pk) : 0; } -/* - * Returns the hash algorithm ID for a given algorithm identifier as used - * inside the signature blob, - */ -static int -rsa_hash_id_from_ident(const char *ident) +static void +ssh_rsa_cleanup(struct sshkey *k) { - if (strcmp(ident, "ssh-rsa") == 0) - return SSH_DIGEST_SHA1; - if (strcmp(ident, "rsa-sha2-256") == 0) - return SSH_DIGEST_SHA256; - if (strcmp(ident, "rsa-sha2-512") == 0) - return SSH_DIGEST_SHA512; - return -1; + sshkey_clear_pkey(k); } -/* - * Return the hash algorithm ID for the specified key name. This includes - * all the cases of rsa_hash_id_from_ident() but also the certificate key - * types. - */ static int -rsa_hash_id_from_keyname(const char *alg) +ssh_rsa_equal(const struct sshkey *a, const struct sshkey *b) { - int r; + return sshkey_equal_public_pkey(a, b); +} - if ((r = rsa_hash_id_from_ident(alg)) != -1) - return r; - if (strcmp(alg, "ssh-rsa-cert-v01@openssh.com") == 0) - return SSH_DIGEST_SHA1; - if (strcmp(alg, "rsa-sha2-256-cert-v01@openssh.com") == 0) - return SSH_DIGEST_SHA256; - if (strcmp(alg, "rsa-sha2-512-cert-v01@openssh.com") == 0) - return SSH_DIGEST_SHA512; - return -1; +static int +ssh_rsa_serialize_public(const struct sshkey *key, struct sshbuf *buf, + enum sshkey_serialize_rep opts) +{ + UNUSED(opts); + return sshbuf_write_pub_rsa(buf, key); } static int -rsa_hash_alg_nid(int type) -{ - switch (type) { - case SSH_DIGEST_SHA1: - return NID_sha1; - case SSH_DIGEST_SHA256: - return NID_sha256; - case SSH_DIGEST_SHA512: - return NID_sha512; - default: - return -1; +ssh_rsa_serialize_private(const struct sshkey *key, struct sshbuf *buf, + enum sshkey_serialize_rep opts) +{ + int r; + + UNUSED(opts); + if (!sshkey_is_cert(key)) { + if ((r = sshbuf_write_pub_rsa_priv(buf, key)) != 0) + return r; } + return sshbuf_write_priv_rsa(buf, key); } -int -ssh_rsa_complete_crt_parameters(struct sshkey *key, const BIGNUM *iqmp) -{ - const BIGNUM *rsa_p, *rsa_q, *rsa_d; - BIGNUM *aux = NULL, *d_consttime = NULL; - BIGNUM *rsa_dmq1 = NULL, *rsa_dmp1 = NULL, *rsa_iqmp = NULL; - BN_CTX *ctx = NULL; +static int +ssh_rsa_generate(struct sshkey *key, int bits) { + EVP_PKEY *pk; + RSA *private = NULL; + BIGNUM *f4 = NULL; int r; - if (key == NULL || key->rsa == NULL || - sshkey_type_plain(key->type) != KEY_RSA) - return SSH_ERR_INVALID_ARGUMENT; + r = sshrsa_verify_length(bits); + if (r != 0) return r; - RSA_get0_key(key->rsa, NULL, NULL, &rsa_d); - RSA_get0_factors(key->rsa, &rsa_p, &rsa_q); + if (bits > SSHBUF_MAX_BIGNUM * 8) + return SSH_ERR_KEY_LENGTH; - if ((ctx = BN_CTX_new()) == NULL) - return SSH_ERR_ALLOC_FAIL; - if ((aux = BN_new()) == NULL || - (rsa_dmq1 = BN_new()) == NULL || - (rsa_dmp1 = BN_new()) == NULL) - return SSH_ERR_ALLOC_FAIL; - if ((d_consttime = BN_dup(rsa_d)) == NULL || - (rsa_iqmp = BN_dup(iqmp)) == NULL) { + ; + if ((pk = EVP_PKEY_new()) == NULL || + (private = RSA_new()) == NULL || + (f4 = BN_new()) == NULL + ) { r = SSH_ERR_ALLOC_FAIL; - goto out; + goto err; } - BN_set_flags(aux, BN_FLG_CONSTTIME); - BN_set_flags(d_consttime, BN_FLG_CONSTTIME); - - if ((BN_sub(aux, rsa_q, BN_value_one()) == 0) || - (BN_mod(rsa_dmq1, d_consttime, aux, ctx) == 0) || - (BN_sub(aux, rsa_p, BN_value_one()) == 0) || - (BN_mod(rsa_dmp1, d_consttime, aux, ctx) == 0)) { + if (!BN_set_word(f4, RSA_F4) || + !RSA_generate_key_ex(private, bits, f4, NULL)) { r = SSH_ERR_LIBCRYPTO_ERROR; - goto out; + goto err; } - if (!RSA_set0_crt_params(key->rsa, rsa_dmp1, rsa_dmq1, rsa_iqmp)) { + + if (!EVP_PKEY_set1_RSA(pk, private)) { r = SSH_ERR_LIBCRYPTO_ERROR; - goto out; + goto err; + } + + key->pk = pk; + pk = NULL; + +err: + EVP_PKEY_free(pk); + RSA_free(private); + BN_free(f4); + return r; +} + +static void +ssh_rsa_move_public(struct sshkey *from, struct sshkey *to) { + sshkey_move_pk(from, to); +} + +static int +ssh_rsa_copy_public(const struct sshkey *from, struct sshkey *to) { + int r; + BIGNUM *n = NULL, *e = NULL; + +{ RSA *rsa = EVP_PKEY_get1_RSA(from->pk); + const BIGNUM *k_n, *k_e; + + if (rsa == NULL) + return SSH_ERR_INVALID_ARGUMENT; + RSA_get0_key(rsa, &k_n, &k_e, NULL); + RSA_free(rsa); + + if ((n = BN_dup(k_n)) == NULL || + (e = BN_dup(k_e)) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto err; } - rsa_dmp1 = rsa_dmq1 = rsa_iqmp = NULL; /* transferred */ +} + + r = sshkey_init_rsa_key(to, n, e, NULL); + if (r != 0) goto err; + /* n = e = NULL; transferred */ + /* success */ - r = 0; - out: - BN_clear_free(aux); - BN_clear_free(d_consttime); - BN_clear_free(rsa_dmp1); - BN_clear_free(rsa_dmq1); - BN_clear_free(rsa_iqmp); - BN_CTX_free(ctx); + return 0; + +err: + BN_clear_free(n); + BN_clear_free(e); + sshkey_clear_pkey(to); return r; } -/* RSASSA-PKCS1-v1_5 (PKCS #1 v2.0 signature) with SHA1 */ static int -ssh_rsa_sign(struct sshkey *key, - u_char **sigp, size_t *lenp, - const u_char *data, size_t datalen, - const char *alg, const char *sk_provider, const char *sk_pin, u_int compat) -{ - const BIGNUM *rsa_n; - u_char digest[SSH_DIGEST_MAX_LENGTH], *sig = NULL; - size_t slen = 0; - u_int hlen, len; - int nid, hash_alg, ret = SSH_ERR_INTERNAL_ERROR; - struct sshbuf *b = NULL; +ssh_rsa_deserialize_public(const char *pkalg, struct sshbuf *buf, + struct sshkey *key) +{ + UNUSED(pkalg); + return sshbuf_read_pub_rsa(buf, key); +} + +static int +ssh_rsa_deserialize_private(const char *pkalg, struct sshbuf *buf, + struct sshkey *key) +{ + int r; + + UNUSED(pkalg); + if (!sshkey_is_cert(key)) { + if ((r = sshbuf_read_pub_rsa_priv(buf, key)) != 0) + return r; + } + return sshbuf_read_priv_rsa(buf, key); +} + +static int +ssh_rsa_sign(const ssh_sign_ctx *ctx, u_char **sigp, size_t *lenp, + const u_char *data, size_t datalen) +{ + const struct sshkey *key = ctx->key; + const ssh_evp_md *dgst; + size_t slen = 0, len; + struct ssh_rsa_alg_st *alg_info; + int ret; if (lenp != NULL) *lenp = 0; if (sigp != NULL) *sigp = NULL; - if (alg == NULL || strlen(alg) == 0) - hash_alg = SSH_DIGEST_SHA1; - else - hash_alg = rsa_hash_id_from_keyname(alg); - if (key == NULL || key->rsa == NULL || hash_alg == -1 || - sshkey_type_plain(key->type) != KEY_RSA) - return SSH_ERR_INVALID_ARGUMENT; - RSA_get0_key(key->rsa, &rsa_n, NULL, NULL); - if (BN_num_bits(rsa_n) < SSH_RSA_MINIMUM_MODULUS_SIZE) - return SSH_ERR_KEY_LENGTH; - slen = RSA_size(key->rsa); - if (slen <= 0 || slen > SSHBUF_MAX_BIGNUM) + alg_info = ssh_rsa_alg_info(ctx->alg); + if (alg_info == NULL) return SSH_ERR_INVALID_ARGUMENT; + debug3_f("alg=%s/%s", (ctx->alg != NULL ? ctx->alg : "(nil)"), alg_info->name); - /* hash the data */ - nid = rsa_hash_alg_nid(hash_alg); - if ((hlen = ssh_digest_bytes(hash_alg)) == 0) - return SSH_ERR_INTERNAL_ERROR; - if ((ret = ssh_digest_memory(hash_alg, data, datalen, - digest, sizeof(digest))) != 0) - goto out; + ret = sshkey_validate_public_rsa(key); + if (ret != 0) return ret; - if ((sig = malloc(slen)) == NULL) { - ret = SSH_ERR_ALLOC_FAIL; + dgst = ssh_evp_md_find(alg_info->id); + + slen = EVP_PKEY_size(key->pk); + debug3_f("slen=%ld", (long)slen); + +{ u_char sig[slen]; +#ifdef HAVE_EVP_DIGESTSIGNINIT /* OpenSSL >= 1.0 */ + /* NOTE: Function EVP_SignFinal() in OpenSSL before 1.0 does not + * return signature length if signature argument is NULL. + */ + if (ssh_pkey_sign(dgst, key->pk, NULL, &len, data, datalen) <= 0) { + ret = SSH_ERR_LIBCRYPTO_ERROR; goto out; } - - if (RSA_sign(nid, digest, hlen, sig, &len, key->rsa) != 1) { + /* paranoid check */ + if (len > slen) { + ret = SSH_ERR_INTERNAL_ERROR; + goto out; + } +#endif /*def HAVE_EVP_DIGESTSIGNINIT*/ + if (ssh_pkey_sign(dgst, key->pk, sig, &len, data, datalen) <= 0) { ret = SSH_ERR_LIBCRYPTO_ERROR; goto out; } + if (len < slen) { size_t diff = slen - len; memmove(sig + diff, sig, len); explicit_bzero(sig, diff); +#ifndef HAVE_EVP_DIGESTSIGNINIT } else if (len > slen) { ret = SSH_ERR_INTERNAL_ERROR; goto out; +#endif /*ndef HAVE_EVP_DIGESTSIGNINIT*/ } - /* encode signature */ - if ((b = sshbuf_new()) == NULL) { - ret = SSH_ERR_ALLOC_FAIL; - goto out; - } - if ((ret = sshbuf_put_cstring(b, rsa_hash_alg_ident(hash_alg))) != 0 || - (ret = sshbuf_put_string(b, sig, slen)) != 0) - goto out; - len = sshbuf_len(b); - if (sigp != NULL) { - if ((*sigp = malloc(len)) == NULL) { - ret = SSH_ERR_ALLOC_FAIL; - goto out; - } - memcpy(*sigp, sshbuf_ptr(b), len); - } - if (lenp != NULL) - *lenp = len; - ret = 0; + + ret = ssh_encode_signature(sigp, lenp, + alg_info->signame, sig, slen); +} out: - explicit_bzero(digest, sizeof(digest)); - freezero(sig, slen); - sshbuf_free(b); return ret; } static int -ssh_rsa_verify(const struct sshkey *key, +ssh_rsa_verify(const ssh_verify_ctx *ctx, const u_char *sig, size_t siglen, - const u_char *data, size_t dlen, const char *alg, u_int compat, - struct sshkey_sig_details **detailsp) + const u_char *data, size_t datalen) { - const BIGNUM *rsa_n; + const struct sshkey *key = ctx->key; + const ssh_evp_md *dgst; + const char *alg = ctx->alg; char *sigtype = NULL; - int hash_alg, want_alg, ret = SSH_ERR_INTERNAL_ERROR; - size_t len = 0, diff, modlen, hlen; + struct ssh_rsa_alg_st *alg_info; + int ret; + size_t len = 0, diff, modlen; struct sshbuf *b = NULL; - u_char digest[SSH_DIGEST_MAX_LENGTH], *osigblob, *sigblob = NULL; + u_char *osigblob, *sigblob = NULL; - if (key == NULL || key->rsa == NULL || - sshkey_type_plain(key->type) != KEY_RSA || - sig == NULL || siglen == 0) + if (sig == NULL || siglen == 0) return SSH_ERR_INVALID_ARGUMENT; - RSA_get0_key(key->rsa, &rsa_n, NULL, NULL); - if (BN_num_bits(rsa_n) < SSH_RSA_MINIMUM_MODULUS_SIZE) - return SSH_ERR_KEY_LENGTH; + + ret = sshkey_validate_public_rsa(key); + if (ret != 0) return ret; if ((b = sshbuf_from(sig, siglen)) == NULL) return SSH_ERR_ALLOC_FAIL; @@ -497,20 +895,25 @@ ret = SSH_ERR_INVALID_FORMAT; goto out; } - if ((hash_alg = rsa_hash_id_from_ident(sigtype)) == -1) { - ret = SSH_ERR_KEY_TYPE_MISMATCH; + /* algorithm for plain keys */ + alg_info = ssh_rsa_alg_info(sigtype); + if (alg_info == NULL) { + ret = SSH_ERR_INVALID_ARGUMENT; goto out; } + debug3_f("alg=%s/%s", (alg != NULL ? alg : "(nil)"), alg_info->name); /* - * Allow ssh-rsa-cert-v01 certs to generate SHA2 signatures for - * legacy reasons, but otherwise the signature type should match. + * For legacy reasons allow ssh-rsa-cert-v01 certs to accept SHA2 signatures + * but otherwise the signature algorithm should match. */ if (alg != NULL && strcmp(alg, "ssh-rsa-cert-v01@openssh.com") != 0) { - if ((want_alg = rsa_hash_id_from_keyname(alg)) == -1) { + struct ssh_rsa_alg_st *want_info; + want_info = ssh_rsa_alg_info(alg); + if (want_info == NULL) { ret = SSH_ERR_INVALID_ARGUMENT; goto out; } - if (hash_alg != want_alg) { + if (alg_info->id != want_info->id) { ret = SSH_ERR_SIGNATURE_INVALID; goto out; } @@ -523,8 +926,10 @@ ret = SSH_ERR_UNEXPECTED_TRAILING_DATA; goto out; } - /* RSA_verify expects a signature of RSA_size */ - modlen = RSA_size(key->rsa); + + dgst = ssh_evp_md_find(alg_info->id); + + modlen = EVP_PKEY_size(key->pk); if (len > modlen) { ret = SSH_ERR_KEY_BITS_MISMATCH; goto out; @@ -540,156 +945,33 @@ explicit_bzero(sigblob, diff); len = modlen; } - if ((hlen = ssh_digest_bytes(hash_alg)) == 0) { - ret = SSH_ERR_INTERNAL_ERROR; - goto out; + + if (ssh_pkey_verify(dgst, key->pk, + sigblob, len, data, datalen) <= 0) { + ret = SSH_ERR_SIGNATURE_INVALID; } - if ((ret = ssh_digest_memory(hash_alg, data, dlen, - digest, sizeof(digest))) != 0) - goto out; - ret = openssh_RSA_verify(hash_alg, digest, hlen, sigblob, len, - key->rsa); out: freezero(sigblob, len); free(sigtype); sshbuf_free(b); - explicit_bzero(digest, sizeof(digest)); - return ret; -} - -/* - * See: - * http://www.rsasecurity.com/rsalabs/pkcs/pkcs-1/ - * ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1.asn - */ - -/* - * id-sha1 OBJECT IDENTIFIER ::= { iso(1) identified-organization(3) - * oiw(14) secsig(3) algorithms(2) 26 } - */ -static const u_char id_sha1[] = { - 0x30, 0x21, /* type Sequence, length 0x21 (33) */ - 0x30, 0x09, /* type Sequence, length 0x09 */ - 0x06, 0x05, /* type OID, length 0x05 */ - 0x2b, 0x0e, 0x03, 0x02, 0x1a, /* id-sha1 OID */ - 0x05, 0x00, /* NULL */ - 0x04, 0x14 /* Octet string, length 0x14 (20), followed by sha1 hash */ -}; - -/* - * See http://csrc.nist.gov/groups/ST/crypto_apps_infra/csor/algorithms.html - * id-sha256 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) - * organization(1) gov(101) csor(3) nistAlgorithm(4) hashAlgs(2) - * id-sha256(1) } - */ -static const u_char id_sha256[] = { - 0x30, 0x31, /* type Sequence, length 0x31 (49) */ - 0x30, 0x0d, /* type Sequence, length 0x0d (13) */ - 0x06, 0x09, /* type OID, length 0x09 */ - 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, /* id-sha256 */ - 0x05, 0x00, /* NULL */ - 0x04, 0x20 /* Octet string, length 0x20 (32), followed by sha256 hash */ -}; - -/* - * See http://csrc.nist.gov/groups/ST/crypto_apps_infra/csor/algorithms.html - * id-sha512 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) - * organization(1) gov(101) csor(3) nistAlgorithm(4) hashAlgs(2) - * id-sha256(3) } - */ -static const u_char id_sha512[] = { - 0x30, 0x51, /* type Sequence, length 0x51 (81) */ - 0x30, 0x0d, /* type Sequence, length 0x0d (13) */ - 0x06, 0x09, /* type OID, length 0x09 */ - 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, /* id-sha512 */ - 0x05, 0x00, /* NULL */ - 0x04, 0x40 /* Octet string, length 0x40 (64), followed by sha512 hash */ -}; - -static int -rsa_hash_alg_oid(int hash_alg, const u_char **oidp, size_t *oidlenp) -{ - switch (hash_alg) { - case SSH_DIGEST_SHA1: - *oidp = id_sha1; - *oidlenp = sizeof(id_sha1); - break; - case SSH_DIGEST_SHA256: - *oidp = id_sha256; - *oidlenp = sizeof(id_sha256); - break; - case SSH_DIGEST_SHA512: - *oidp = id_sha512; - *oidlenp = sizeof(id_sha512); - break; - default: - return SSH_ERR_INVALID_ARGUMENT; - } - return 0; -} - -static int -openssh_RSA_verify(int hash_alg, u_char *hash, size_t hashlen, - u_char *sigbuf, size_t siglen, RSA *rsa) -{ - size_t rsasize = 0, oidlen = 0, hlen = 0; - int ret, len, oidmatch, hashmatch; - const u_char *oid = NULL; - u_char *decrypted = NULL; - - if ((ret = rsa_hash_alg_oid(hash_alg, &oid, &oidlen)) != 0) - return ret; - ret = SSH_ERR_INTERNAL_ERROR; - hlen = ssh_digest_bytes(hash_alg); - if (hashlen != hlen) { - ret = SSH_ERR_INVALID_ARGUMENT; - goto done; - } - rsasize = RSA_size(rsa); - if (rsasize <= 0 || rsasize > SSHBUF_MAX_BIGNUM || - siglen == 0 || siglen > rsasize) { - ret = SSH_ERR_INVALID_ARGUMENT; - goto done; - } - if ((decrypted = malloc(rsasize)) == NULL) { - ret = SSH_ERR_ALLOC_FAIL; - goto done; - } - if ((len = RSA_public_decrypt(siglen, sigbuf, decrypted, rsa, - RSA_PKCS1_PADDING)) < 0) { - ret = SSH_ERR_LIBCRYPTO_ERROR; - goto done; - } - if (len < 0 || (size_t)len != hlen + oidlen) { - ret = SSH_ERR_INVALID_FORMAT; - goto done; - } - oidmatch = timingsafe_bcmp(decrypted, oid, oidlen) == 0; - hashmatch = timingsafe_bcmp(decrypted + oidlen, hash, hlen) == 0; - if (!oidmatch || !hashmatch) { - ret = SSH_ERR_SIGNATURE_INVALID; - goto done; - } - ret = 0; -done: - freezero(decrypted, rsasize); return ret; } static const struct sshkey_impl_funcs sshkey_rsa_funcs = { /* .size = */ ssh_rsa_size, - /* .alloc = */ ssh_rsa_alloc, + /* .alloc = NULL, */ /* .cleanup = */ ssh_rsa_cleanup, /* .equal = */ ssh_rsa_equal, - /* .ssh_serialize_public = */ ssh_rsa_serialize_public, - /* .ssh_deserialize_public = */ ssh_rsa_deserialize_public, - /* .ssh_serialize_private = */ ssh_rsa_serialize_private, - /* .ssh_deserialize_private = */ ssh_rsa_deserialize_private, + /* .serialize_public = */ ssh_rsa_serialize_public, + /* .deserialize_public = */ ssh_rsa_deserialize_public, + /* .serialize_private = */ ssh_rsa_serialize_private, + /* .deserialize_private = */ ssh_rsa_deserialize_private, /* .generate = */ ssh_rsa_generate, + /* .move_public = */ ssh_rsa_move_public, /* .copy_public = */ ssh_rsa_copy_public, /* .sign = */ ssh_rsa_sign, - /* .verify = */ ssh_rsa_verify, + /* .verify = */ ssh_rsa_verify }; const struct sshkey_impl sshkey_rsa_impl = { @@ -701,7 +983,7 @@ /* .cert = */ 0, /* .sigonly = */ 0, /* .keybits = */ 0, - /* .funcs = */ &sshkey_rsa_funcs, + /* .funcs = */ &sshkey_rsa_funcs }; const struct sshkey_impl sshkey_rsa_cert_impl = { @@ -713,11 +995,10 @@ /* .cert = */ 1, /* .sigonly = */ 0, /* .keybits = */ 0, - /* .funcs = */ &sshkey_rsa_funcs, + /* .funcs = */ &sshkey_rsa_funcs }; -/* SHA2 signature algorithms */ - +#ifdef HAVE_EVP_SHA256 const struct sshkey_impl sshkey_rsa_sha256_impl = { /* .name = */ "rsa-sha2-256", /* .shortname = */ "RSA", @@ -727,7 +1008,7 @@ /* .cert = */ 0, /* .sigonly = */ 1, /* .keybits = */ 0, - /* .funcs = */ &sshkey_rsa_funcs, + /* .funcs = */ &sshkey_rsa_funcs }; const struct sshkey_impl sshkey_rsa_sha512_impl = { @@ -739,7 +1020,7 @@ /* .cert = */ 0, /* .sigonly = */ 1, /* .keybits = */ 0, - /* .funcs = */ &sshkey_rsa_funcs, + /* .funcs = */ &sshkey_rsa_funcs }; const struct sshkey_impl sshkey_rsa_sha256_cert_impl = { @@ -751,7 +1032,7 @@ /* .cert = */ 1, /* .sigonly = */ 1, /* .keybits = */ 0, - /* .funcs = */ &sshkey_rsa_funcs, + /* .funcs = */ &sshkey_rsa_funcs }; const struct sshkey_impl sshkey_rsa_sha512_cert_impl = { @@ -763,6 +1044,11 @@ /* .cert = */ 1, /* .sigonly = */ 1, /* .keybits = */ 0, - /* .funcs = */ &sshkey_rsa_funcs, + /* .funcs = */ &sshkey_rsa_funcs }; +#endif /*def HAVE_EVP_SHA256*/ +#else + +typedef int ssh_rsa_empty_translation_unit; + #endif /* WITH_OPENSSL */ diff -ruN openssh-9.4p1/sshsig.c openssh-9.4p1+x509-14.2.1/sshsig.c --- openssh-9.4p1/sshsig.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/sshsig.c 1970-01-01 02:00:00.000000000 +0200 @@ -1,1147 +0,0 @@ -/* $OpenBSD: sshsig.c,v 1.32 2023/04/06 03:56:02 djm Exp $ */ -/* - * Copyright (c) 2019 Google LLC - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include "includes.h" - -#include -#include -#include -#include -#include -#include - -#include "authfd.h" -#include "authfile.h" -#include "log.h" -#include "misc.h" -#include "sshbuf.h" -#include "sshsig.h" -#include "ssherr.h" -#include "sshkey.h" -#include "match.h" -#include "digest.h" - -#define SIG_VERSION 0x01 -#define MAGIC_PREAMBLE "SSHSIG" -#define MAGIC_PREAMBLE_LEN (sizeof(MAGIC_PREAMBLE) - 1) -#define BEGIN_SIGNATURE "-----BEGIN SSH SIGNATURE-----\n" -#define END_SIGNATURE "-----END SSH SIGNATURE-----" -#define RSA_SIGN_ALG "rsa-sha2-512" /* XXX maybe make configurable */ -#define RSA_SIGN_ALLOWED "rsa-sha2-512,rsa-sha2-256" -#define HASHALG_DEFAULT "sha512" /* XXX maybe make configurable */ -#define HASHALG_ALLOWED "sha256,sha512" - -int -sshsig_armor(const struct sshbuf *blob, struct sshbuf **out) -{ - struct sshbuf *buf = NULL; - int r = SSH_ERR_INTERNAL_ERROR; - - *out = NULL; - - if ((buf = sshbuf_new()) == NULL) { - error_f("sshbuf_new failed"); - r = SSH_ERR_ALLOC_FAIL; - goto out; - } - - if ((r = sshbuf_put(buf, BEGIN_SIGNATURE, - sizeof(BEGIN_SIGNATURE)-1)) != 0) { - error_fr(r, "sshbuf_putf"); - goto out; - } - - if ((r = sshbuf_dtob64(blob, buf, 1)) != 0) { - error_fr(r, "base64 encode signature"); - goto out; - } - - if ((r = sshbuf_put(buf, END_SIGNATURE, - sizeof(END_SIGNATURE)-1)) != 0 || - (r = sshbuf_put_u8(buf, '\n')) != 0) { - error_fr(r, "sshbuf_put"); - goto out; - } - /* success */ - *out = buf; - buf = NULL; /* transferred */ - r = 0; - out: - sshbuf_free(buf); - return r; -} - -int -sshsig_dearmor(struct sshbuf *sig, struct sshbuf **out) -{ - int r; - size_t eoffset = 0; - struct sshbuf *buf = NULL; - struct sshbuf *sbuf = NULL; - char *b64 = NULL; - - if ((sbuf = sshbuf_fromb(sig)) == NULL) { - error_f("sshbuf_fromb failed"); - return SSH_ERR_ALLOC_FAIL; - } - - if ((r = sshbuf_cmp(sbuf, 0, - BEGIN_SIGNATURE, sizeof(BEGIN_SIGNATURE)-1)) != 0) { - error("Couldn't parse signature: missing header"); - goto done; - } - - if ((r = sshbuf_consume(sbuf, sizeof(BEGIN_SIGNATURE)-1)) != 0) { - error_fr(r, "consume"); - goto done; - } - - if ((r = sshbuf_find(sbuf, 0, "\n" END_SIGNATURE, - sizeof("\n" END_SIGNATURE)-1, &eoffset)) != 0) { - error("Couldn't parse signature: missing footer"); - goto done; - } - - if ((r = sshbuf_consume_end(sbuf, sshbuf_len(sbuf)-eoffset)) != 0) { - error_fr(r, "consume"); - goto done; - } - - if ((b64 = sshbuf_dup_string(sbuf)) == NULL) { - error_f("sshbuf_dup_string failed"); - r = SSH_ERR_ALLOC_FAIL; - goto done; - } - - if ((buf = sshbuf_new()) == NULL) { - error_f("sshbuf_new() failed"); - r = SSH_ERR_ALLOC_FAIL; - goto done; - } - - if ((r = sshbuf_b64tod(buf, b64)) != 0) { - error_fr(r, "decode base64"); - goto done; - } - - /* success */ - *out = buf; - r = 0; - buf = NULL; /* transferred */ -done: - sshbuf_free(buf); - sshbuf_free(sbuf); - free(b64); - return r; -} - -static int -sshsig_wrap_sign(struct sshkey *key, const char *hashalg, - const char *sk_provider, const char *sk_pin, const struct sshbuf *h_message, - const char *sig_namespace, struct sshbuf **out, - sshsig_signer *signer, void *signer_ctx) -{ - int r; - size_t slen = 0; - u_char *sig = NULL; - struct sshbuf *blob = NULL; - struct sshbuf *tosign = NULL; - const char *sign_alg = NULL; - - if ((tosign = sshbuf_new()) == NULL || - (blob = sshbuf_new()) == NULL) { - error_f("sshbuf_new failed"); - r = SSH_ERR_ALLOC_FAIL; - goto done; - } - - if ((r = sshbuf_put(tosign, MAGIC_PREAMBLE, MAGIC_PREAMBLE_LEN)) != 0 || - (r = sshbuf_put_cstring(tosign, sig_namespace)) != 0 || - (r = sshbuf_put_string(tosign, NULL, 0)) != 0 || /* reserved */ - (r = sshbuf_put_cstring(tosign, hashalg)) != 0 || - (r = sshbuf_put_stringb(tosign, h_message)) != 0) { - error_fr(r, "assemble message to sign"); - goto done; - } - - /* If using RSA keys then default to a good signature algorithm */ - if (sshkey_type_plain(key->type) == KEY_RSA) - sign_alg = RSA_SIGN_ALG; - - if (signer != NULL) { - if ((r = signer(key, &sig, &slen, - sshbuf_ptr(tosign), sshbuf_len(tosign), - sign_alg, sk_provider, sk_pin, 0, signer_ctx)) != 0) { - error_r(r, "Couldn't sign message (signer)"); - goto done; - } - } else { - if ((r = sshkey_sign(key, &sig, &slen, - sshbuf_ptr(tosign), sshbuf_len(tosign), - sign_alg, sk_provider, sk_pin, 0)) != 0) { - error_r(r, "Couldn't sign message"); - goto done; - } - } - - if ((r = sshbuf_put(blob, MAGIC_PREAMBLE, MAGIC_PREAMBLE_LEN)) != 0 || - (r = sshbuf_put_u32(blob, SIG_VERSION)) != 0 || - (r = sshkey_puts(key, blob)) != 0 || - (r = sshbuf_put_cstring(blob, sig_namespace)) != 0 || - (r = sshbuf_put_string(blob, NULL, 0)) != 0 || /* reserved */ - (r = sshbuf_put_cstring(blob, hashalg)) != 0 || - (r = sshbuf_put_string(blob, sig, slen)) != 0) { - error_fr(r, "assemble signature object"); - goto done; - } - - if (out != NULL) { - *out = blob; - blob = NULL; - } - r = 0; -done: - free(sig); - sshbuf_free(blob); - sshbuf_free(tosign); - return r; -} - -/* Check preamble and version. */ -static int -sshsig_parse_preamble(struct sshbuf *buf) -{ - int r = SSH_ERR_INTERNAL_ERROR; - uint32_t sversion; - - if ((r = sshbuf_cmp(buf, 0, MAGIC_PREAMBLE, MAGIC_PREAMBLE_LEN)) != 0 || - (r = sshbuf_consume(buf, (sizeof(MAGIC_PREAMBLE)-1))) != 0 || - (r = sshbuf_get_u32(buf, &sversion)) != 0) { - error("Couldn't verify signature: invalid format"); - return r; - } - - if (sversion > SIG_VERSION) { - error("Signature version %lu is larger than supported " - "version %u", (unsigned long)sversion, SIG_VERSION); - return SSH_ERR_INVALID_FORMAT; - } - return 0; -} - -static int -sshsig_check_hashalg(const char *hashalg) -{ - if (hashalg == NULL || - match_pattern_list(hashalg, HASHALG_ALLOWED, 0) == 1) - return 0; - error_f("unsupported hash algorithm \"%.100s\"", hashalg); - return SSH_ERR_SIGN_ALG_UNSUPPORTED; -} - -static int -sshsig_peek_hashalg(struct sshbuf *signature, char **hashalgp) -{ - struct sshbuf *buf = NULL; - char *hashalg = NULL; - int r = SSH_ERR_INTERNAL_ERROR; - - if (hashalgp != NULL) - *hashalgp = NULL; - if ((buf = sshbuf_fromb(signature)) == NULL) - return SSH_ERR_ALLOC_FAIL; - if ((r = sshsig_parse_preamble(buf)) != 0) - goto done; - if ((r = sshbuf_get_string_direct(buf, NULL, NULL)) != 0 || - (r = sshbuf_get_string_direct(buf, NULL, NULL)) != 0 || - (r = sshbuf_get_string(buf, NULL, NULL)) != 0 || - (r = sshbuf_get_cstring(buf, &hashalg, NULL)) != 0 || - (r = sshbuf_get_string_direct(buf, NULL, NULL)) != 0) { - error_fr(r, "parse signature object"); - goto done; - } - - /* success */ - r = 0; - *hashalgp = hashalg; - hashalg = NULL; - done: - free(hashalg); - sshbuf_free(buf); - return r; -} - -static int -sshsig_wrap_verify(struct sshbuf *signature, const char *hashalg, - const struct sshbuf *h_message, const char *expect_namespace, - struct sshkey **sign_keyp, struct sshkey_sig_details **sig_details) -{ - int r = SSH_ERR_INTERNAL_ERROR; - struct sshbuf *buf = NULL, *toverify = NULL; - struct sshkey *key = NULL; - const u_char *sig; - char *got_namespace = NULL, *sigtype = NULL, *sig_hashalg = NULL; - size_t siglen; - - debug_f("verify message length %zu", sshbuf_len(h_message)); - if (sig_details != NULL) - *sig_details = NULL; - if (sign_keyp != NULL) - *sign_keyp = NULL; - - if ((toverify = sshbuf_new()) == NULL) { - error_f("sshbuf_new failed"); - r = SSH_ERR_ALLOC_FAIL; - goto done; - } - if ((r = sshbuf_put(toverify, MAGIC_PREAMBLE, - MAGIC_PREAMBLE_LEN)) != 0 || - (r = sshbuf_put_cstring(toverify, expect_namespace)) != 0 || - (r = sshbuf_put_string(toverify, NULL, 0)) != 0 || /* reserved */ - (r = sshbuf_put_cstring(toverify, hashalg)) != 0 || - (r = sshbuf_put_stringb(toverify, h_message)) != 0) { - error_fr(r, "assemble message to verify"); - goto done; - } - - if ((r = sshsig_parse_preamble(signature)) != 0) - goto done; - - if ((r = sshkey_froms(signature, &key)) != 0 || - (r = sshbuf_get_cstring(signature, &got_namespace, NULL)) != 0 || - (r = sshbuf_get_string(signature, NULL, NULL)) != 0 || - (r = sshbuf_get_cstring(signature, &sig_hashalg, NULL)) != 0 || - (r = sshbuf_get_string_direct(signature, &sig, &siglen)) != 0) { - error_fr(r, "parse signature object"); - goto done; - } - - if (sshbuf_len(signature) != 0) { - error("Signature contains trailing data"); - r = SSH_ERR_INVALID_FORMAT; - goto done; - } - - if (strcmp(expect_namespace, got_namespace) != 0) { - error("Couldn't verify signature: namespace does not match"); - debug_f("expected namespace \"%s\" received \"%s\"", - expect_namespace, got_namespace); - r = SSH_ERR_SIGNATURE_INVALID; - goto done; - } - if (strcmp(hashalg, sig_hashalg) != 0) { - error("Couldn't verify signature: hash algorithm mismatch"); - debug_f("expected algorithm \"%s\" received \"%s\"", - hashalg, sig_hashalg); - r = SSH_ERR_SIGNATURE_INVALID; - goto done; - } - /* Ensure that RSA keys use an acceptable signature algorithm */ - if (sshkey_type_plain(key->type) == KEY_RSA) { - if ((r = sshkey_get_sigtype(sig, siglen, &sigtype)) != 0) { - error_r(r, "Couldn't verify signature: unable to get " - "signature type"); - goto done; - } - if (match_pattern_list(sigtype, RSA_SIGN_ALLOWED, 0) != 1) { - error("Couldn't verify signature: unsupported RSA " - "signature algorithm %s", sigtype); - r = SSH_ERR_SIGN_ALG_UNSUPPORTED; - goto done; - } - } - if ((r = sshkey_verify(key, sig, siglen, sshbuf_ptr(toverify), - sshbuf_len(toverify), NULL, 0, sig_details)) != 0) { - error_r(r, "Signature verification failed"); - goto done; - } - - /* success */ - r = 0; - if (sign_keyp != NULL) { - *sign_keyp = key; - key = NULL; /* transferred */ - } -done: - free(got_namespace); - free(sigtype); - free(sig_hashalg); - sshbuf_free(buf); - sshbuf_free(toverify); - sshkey_free(key); - return r; -} - -static int -hash_buffer(const struct sshbuf *m, const char *hashalg, struct sshbuf **bp) -{ - char *hex, hash[SSH_DIGEST_MAX_LENGTH]; - int alg, r = SSH_ERR_INTERNAL_ERROR; - struct sshbuf *b = NULL; - - *bp = NULL; - memset(hash, 0, sizeof(hash)); - - if ((r = sshsig_check_hashalg(hashalg)) != 0) - return r; - if ((alg = ssh_digest_alg_by_name(hashalg)) == -1) { - error_f("can't look up hash algorithm %s", hashalg); - return SSH_ERR_INTERNAL_ERROR; - } - if ((r = ssh_digest_buffer(alg, m, hash, sizeof(hash))) != 0) { - error_fr(r, "ssh_digest_buffer"); - return r; - } - if ((hex = tohex(hash, ssh_digest_bytes(alg))) != NULL) { - debug3_f("final hash: %s", hex); - freezero(hex, strlen(hex)); - } - if ((b = sshbuf_new()) == NULL) { - r = SSH_ERR_ALLOC_FAIL; - goto out; - } - if ((r = sshbuf_put(b, hash, ssh_digest_bytes(alg))) != 0) { - error_fr(r, "sshbuf_put"); - goto out; - } - *bp = b; - b = NULL; /* transferred */ - /* success */ - r = 0; - out: - sshbuf_free(b); - explicit_bzero(hash, sizeof(hash)); - return r; -} - -int -sshsig_signb(struct sshkey *key, const char *hashalg, - const char *sk_provider, const char *sk_pin, - const struct sshbuf *message, const char *sig_namespace, - struct sshbuf **out, sshsig_signer *signer, void *signer_ctx) -{ - struct sshbuf *b = NULL; - int r = SSH_ERR_INTERNAL_ERROR; - - if (hashalg == NULL) - hashalg = HASHALG_DEFAULT; - if (out != NULL) - *out = NULL; - if ((r = hash_buffer(message, hashalg, &b)) != 0) { - error_fr(r, "hash buffer"); - goto out; - } - if ((r = sshsig_wrap_sign(key, hashalg, sk_provider, sk_pin, b, - sig_namespace, out, signer, signer_ctx)) != 0) - goto out; - /* success */ - r = 0; - out: - sshbuf_free(b); - return r; -} - -int -sshsig_verifyb(struct sshbuf *signature, const struct sshbuf *message, - const char *expect_namespace, struct sshkey **sign_keyp, - struct sshkey_sig_details **sig_details) -{ - struct sshbuf *b = NULL; - int r = SSH_ERR_INTERNAL_ERROR; - char *hashalg = NULL; - - if (sig_details != NULL) - *sig_details = NULL; - if (sign_keyp != NULL) - *sign_keyp = NULL; - if ((r = sshsig_peek_hashalg(signature, &hashalg)) != 0) - return r; - debug_f("signature made with hash \"%s\"", hashalg); - if ((r = hash_buffer(message, hashalg, &b)) != 0) { - error_fr(r, "hash buffer"); - goto out; - } - if ((r = sshsig_wrap_verify(signature, hashalg, b, expect_namespace, - sign_keyp, sig_details)) != 0) - goto out; - /* success */ - r = 0; - out: - sshbuf_free(b); - free(hashalg); - return r; -} - -static int -hash_file(int fd, const char *hashalg, struct sshbuf **bp) -{ - char *hex, rbuf[8192], hash[SSH_DIGEST_MAX_LENGTH]; - ssize_t n, total = 0; - struct ssh_digest_ctx *ctx = NULL; - int alg, oerrno, r = SSH_ERR_INTERNAL_ERROR; - struct sshbuf *b = NULL; - - *bp = NULL; - memset(hash, 0, sizeof(hash)); - - if ((r = sshsig_check_hashalg(hashalg)) != 0) - return r; - if ((alg = ssh_digest_alg_by_name(hashalg)) == -1) { - error_f("can't look up hash algorithm %s", hashalg); - return SSH_ERR_INTERNAL_ERROR; - } - if ((ctx = ssh_digest_start(alg)) == NULL) { - error_f("ssh_digest_start failed"); - return SSH_ERR_INTERNAL_ERROR; - } - for (;;) { - if ((n = read(fd, rbuf, sizeof(rbuf))) == -1) { - if (errno == EINTR || errno == EAGAIN) - continue; - oerrno = errno; - error_f("read: %s", strerror(errno)); - errno = oerrno; - r = SSH_ERR_SYSTEM_ERROR; - goto out; - } else if (n == 0) { - debug2_f("hashed %zu bytes", total); - break; /* EOF */ - } - total += (size_t)n; - if ((r = ssh_digest_update(ctx, rbuf, (size_t)n)) != 0) { - error_fr(r, "ssh_digest_update"); - goto out; - } - } - if ((r = ssh_digest_final(ctx, hash, sizeof(hash))) != 0) { - error_fr(r, "ssh_digest_final"); - goto out; - } - if ((hex = tohex(hash, ssh_digest_bytes(alg))) != NULL) { - debug3_f("final hash: %s", hex); - freezero(hex, strlen(hex)); - } - if ((b = sshbuf_new()) == NULL) { - r = SSH_ERR_ALLOC_FAIL; - goto out; - } - if ((r = sshbuf_put(b, hash, ssh_digest_bytes(alg))) != 0) { - error_fr(r, "sshbuf_put"); - goto out; - } - *bp = b; - b = NULL; /* transferred */ - /* success */ - r = 0; - out: - oerrno = errno; - sshbuf_free(b); - ssh_digest_free(ctx); - explicit_bzero(hash, sizeof(hash)); - errno = oerrno; - return r; -} - -int -sshsig_sign_fd(struct sshkey *key, const char *hashalg, - const char *sk_provider, const char *sk_pin, - int fd, const char *sig_namespace, struct sshbuf **out, - sshsig_signer *signer, void *signer_ctx) -{ - struct sshbuf *b = NULL; - int r = SSH_ERR_INTERNAL_ERROR; - - if (hashalg == NULL) - hashalg = HASHALG_DEFAULT; - if (out != NULL) - *out = NULL; - if ((r = hash_file(fd, hashalg, &b)) != 0) { - error_fr(r, "hash_file"); - return r; - } - if ((r = sshsig_wrap_sign(key, hashalg, sk_provider, sk_pin, b, - sig_namespace, out, signer, signer_ctx)) != 0) - goto out; - /* success */ - r = 0; - out: - sshbuf_free(b); - return r; -} - -int -sshsig_verify_fd(struct sshbuf *signature, int fd, - const char *expect_namespace, struct sshkey **sign_keyp, - struct sshkey_sig_details **sig_details) -{ - struct sshbuf *b = NULL; - int r = SSH_ERR_INTERNAL_ERROR; - char *hashalg = NULL; - - if (sig_details != NULL) - *sig_details = NULL; - if (sign_keyp != NULL) - *sign_keyp = NULL; - if ((r = sshsig_peek_hashalg(signature, &hashalg)) != 0) - return r; - debug_f("signature made with hash \"%s\"", hashalg); - if ((r = hash_file(fd, hashalg, &b)) != 0) { - error_fr(r, "hash_file"); - goto out; - } - if ((r = sshsig_wrap_verify(signature, hashalg, b, expect_namespace, - sign_keyp, sig_details)) != 0) - goto out; - /* success */ - r = 0; - out: - sshbuf_free(b); - free(hashalg); - return r; -} - -struct sshsigopt { - int ca; - char *namespaces; - uint64_t valid_after, valid_before; -}; - -struct sshsigopt * -sshsigopt_parse(const char *opts, const char *path, u_long linenum, - const char **errstrp) -{ - struct sshsigopt *ret; - int r; - char *opt; - const char *errstr = NULL; - - if ((ret = calloc(1, sizeof(*ret))) == NULL) - return NULL; - if (opts == NULL || *opts == '\0') - return ret; /* Empty options yields empty options :) */ - - while (*opts && *opts != ' ' && *opts != '\t') { - /* flag options */ - if ((r = opt_flag("cert-authority", 0, &opts)) != -1) { - ret->ca = 1; - } else if (opt_match(&opts, "namespaces")) { - if (ret->namespaces != NULL) { - errstr = "multiple \"namespaces\" clauses"; - goto fail; - } - ret->namespaces = opt_dequote(&opts, &errstr); - if (ret->namespaces == NULL) - goto fail; - } else if (opt_match(&opts, "valid-after")) { - if (ret->valid_after != 0) { - errstr = "multiple \"valid-after\" clauses"; - goto fail; - } - if ((opt = opt_dequote(&opts, &errstr)) == NULL) - goto fail; - if (parse_absolute_time(opt, &ret->valid_after) != 0 || - ret->valid_after == 0) { - free(opt); - errstr = "invalid \"valid-after\" time"; - goto fail; - } - free(opt); - } else if (opt_match(&opts, "valid-before")) { - if (ret->valid_before != 0) { - errstr = "multiple \"valid-before\" clauses"; - goto fail; - } - if ((opt = opt_dequote(&opts, &errstr)) == NULL) - goto fail; - if (parse_absolute_time(opt, &ret->valid_before) != 0 || - ret->valid_before == 0) { - free(opt); - errstr = "invalid \"valid-before\" time"; - goto fail; - } - free(opt); - } - /* - * Skip the comma, and move to the next option - * (or break out if there are no more). - */ - if (*opts == '\0' || *opts == ' ' || *opts == '\t') - break; /* End of options. */ - /* Anything other than a comma is an unknown option */ - if (*opts != ',') { - errstr = "unknown key option"; - goto fail; - } - opts++; - if (*opts == '\0') { - errstr = "unexpected end-of-options"; - goto fail; - } - } - /* final consistency check */ - if (ret->valid_after != 0 && ret->valid_before != 0 && - ret->valid_before <= ret->valid_after) { - errstr = "\"valid-before\" time is before \"valid-after\""; - goto fail; - } - /* success */ - return ret; - fail: - if (errstrp != NULL) - *errstrp = errstr; - sshsigopt_free(ret); - return NULL; -} - -void -sshsigopt_free(struct sshsigopt *opts) -{ - if (opts == NULL) - return; - free(opts->namespaces); - free(opts); -} - -static int -parse_principals_key_and_options(const char *path, u_long linenum, char *line, - const char *required_principal, char **principalsp, struct sshkey **keyp, - struct sshsigopt **sigoptsp) -{ - char *opts = NULL, *tmp, *cp, *principals = NULL; - const char *reason = NULL; - struct sshsigopt *sigopts = NULL; - struct sshkey *key = NULL; - int r = SSH_ERR_INTERNAL_ERROR; - - if (principalsp != NULL) - *principalsp = NULL; - if (sigoptsp != NULL) - *sigoptsp = NULL; - if (keyp != NULL) - *keyp = NULL; - - cp = line; - cp = cp + strspn(cp, " \t"); /* skip leading whitespace */ - if (*cp == '#' || *cp == '\0') - return SSH_ERR_KEY_NOT_FOUND; /* blank or all-comment line */ - - /* format: identity[,identity...] [option[,option...]] key */ - if ((tmp = strdelimw(&cp)) == NULL || cp == NULL) { - error("%s:%lu: invalid line", path, linenum); - r = SSH_ERR_INVALID_FORMAT; - goto out; - } - if ((principals = strdup(tmp)) == NULL) { - error_f("strdup failed"); - r = SSH_ERR_ALLOC_FAIL; - goto out; - } - /* - * Bail out early if we're looking for a particular principal and this - * line does not list it. - */ - if (required_principal != NULL) { - if (match_pattern_list(required_principal, - principals, 0) != 1) { - /* principal didn't match */ - r = SSH_ERR_KEY_NOT_FOUND; - goto out; - } - debug_f("%s:%lu: matched principal \"%s\"", - path, linenum, required_principal); - } - - if ((key = sshkey_new(KEY_UNSPEC)) == NULL) { - error_f("sshkey_new failed"); - r = SSH_ERR_ALLOC_FAIL; - goto out; - } - if (sshkey_read(key, &cp) != 0) { - /* no key? Check for options */ - opts = cp; - if (sshkey_advance_past_options(&cp) != 0) { - error("%s:%lu: invalid options", path, linenum); - r = SSH_ERR_INVALID_FORMAT; - goto out; - } - if (cp == NULL || *cp == '\0') { - error("%s:%lu: missing key", path, linenum); - r = SSH_ERR_INVALID_FORMAT; - goto out; - } - *cp++ = '\0'; - skip_space(&cp); - if (sshkey_read(key, &cp) != 0) { - error("%s:%lu: invalid key", path, linenum); - r = SSH_ERR_INVALID_FORMAT; - goto out; - } - } - debug3("%s:%lu: options %s", path, linenum, opts == NULL ? "" : opts); - if ((sigopts = sshsigopt_parse(opts, path, linenum, &reason)) == NULL) { - error("%s:%lu: bad options: %s", path, linenum, reason); - r = SSH_ERR_INVALID_FORMAT; - goto out; - } - /* success */ - if (principalsp != NULL) { - *principalsp = principals; - principals = NULL; /* transferred */ - } - if (sigoptsp != NULL) { - *sigoptsp = sigopts; - sigopts = NULL; /* transferred */ - } - if (keyp != NULL) { - *keyp = key; - key = NULL; /* transferred */ - } - r = 0; - out: - free(principals); - sshsigopt_free(sigopts); - sshkey_free(key); - return r; -} - -static int -cert_filter_principals(const char *path, u_long linenum, - char **principalsp, const struct sshkey *cert, uint64_t verify_time) -{ - char *cp, *oprincipals, *principals; - const char *reason; - struct sshbuf *nprincipals; - int r = SSH_ERR_INTERNAL_ERROR, success = 0; - u_int i; - - oprincipals = principals = *principalsp; - *principalsp = NULL; - - if ((nprincipals = sshbuf_new()) == NULL) { - r = SSH_ERR_ALLOC_FAIL; - goto out; - } - - while ((cp = strsep(&principals, ",")) != NULL && *cp != '\0') { - /* Check certificate validity */ - if ((r = sshkey_cert_check_authority(cert, 0, 1, 0, - verify_time, NULL, &reason)) != 0) { - debug("%s:%lu: principal \"%s\" not authorized: %s", - path, linenum, cp, reason); - continue; - } - /* Return all matching principal names from the cert */ - for (i = 0; i < cert->cert->nprincipals; i++) { - if (match_pattern(cert->cert->principals[i], cp)) { - if ((r = sshbuf_putf(nprincipals, "%s%s", - sshbuf_len(nprincipals) != 0 ? "," : "", - cert->cert->principals[i])) != 0) { - error_f("buffer error"); - goto out; - } - } - } - } - if (sshbuf_len(nprincipals) == 0) { - error("%s:%lu: no valid principals found", path, linenum); - r = SSH_ERR_KEY_CERT_INVALID; - goto out; - } - if ((principals = sshbuf_dup_string(nprincipals)) == NULL) { - error_f("buffer error"); - goto out; - } - /* success */ - success = 1; - *principalsp = principals; - out: - sshbuf_free(nprincipals); - free(oprincipals); - return success ? 0 : r; -} - -static int -check_allowed_keys_line(const char *path, u_long linenum, char *line, - const struct sshkey *sign_key, const char *principal, - const char *sig_namespace, uint64_t verify_time, char **principalsp) -{ - struct sshkey *found_key = NULL; - char *principals = NULL; - int r, success = 0; - const char *reason = NULL; - struct sshsigopt *sigopts = NULL; - char tvalid[64], tverify[64]; - - if (principalsp != NULL) - *principalsp = NULL; - - /* Parse the line */ - if ((r = parse_principals_key_and_options(path, linenum, line, - principal, &principals, &found_key, &sigopts)) != 0) { - /* error already logged */ - goto done; - } - - if (!sigopts->ca && sshkey_equal(found_key, sign_key)) { - /* Exact match of key */ - debug("%s:%lu: matched key", path, linenum); - } else if (sigopts->ca && sshkey_is_cert(sign_key) && - sshkey_equal_public(sign_key->cert->signature_key, found_key)) { - if (principal) { - /* Match certificate CA key with specified principal */ - if ((r = sshkey_cert_check_authority(sign_key, 0, 1, 0, - verify_time, principal, &reason)) != 0) { - error("%s:%lu: certificate not authorized: %s", - path, linenum, reason); - goto done; - } - debug("%s:%lu: matched certificate CA key", - path, linenum); - } else { - /* No principal specified - find all matching ones */ - if ((r = cert_filter_principals(path, linenum, - &principals, sign_key, verify_time)) != 0) { - /* error already displayed */ - debug_r(r, "%s:%lu: cert_filter_principals", - path, linenum); - goto done; - } - debug("%s:%lu: matched certificate CA key", - path, linenum); - } - } else { - /* Didn't match key */ - goto done; - } - - /* Check whether options preclude the use of this key */ - if (sigopts->namespaces != NULL && sig_namespace != NULL && - match_pattern_list(sig_namespace, sigopts->namespaces, 0) != 1) { - error("%s:%lu: key is not permitted for use in signature " - "namespace \"%s\"", path, linenum, sig_namespace); - goto done; - } - - /* check key time validity */ - format_absolute_time((uint64_t)verify_time, tverify, sizeof(tverify)); - if (sigopts->valid_after != 0 && - (uint64_t)verify_time < sigopts->valid_after) { - format_absolute_time(sigopts->valid_after, - tvalid, sizeof(tvalid)); - error("%s:%lu: key is not yet valid: " - "verify time %s < valid-after %s", path, linenum, - tverify, tvalid); - goto done; - } - if (sigopts->valid_before != 0 && - (uint64_t)verify_time > sigopts->valid_before) { - format_absolute_time(sigopts->valid_before, - tvalid, sizeof(tvalid)); - error("%s:%lu: key has expired: " - "verify time %s > valid-before %s", path, linenum, - tverify, tvalid); - goto done; - } - success = 1; - - done: - if (success && principalsp != NULL) { - *principalsp = principals; - principals = NULL; /* transferred */ - } - free(principals); - sshkey_free(found_key); - sshsigopt_free(sigopts); - return success ? 0 : SSH_ERR_KEY_NOT_FOUND; -} - -int -sshsig_check_allowed_keys(const char *path, const struct sshkey *sign_key, - const char *principal, const char *sig_namespace, uint64_t verify_time) -{ - FILE *f = NULL; - char *line = NULL; - size_t linesize = 0; - u_long linenum = 0; - int r = SSH_ERR_KEY_NOT_FOUND, oerrno; - - /* Check key and principal against file */ - if ((f = fopen(path, "r")) == NULL) { - oerrno = errno; - error("Unable to open allowed keys file \"%s\": %s", - path, strerror(errno)); - errno = oerrno; - return SSH_ERR_SYSTEM_ERROR; - } - - while (getline(&line, &linesize, f) != -1) { - linenum++; - r = check_allowed_keys_line(path, linenum, line, sign_key, - principal, sig_namespace, verify_time, NULL); - free(line); - line = NULL; - linesize = 0; - if (r == SSH_ERR_KEY_NOT_FOUND) - continue; - else if (r == 0) { - /* success */ - fclose(f); - return 0; - } else - break; - } - /* Either we hit an error parsing or we simply didn't find the key */ - fclose(f); - free(line); - return r; -} - -int -sshsig_find_principals(const char *path, const struct sshkey *sign_key, - uint64_t verify_time, char **principals) -{ - FILE *f = NULL; - char *line = NULL; - size_t linesize = 0; - u_long linenum = 0; - int r = SSH_ERR_KEY_NOT_FOUND, oerrno; - - if ((f = fopen(path, "r")) == NULL) { - oerrno = errno; - error("Unable to open allowed keys file \"%s\": %s", - path, strerror(errno)); - errno = oerrno; - return SSH_ERR_SYSTEM_ERROR; - } - - while (getline(&line, &linesize, f) != -1) { - linenum++; - r = check_allowed_keys_line(path, linenum, line, - sign_key, NULL, NULL, verify_time, principals); - free(line); - line = NULL; - linesize = 0; - if (r == SSH_ERR_KEY_NOT_FOUND) - continue; - else if (r == 0) { - /* success */ - fclose(f); - return 0; - } else - break; - } - free(line); - /* Either we hit an error parsing or we simply didn't find the key */ - if (ferror(f) != 0) { - oerrno = errno; - fclose(f); - error("Unable to read allowed keys file \"%s\": %s", - path, strerror(errno)); - errno = oerrno; - return SSH_ERR_SYSTEM_ERROR; - } - fclose(f); - return r; -} - -int -sshsig_match_principals(const char *path, const char *principal, - char ***principalsp, size_t *nprincipalsp) -{ - FILE *f = NULL; - char *found, *line = NULL, **principals = NULL, **tmp; - size_t i, nprincipals = 0, linesize = 0; - u_long linenum = 0; - int oerrno = 0, r, ret = 0; - - if (principalsp != NULL) - *principalsp = NULL; - if (nprincipalsp != NULL) - *nprincipalsp = 0; - - /* Check key and principal against file */ - if ((f = fopen(path, "r")) == NULL) { - oerrno = errno; - error("Unable to open allowed keys file \"%s\": %s", - path, strerror(errno)); - errno = oerrno; - return SSH_ERR_SYSTEM_ERROR; - } - - while (getline(&line, &linesize, f) != -1) { - linenum++; - /* Parse the line */ - if ((r = parse_principals_key_and_options(path, linenum, line, - principal, &found, NULL, NULL)) != 0) { - if (r == SSH_ERR_KEY_NOT_FOUND) - continue; - ret = r; - oerrno = errno; - break; /* unexpected error */ - } - if ((tmp = recallocarray(principals, nprincipals, - nprincipals + 1, sizeof(*principals))) == NULL) { - ret = SSH_ERR_ALLOC_FAIL; - free(found); - break; - } - principals = tmp; - principals[nprincipals++] = found; /* transferred */ - free(line); - line = NULL; - linesize = 0; - } - fclose(f); - - if (ret == 0) { - if (nprincipals == 0) - ret = SSH_ERR_KEY_NOT_FOUND; - if (principalsp != NULL) { - *principalsp = principals; - principals = NULL; /* transferred */ - } - if (nprincipalsp != 0) { - *nprincipalsp = nprincipals; - nprincipals = 0; - } - } - - for (i = 0; i < nprincipals; i++) - free(principals[i]); - free(principals); - - errno = oerrno; - return ret; -} - -int -sshsig_get_pubkey(struct sshbuf *signature, struct sshkey **pubkey) -{ - struct sshkey *pk = NULL; - int r = SSH_ERR_SIGNATURE_INVALID; - - if (pubkey == NULL) - return SSH_ERR_INTERNAL_ERROR; - if ((r = sshsig_parse_preamble(signature)) != 0) - return r; - if ((r = sshkey_froms(signature, &pk)) != 0) - return r; - - *pubkey = pk; - pk = NULL; - return 0; -} diff -ruN openssh-9.4p1/sshsig.h openssh-9.4p1+x509-14.2.1/sshsig.h --- openssh-9.4p1/sshsig.h 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/sshsig.h 1970-01-01 02:00:00.000000000 +0200 @@ -1,111 +0,0 @@ -/* $OpenBSD: sshsig.h,v 1.11 2021/11/27 07:14:46 djm Exp $ */ -/* - * Copyright (c) 2019 Google LLC - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#ifndef SSHSIG_H -#define SSHSIG_H - -struct sshbuf; -struct sshkey; -struct sshsigopt; -struct sshkey_sig_details; - -typedef int sshsig_signer(struct sshkey *, u_char **, size_t *, - const u_char *, size_t, const char *, const char *, const char *, - u_int, void *); - -/* Buffer-oriented API */ - -/* - * Creates a detached SSH signature for a given buffer. - * Returns 0 on success or a negative SSH_ERR_* error code on failure. - * out is populated with the detached signature, or NULL on failure. - */ -int sshsig_signb(struct sshkey *key, const char *hashalg, - const char *sk_provider, const char *sk_pin, const struct sshbuf *message, - const char *sig_namespace, struct sshbuf **out, - sshsig_signer *signer, void *signer_ctx); - -/* - * Verifies that a detached signature is valid and optionally returns key - * used to sign via argument. - * Returns 0 on success or a negative SSH_ERR_* error code on failure. - */ -int sshsig_verifyb(struct sshbuf *signature, - const struct sshbuf *message, const char *sig_namespace, - struct sshkey **sign_keyp, struct sshkey_sig_details **sig_details); - -/* File/FD-oriented API */ - -/* - * Creates a detached SSH signature for a given file. - * Returns 0 on success or a negative SSH_ERR_* error code on failure. - * out is populated with the detached signature, or NULL on failure. - */ -int sshsig_sign_fd(struct sshkey *key, const char *hashalg, - const char *sk_provider, const char *sk_pin, - int fd, const char *sig_namespace, - struct sshbuf **out, sshsig_signer *signer, void *signer_ctx); - -/* - * Verifies that a detached signature over a file is valid and optionally - * returns key used to sign via argument. - * Returns 0 on success or a negative SSH_ERR_* error code on failure. - */ -int sshsig_verify_fd(struct sshbuf *signature, int fd, - const char *sig_namespace, struct sshkey **sign_keyp, - struct sshkey_sig_details **sig_details); - -/* Utility functions */ - -/* - * Return a base64 encoded "ASCII armoured" version of a raw signature. - */ -int sshsig_armor(const struct sshbuf *blob, struct sshbuf **out); - -/* - * Decode a base64 encoded armoured signature to a raw signature. - */ -int sshsig_dearmor(struct sshbuf *sig, struct sshbuf **out); - -/* - * Checks whether a particular key/principal/namespace is permitted by - * an allowed_keys file. Returns 0 on success. - */ -int sshsig_check_allowed_keys(const char *path, const struct sshkey *sign_key, - const char *principal, const char *ns, uint64_t verify_time); - -/* Parse zero or more allowed_keys signature options */ -struct sshsigopt *sshsigopt_parse(const char *opts, - const char *path, u_long linenum, const char **errstrp); - -/* Free signature options */ -void sshsigopt_free(struct sshsigopt *opts); - -/* Get public key from signature */ -int sshsig_get_pubkey(struct sshbuf *signature, struct sshkey **pubkey); - -/* Find principal in allowed_keys file, given a sshkey. Returns - * 0 on success. - */ -int sshsig_find_principals(const char *path, const struct sshkey *sign_key, - uint64_t verify_time, char **principal); - -/* Find all principals in allowed_keys file matching *principal */ -int sshsig_match_principals(const char *path, - const char *principal, char ***principalsp, size_t *nprincipalsp); - -#endif /* SSHSIG_H */ diff -ruN openssh-9.4p1/ssh-sk.c openssh-9.4p1+x509-14.2.1/ssh-sk.c --- openssh-9.4p1/ssh-sk.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/ssh-sk.c 1970-01-01 02:00:00.000000000 +0200 @@ -1,879 +0,0 @@ -/* $OpenBSD: ssh-sk.c,v 1.40 2023/07/19 14:02:27 djm Exp $ */ -/* - * Copyright (c) 2019 Google LLC - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -/* #define DEBUG_SK 1 */ - -#include "includes.h" - -#ifdef ENABLE_SK - -#include -#include -#ifdef HAVE_STDINT_H -# include -#endif -#include -#include - -#if defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC) -#include -#include -#endif /* WITH_OPENSSL && OPENSSL_HAS_ECC */ - -#include "log.h" -#include "misc.h" -#include "sshbuf.h" -#include "sshkey.h" -#include "ssherr.h" -#include "digest.h" - -#include "ssh-sk.h" -#include "sk-api.h" -#include "crypto_api.h" - -/* - * Almost every use of OpenSSL in this file is for ECDSA-NISTP256. - * This is strictly a larger hammer than necessary, but it reduces changes - * with upstream. - */ -#ifndef OPENSSL_HAS_ECC -# undef WITH_OPENSSL -#endif - -struct sshsk_provider { - char *path; - void *dlhandle; - - /* Return the version of the middleware API */ - uint32_t (*sk_api_version)(void); - - /* Enroll a U2F key (private key generation) */ - int (*sk_enroll)(int alg, const uint8_t *challenge, - size_t challenge_len, const char *application, uint8_t flags, - const char *pin, struct sk_option **opts, - struct sk_enroll_response **enroll_response); - - /* Sign a challenge */ - int (*sk_sign)(int alg, const uint8_t *message, size_t message_len, - const char *application, - const uint8_t *key_handle, size_t key_handle_len, - uint8_t flags, const char *pin, struct sk_option **opts, - struct sk_sign_response **sign_response); - - /* Enumerate resident keys */ - int (*sk_load_resident_keys)(const char *pin, struct sk_option **opts, - struct sk_resident_key ***rks, size_t *nrks); -}; - -/* Built-in version */ -int ssh_sk_enroll(int alg, const uint8_t *challenge, - size_t challenge_len, const char *application, uint8_t flags, - const char *pin, struct sk_option **opts, - struct sk_enroll_response **enroll_response); -int ssh_sk_sign(int alg, const uint8_t *message, size_t message_len, - const char *application, - const uint8_t *key_handle, size_t key_handle_len, - uint8_t flags, const char *pin, struct sk_option **opts, - struct sk_sign_response **sign_response); -int ssh_sk_load_resident_keys(const char *pin, struct sk_option **opts, - struct sk_resident_key ***rks, size_t *nrks); - -static void -sshsk_free(struct sshsk_provider *p) -{ - if (p == NULL) - return; - free(p->path); - if (p->dlhandle != NULL) - dlclose(p->dlhandle); - free(p); -} - -static struct sshsk_provider * -sshsk_open(const char *path) -{ - struct sshsk_provider *ret = NULL; - uint32_t version; - - if (path == NULL || *path == '\0') { - error("No FIDO SecurityKeyProvider specified"); - return NULL; - } - if ((ret = calloc(1, sizeof(*ret))) == NULL) { - error_f("calloc failed"); - return NULL; - } - if ((ret->path = strdup(path)) == NULL) { - error_f("strdup failed"); - goto fail; - } - /* Skip the rest if we're using the linked in middleware */ - if (strcasecmp(ret->path, "internal") == 0) { -#ifdef ENABLE_SK_INTERNAL - ret->sk_enroll = ssh_sk_enroll; - ret->sk_sign = ssh_sk_sign; - ret->sk_load_resident_keys = ssh_sk_load_resident_keys; - return ret; -#else - error("internal security key support not enabled"); - goto fail; -#endif - } - if (lib_contains_symbol(path, "sk_api_version") != 0) { - error("provider %s is not an OpenSSH FIDO library", path); - goto fail; - } - if ((ret->dlhandle = dlopen(path, RTLD_NOW)) == NULL) - fatal("Provider \"%s\" dlopen failed: %s", path, dlerror()); - if ((ret->sk_api_version = dlsym(ret->dlhandle, - "sk_api_version")) == NULL) { - error("Provider \"%s\" dlsym(sk_api_version) failed: %s", - path, dlerror()); - goto fail; - } - version = ret->sk_api_version(); - debug_f("provider %s implements version 0x%08lx", ret->path, - (u_long)version); - if ((version & SSH_SK_VERSION_MAJOR_MASK) != SSH_SK_VERSION_MAJOR) { - error("Provider \"%s\" implements unsupported " - "version 0x%08lx (supported: 0x%08lx)", - path, (u_long)version, (u_long)SSH_SK_VERSION_MAJOR); - goto fail; - } - if ((ret->sk_enroll = dlsym(ret->dlhandle, "sk_enroll")) == NULL) { - error("Provider %s dlsym(sk_enroll) failed: %s", - path, dlerror()); - goto fail; - } - if ((ret->sk_sign = dlsym(ret->dlhandle, "sk_sign")) == NULL) { - error("Provider \"%s\" dlsym(sk_sign) failed: %s", - path, dlerror()); - goto fail; - } - if ((ret->sk_load_resident_keys = dlsym(ret->dlhandle, - "sk_load_resident_keys")) == NULL) { - error("Provider \"%s\" dlsym(sk_load_resident_keys) " - "failed: %s", path, dlerror()); - goto fail; - } - /* success */ - return ret; -fail: - sshsk_free(ret); - return NULL; -} - -static void -sshsk_free_enroll_response(struct sk_enroll_response *r) -{ - if (r == NULL) - return; - freezero(r->key_handle, r->key_handle_len); - freezero(r->public_key, r->public_key_len); - freezero(r->signature, r->signature_len); - freezero(r->attestation_cert, r->attestation_cert_len); - freezero(r->authdata, r->authdata_len); - freezero(r, sizeof(*r)); -} - -static void -sshsk_free_sign_response(struct sk_sign_response *r) -{ - if (r == NULL) - return; - freezero(r->sig_r, r->sig_r_len); - freezero(r->sig_s, r->sig_s_len); - freezero(r, sizeof(*r)); -} - -#ifdef WITH_OPENSSL -/* Assemble key from response */ -static int -sshsk_ecdsa_assemble(struct sk_enroll_response *resp, struct sshkey **keyp) -{ - struct sshkey *key = NULL; - struct sshbuf *b = NULL; - EC_POINT *q = NULL; - int r; - - *keyp = NULL; - if ((key = sshkey_new(KEY_ECDSA_SK)) == NULL) { - error_f("sshkey_new failed"); - r = SSH_ERR_ALLOC_FAIL; - goto out; - } - key->ecdsa_nid = NID_X9_62_prime256v1; - if ((key->ecdsa = EC_KEY_new_by_curve_name(key->ecdsa_nid)) == NULL || - (q = EC_POINT_new(EC_KEY_get0_group(key->ecdsa))) == NULL || - (b = sshbuf_new()) == NULL) { - error_f("allocation failed"); - r = SSH_ERR_ALLOC_FAIL; - goto out; - } - if ((r = sshbuf_put_string(b, - resp->public_key, resp->public_key_len)) != 0) { - error_fr(r, "sshbuf_put_string"); - goto out; - } - if ((r = sshbuf_get_ec(b, q, EC_KEY_get0_group(key->ecdsa))) != 0) { - error_fr(r, "parse"); - r = SSH_ERR_INVALID_FORMAT; - goto out; - } - if (sshkey_ec_validate_public(EC_KEY_get0_group(key->ecdsa), q) != 0) { - error("Authenticator returned invalid ECDSA key"); - r = SSH_ERR_KEY_INVALID_EC_VALUE; - goto out; - } - if (EC_KEY_set_public_key(key->ecdsa, q) != 1) { - /* XXX assume it is a allocation error */ - error_f("allocation failed"); - r = SSH_ERR_ALLOC_FAIL; - goto out; - } - /* success */ - *keyp = key; - key = NULL; /* transferred */ - r = 0; - out: - EC_POINT_free(q); - sshkey_free(key); - sshbuf_free(b); - return r; -} -#endif /* WITH_OPENSSL */ - -static int -sshsk_ed25519_assemble(struct sk_enroll_response *resp, struct sshkey **keyp) -{ - struct sshkey *key = NULL; - int r; - - *keyp = NULL; - if (resp->public_key_len != ED25519_PK_SZ) { - error_f("invalid size: %zu", resp->public_key_len); - r = SSH_ERR_INVALID_FORMAT; - goto out; - } - if ((key = sshkey_new(KEY_ED25519_SK)) == NULL) { - error_f("sshkey_new failed"); - r = SSH_ERR_ALLOC_FAIL; - goto out; - } - if ((key->ed25519_pk = malloc(ED25519_PK_SZ)) == NULL) { - error_f("malloc failed"); - r = SSH_ERR_ALLOC_FAIL; - goto out; - } - memcpy(key->ed25519_pk, resp->public_key, ED25519_PK_SZ); - /* success */ - *keyp = key; - key = NULL; /* transferred */ - r = 0; - out: - sshkey_free(key); - return r; -} - -static int -sshsk_key_from_response(int alg, const char *application, uint8_t flags, - struct sk_enroll_response *resp, struct sshkey **keyp) -{ - struct sshkey *key = NULL; - int r = SSH_ERR_INTERNAL_ERROR; - - *keyp = NULL; - - /* Check response validity */ - if (resp->public_key == NULL || resp->key_handle == NULL) { - error_f("sk_enroll response invalid"); - r = SSH_ERR_INVALID_FORMAT; - goto out; - } - switch (alg) { -#ifdef WITH_OPENSSL - case SSH_SK_ECDSA: - if ((r = sshsk_ecdsa_assemble(resp, &key)) != 0) - goto out; - break; -#endif /* WITH_OPENSSL */ - case SSH_SK_ED25519: - if ((r = sshsk_ed25519_assemble(resp, &key)) != 0) - goto out; - break; - default: - error_f("unsupported algorithm %d", alg); - r = SSH_ERR_INVALID_ARGUMENT; - goto out; - } - key->sk_flags = flags; - if ((key->sk_key_handle = sshbuf_new()) == NULL || - (key->sk_reserved = sshbuf_new()) == NULL) { - error_f("allocation failed"); - r = SSH_ERR_ALLOC_FAIL; - goto out; - } - if ((key->sk_application = strdup(application)) == NULL) { - error_f("strdup application failed"); - r = SSH_ERR_ALLOC_FAIL; - goto out; - } - if ((r = sshbuf_put(key->sk_key_handle, resp->key_handle, - resp->key_handle_len)) != 0) { - error_fr(r, "put key handle"); - goto out; - } - /* success */ - r = 0; - *keyp = key; - key = NULL; - out: - sshkey_free(key); - return r; -} - -static int -skerr_to_ssherr(int skerr) -{ - switch (skerr) { - case SSH_SK_ERR_UNSUPPORTED: - return SSH_ERR_FEATURE_UNSUPPORTED; - case SSH_SK_ERR_PIN_REQUIRED: - return SSH_ERR_KEY_WRONG_PASSPHRASE; - case SSH_SK_ERR_DEVICE_NOT_FOUND: - return SSH_ERR_DEVICE_NOT_FOUND; - case SSH_SK_ERR_CREDENTIAL_EXISTS: - return SSH_ERR_KEY_BAD_PERMISSIONS; - case SSH_SK_ERR_GENERAL: - default: - return SSH_ERR_INVALID_FORMAT; - } -} - -static void -sshsk_free_options(struct sk_option **opts) -{ - size_t i; - - if (opts == NULL) - return; - for (i = 0; opts[i] != NULL; i++) { - free(opts[i]->name); - free(opts[i]->value); - free(opts[i]); - } - free(opts); -} - -static int -sshsk_add_option(struct sk_option ***optsp, size_t *noptsp, - const char *name, const char *value, uint8_t required) -{ - struct sk_option **opts = *optsp; - size_t nopts = *noptsp; - - if ((opts = recallocarray(opts, nopts, nopts + 2, /* extra for NULL */ - sizeof(*opts))) == NULL) { - error_f("array alloc failed"); - return SSH_ERR_ALLOC_FAIL; - } - *optsp = opts; - *noptsp = nopts + 1; - if ((opts[nopts] = calloc(1, sizeof(**opts))) == NULL) { - error_f("alloc failed"); - return SSH_ERR_ALLOC_FAIL; - } - if ((opts[nopts]->name = strdup(name)) == NULL || - (opts[nopts]->value = strdup(value)) == NULL) { - error_f("alloc failed"); - return SSH_ERR_ALLOC_FAIL; - } - opts[nopts]->required = required; - return 0; -} - -static int -make_options(const char *device, const char *user_id, - struct sk_option ***optsp) -{ - struct sk_option **opts = NULL; - size_t nopts = 0; - int r, ret = SSH_ERR_INTERNAL_ERROR; - - if (device != NULL && - (r = sshsk_add_option(&opts, &nopts, "device", device, 0)) != 0) { - ret = r; - goto out; - } - if (user_id != NULL && - (r = sshsk_add_option(&opts, &nopts, "user", user_id, 0)) != 0) { - ret = r; - goto out; - } - /* success */ - *optsp = opts; - opts = NULL; - nopts = 0; - ret = 0; - out: - sshsk_free_options(opts); - return ret; -} - - -static int -fill_attestation_blob(const struct sk_enroll_response *resp, - struct sshbuf *attest) -{ - int r; - - if (attest == NULL) - return 0; /* nothing to do */ - if ((r = sshbuf_put_cstring(attest, "ssh-sk-attest-v01")) != 0 || - (r = sshbuf_put_string(attest, - resp->attestation_cert, resp->attestation_cert_len)) != 0 || - (r = sshbuf_put_string(attest, - resp->signature, resp->signature_len)) != 0 || - (r = sshbuf_put_string(attest, - resp->authdata, resp->authdata_len)) != 0 || - (r = sshbuf_put_u32(attest, 0)) != 0 || /* resvd flags */ - (r = sshbuf_put_string(attest, NULL, 0)) != 0 /* resvd */) { - error_fr(r, "compose"); - return r; - } - /* success */ - return 0; -} - -int -sshsk_enroll(int type, const char *provider_path, const char *device, - const char *application, const char *userid, uint8_t flags, - const char *pin, struct sshbuf *challenge_buf, - struct sshkey **keyp, struct sshbuf *attest) -{ - struct sshsk_provider *skp = NULL; - struct sshkey *key = NULL; - u_char randchall[32]; - const u_char *challenge; - size_t challenge_len; - struct sk_enroll_response *resp = NULL; - struct sk_option **opts = NULL; - int r = SSH_ERR_INTERNAL_ERROR; - int alg; - - debug_f("provider \"%s\", device \"%s\", application \"%s\", " - "userid \"%s\", flags 0x%02x, challenge len %zu%s", - provider_path, device, application, userid, flags, - challenge_buf == NULL ? 0 : sshbuf_len(challenge_buf), - (pin != NULL && *pin != '\0') ? " with-pin" : ""); - - *keyp = NULL; - if (attest) - sshbuf_reset(attest); - - if ((r = make_options(device, userid, &opts)) != 0) - goto out; - - switch (type) { -#ifdef WITH_OPENSSL - case KEY_ECDSA_SK: - alg = SSH_SK_ECDSA; - break; -#endif /* WITH_OPENSSL */ - case KEY_ED25519_SK: - alg = SSH_SK_ED25519; - break; - default: - error_f("unsupported key type"); - r = SSH_ERR_INVALID_ARGUMENT; - goto out; - } - if (provider_path == NULL) { - error_f("missing provider"); - r = SSH_ERR_INVALID_ARGUMENT; - goto out; - } - if (application == NULL || *application == '\0') { - error_f("missing application"); - r = SSH_ERR_INVALID_ARGUMENT; - goto out; - } - if (challenge_buf == NULL) { - debug_f("using random challenge"); - arc4random_buf(randchall, sizeof(randchall)); - challenge = randchall; - challenge_len = sizeof(randchall); - } else if (sshbuf_len(challenge_buf) == 0) { - error("Missing enrollment challenge"); - r = SSH_ERR_INVALID_ARGUMENT; - goto out; - } else { - challenge = sshbuf_ptr(challenge_buf); - challenge_len = sshbuf_len(challenge_buf); - debug3_f("using explicit challenge len=%zd", challenge_len); - } - if ((skp = sshsk_open(provider_path)) == NULL) { - r = SSH_ERR_INVALID_FORMAT; /* XXX sshsk_open return code? */ - goto out; - } - /* XXX validate flags? */ - /* enroll key */ - if ((r = skp->sk_enroll(alg, challenge, challenge_len, application, - flags, pin, opts, &resp)) != 0) { - debug_f("provider \"%s\" failure %d", provider_path, r); - r = skerr_to_ssherr(r); - goto out; - } - - if ((r = sshsk_key_from_response(alg, application, resp->flags, - resp, &key)) != 0) - goto out; - - /* Optionally fill in the attestation information */ - if ((r = fill_attestation_blob(resp, attest)) != 0) - goto out; - - /* success */ - *keyp = key; - key = NULL; /* transferred */ - r = 0; - out: - sshsk_free_options(opts); - sshsk_free(skp); - sshkey_free(key); - sshsk_free_enroll_response(resp); - explicit_bzero(randchall, sizeof(randchall)); - return r; -} - -#ifdef WITH_OPENSSL -static int -sshsk_ecdsa_sig(struct sk_sign_response *resp, struct sshbuf *sig) -{ - struct sshbuf *inner_sig = NULL; - int r = SSH_ERR_INTERNAL_ERROR; - - /* Check response validity */ - if (resp->sig_r == NULL || resp->sig_s == NULL) { - error_f("sk_sign response invalid"); - r = SSH_ERR_INVALID_FORMAT; - goto out; - } - if ((inner_sig = sshbuf_new()) == NULL) { - r = SSH_ERR_ALLOC_FAIL; - goto out; - } - /* Prepare and append inner signature object */ - if ((r = sshbuf_put_bignum2_bytes(inner_sig, - resp->sig_r, resp->sig_r_len)) != 0 || - (r = sshbuf_put_bignum2_bytes(inner_sig, - resp->sig_s, resp->sig_s_len)) != 0) { - error_fr(r, "compose inner"); - goto out; - } - if ((r = sshbuf_put_stringb(sig, inner_sig)) != 0 || - (r = sshbuf_put_u8(sig, resp->flags)) != 0 || - (r = sshbuf_put_u32(sig, resp->counter)) != 0) { - error_fr(r, "compose"); - goto out; - } -#ifdef DEBUG_SK - fprintf(stderr, "%s: sig_r:\n", __func__); - sshbuf_dump_data(resp->sig_r, resp->sig_r_len, stderr); - fprintf(stderr, "%s: sig_s:\n", __func__); - sshbuf_dump_data(resp->sig_s, resp->sig_s_len, stderr); - fprintf(stderr, "%s: inner:\n", __func__); - sshbuf_dump(inner_sig, stderr); -#endif - r = 0; - out: - sshbuf_free(inner_sig); - return r; -} -#endif /* WITH_OPENSSL */ - -static int -sshsk_ed25519_sig(struct sk_sign_response *resp, struct sshbuf *sig) -{ - int r = SSH_ERR_INTERNAL_ERROR; - - /* Check response validity */ - if (resp->sig_r == NULL) { - error_f("sk_sign response invalid"); - r = SSH_ERR_INVALID_FORMAT; - goto out; - } - if ((r = sshbuf_put_string(sig, - resp->sig_r, resp->sig_r_len)) != 0 || - (r = sshbuf_put_u8(sig, resp->flags)) != 0 || - (r = sshbuf_put_u32(sig, resp->counter)) != 0) { - error_fr(r, "compose"); - goto out; - } -#ifdef DEBUG_SK - fprintf(stderr, "%s: sig_r:\n", __func__); - sshbuf_dump_data(resp->sig_r, resp->sig_r_len, stderr); -#endif - r = 0; - out: - return r; -} - -int -sshsk_sign(const char *provider_path, struct sshkey *key, - u_char **sigp, size_t *lenp, const u_char *data, size_t datalen, - u_int compat, const char *pin) -{ - struct sshsk_provider *skp = NULL; - int r = SSH_ERR_INTERNAL_ERROR; - int type, alg; - struct sk_sign_response *resp = NULL; - struct sshbuf *inner_sig = NULL, *sig = NULL; - struct sk_option **opts = NULL; - - debug_f("provider \"%s\", key %s, flags 0x%02x%s", - provider_path, sshkey_type(key), key->sk_flags, - (pin != NULL && *pin != '\0') ? " with-pin" : ""); - - if (sigp != NULL) - *sigp = NULL; - if (lenp != NULL) - *lenp = 0; - type = sshkey_type_plain(key->type); - switch (type) { -#ifdef WITH_OPENSSL - case KEY_ECDSA_SK: - alg = SSH_SK_ECDSA; - break; -#endif /* WITH_OPENSSL */ - case KEY_ED25519_SK: - alg = SSH_SK_ED25519; - break; - default: - return SSH_ERR_INVALID_ARGUMENT; - } - if (provider_path == NULL || - key->sk_key_handle == NULL || - key->sk_application == NULL || *key->sk_application == '\0') { - r = SSH_ERR_INVALID_ARGUMENT; - goto out; - } - if ((skp = sshsk_open(provider_path)) == NULL) { - r = SSH_ERR_INVALID_FORMAT; /* XXX sshsk_open return code? */ - goto out; - } -#ifdef DEBUG_SK - fprintf(stderr, "%s: sk_flags = 0x%02x, sk_application = \"%s\"\n", - __func__, key->sk_flags, key->sk_application); - fprintf(stderr, "%s: sk_key_handle:\n", __func__); - sshbuf_dump(key->sk_key_handle, stderr); -#endif - if ((r = skp->sk_sign(alg, data, datalen, key->sk_application, - sshbuf_ptr(key->sk_key_handle), sshbuf_len(key->sk_key_handle), - key->sk_flags, pin, opts, &resp)) != 0) { - debug_f("sk_sign failed with code %d", r); - r = skerr_to_ssherr(r); - goto out; - } - /* Assemble signature */ - if ((sig = sshbuf_new()) == NULL) { - r = SSH_ERR_ALLOC_FAIL; - goto out; - } - if ((r = sshbuf_put_cstring(sig, sshkey_ssh_name_plain(key))) != 0) { - error_fr(r, "compose outer"); - goto out; - } - switch (type) { -#ifdef WITH_OPENSSL - case KEY_ECDSA_SK: - if ((r = sshsk_ecdsa_sig(resp, sig)) != 0) - goto out; - break; -#endif /* WITH_OPENSSL */ - case KEY_ED25519_SK: - if ((r = sshsk_ed25519_sig(resp, sig)) != 0) - goto out; - break; - } -#ifdef DEBUG_SK - fprintf(stderr, "%s: sig_flags = 0x%02x, sig_counter = %u\n", - __func__, resp->flags, resp->counter); - fprintf(stderr, "%s: data to sign:\n", __func__); - sshbuf_dump_data(data, datalen, stderr); - fprintf(stderr, "%s: sigbuf:\n", __func__); - sshbuf_dump(sig, stderr); -#endif - if (sigp != NULL) { - if ((*sigp = malloc(sshbuf_len(sig))) == NULL) { - r = SSH_ERR_ALLOC_FAIL; - goto out; - } - memcpy(*sigp, sshbuf_ptr(sig), sshbuf_len(sig)); - } - if (lenp != NULL) - *lenp = sshbuf_len(sig); - /* success */ - r = 0; - out: - sshsk_free_options(opts); - sshsk_free(skp); - sshsk_free_sign_response(resp); - sshbuf_free(sig); - sshbuf_free(inner_sig); - return r; -} - -static void -sshsk_free_sk_resident_keys(struct sk_resident_key **rks, size_t nrks) -{ - size_t i; - - if (nrks == 0 || rks == NULL) - return; - for (i = 0; i < nrks; i++) { - free(rks[i]->application); - freezero(rks[i]->user_id, rks[i]->user_id_len); - freezero(rks[i]->key.key_handle, rks[i]->key.key_handle_len); - freezero(rks[i]->key.public_key, rks[i]->key.public_key_len); - freezero(rks[i]->key.signature, rks[i]->key.signature_len); - freezero(rks[i]->key.attestation_cert, - rks[i]->key.attestation_cert_len); - freezero(rks[i], sizeof(**rks)); - } - free(rks); -} - -static void -sshsk_free_resident_key(struct sshsk_resident_key *srk) -{ - if (srk == NULL) - return; - sshkey_free(srk->key); - freezero(srk->user_id, srk->user_id_len); - free(srk); -} - - -void -sshsk_free_resident_keys(struct sshsk_resident_key **srks, size_t nsrks) -{ - size_t i; - - if (srks == NULL || nsrks == 0) - return; - - for (i = 0; i < nsrks; i++) - sshsk_free_resident_key(srks[i]); - free(srks); -} - -int -sshsk_load_resident(const char *provider_path, const char *device, - const char *pin, u_int flags, struct sshsk_resident_key ***srksp, - size_t *nsrksp) -{ - struct sshsk_provider *skp = NULL; - int r = SSH_ERR_INTERNAL_ERROR; - struct sk_resident_key **rks = NULL; - size_t i, nrks = 0, nsrks = 0; - struct sshkey *key = NULL; - struct sshsk_resident_key *srk = NULL, **srks = NULL, **tmp; - uint8_t sk_flags; - struct sk_option **opts = NULL; - - debug_f("provider \"%s\"%s", provider_path, - (pin != NULL && *pin != '\0') ? ", have-pin": ""); - - if (srksp == NULL || nsrksp == NULL) - return SSH_ERR_INVALID_ARGUMENT; - *srksp = NULL; - *nsrksp = 0; - - if ((r = make_options(device, NULL, &opts)) != 0) - goto out; - if ((skp = sshsk_open(provider_path)) == NULL) { - r = SSH_ERR_INVALID_FORMAT; /* XXX sshsk_open return code? */ - goto out; - } - if ((r = skp->sk_load_resident_keys(pin, opts, &rks, &nrks)) != 0) { - error("Provider \"%s\" returned failure %d", provider_path, r); - r = skerr_to_ssherr(r); - goto out; - } - for (i = 0; i < nrks; i++) { - debug3_f("rk %zu: slot %zu, alg %d, app \"%s\", uidlen %zu", - i, rks[i]->slot, rks[i]->alg, rks[i]->application, - rks[i]->user_id_len); - /* XXX need better filter here */ - if (strncmp(rks[i]->application, "ssh:", 4) != 0) - continue; - switch (rks[i]->alg) { - case SSH_SK_ECDSA: - case SSH_SK_ED25519: - break; - default: - continue; - } - sk_flags = SSH_SK_USER_PRESENCE_REQD|SSH_SK_RESIDENT_KEY; - if ((rks[i]->flags & SSH_SK_USER_VERIFICATION_REQD)) - sk_flags |= SSH_SK_USER_VERIFICATION_REQD; - if ((r = sshsk_key_from_response(rks[i]->alg, - rks[i]->application, sk_flags, &rks[i]->key, &key)) != 0) - goto out; - if ((srk = calloc(1, sizeof(*srk))) == NULL) { - error_f("calloc failed"); - r = SSH_ERR_ALLOC_FAIL; - goto out; - } - srk->key = key; - key = NULL; /* transferred */ - if ((srk->user_id = calloc(1, rks[i]->user_id_len)) == NULL) { - error_f("calloc failed"); - r = SSH_ERR_ALLOC_FAIL; - goto out; - } - memcpy(srk->user_id, rks[i]->user_id, rks[i]->user_id_len); - srk->user_id_len = rks[i]->user_id_len; - if ((tmp = recallocarray(srks, nsrks, nsrks + 1, - sizeof(*tmp))) == NULL) { - error_f("recallocarray failed"); - r = SSH_ERR_ALLOC_FAIL; - goto out; - } - srks = tmp; - srks[nsrks++] = srk; - srk = NULL; - /* XXX synthesise comment */ - } - /* success */ - *srksp = srks; - *nsrksp = nsrks; - srks = NULL; - nsrks = 0; - r = 0; - out: - sshsk_free_options(opts); - sshsk_free(skp); - sshsk_free_sk_resident_keys(rks, nrks); - sshkey_free(key); - sshsk_free_resident_key(srk); - sshsk_free_resident_keys(srks, nsrks); - return r; -} - -#endif /* ENABLE_SK */ diff -ruN openssh-9.4p1/ssh-sk-client.c openssh-9.4p1+x509-14.2.1/ssh-sk-client.c --- openssh-9.4p1/ssh-sk-client.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/ssh-sk-client.c 1970-01-01 02:00:00.000000000 +0200 @@ -1,480 +0,0 @@ -/* $OpenBSD: ssh-sk-client.c,v 1.12 2022/01/14 03:34:00 djm Exp $ */ -/* - * Copyright (c) 2019 Google LLC - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include "includes.h" - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "log.h" -#include "ssherr.h" -#include "sshbuf.h" -#include "sshkey.h" -#include "msg.h" -#include "digest.h" -#include "pathnames.h" -#include "ssh-sk.h" -#include "misc.h" - -/* #define DEBUG_SK 1 */ - -static int -start_helper(int *fdp, pid_t *pidp, void (**osigchldp)(int)) -{ - void (*osigchld)(int); - int oerrno, pair[2]; - pid_t pid; - char *helper, *verbosity = NULL; - - *fdp = -1; - *pidp = 0; - *osigchldp = SIG_DFL; - - helper = getenv("SSH_SK_HELPER"); - if (helper == NULL || strlen(helper) == 0) - helper = _PATH_SSH_SK_HELPER; - if (access(helper, X_OK) != 0) { - oerrno = errno; - error_f("helper \"%s\" unusable: %s", helper, strerror(errno)); - errno = oerrno; - return SSH_ERR_SYSTEM_ERROR; - } -#ifdef DEBUG_SK - verbosity = "-vvv"; -#endif - - /* Start helper */ - if (socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == -1) { - error("socketpair: %s", strerror(errno)); - return SSH_ERR_SYSTEM_ERROR; - } - osigchld = ssh_signal(SIGCHLD, SIG_DFL); - if ((pid = fork()) == -1) { - oerrno = errno; - error("fork: %s", strerror(errno)); - close(pair[0]); - close(pair[1]); - ssh_signal(SIGCHLD, osigchld); - errno = oerrno; - return SSH_ERR_SYSTEM_ERROR; - } - if (pid == 0) { - if ((dup2(pair[1], STDIN_FILENO) == -1) || - (dup2(pair[1], STDOUT_FILENO) == -1)) { - error_f("dup2: %s", strerror(errno)); - _exit(1); - } - close(pair[0]); - close(pair[1]); - closefrom(STDERR_FILENO + 1); - debug_f("starting %s %s", helper, - verbosity == NULL ? "" : verbosity); - execlp(helper, helper, verbosity, (char *)NULL); - error_f("execlp: %s", strerror(errno)); - _exit(1); - } - close(pair[1]); - - /* success */ - debug3_f("started pid=%ld", (long)pid); - *fdp = pair[0]; - *pidp = pid; - *osigchldp = osigchld; - return 0; -} - -static int -reap_helper(pid_t pid) -{ - int status, oerrno; - - debug3_f("pid=%ld", (long)pid); - - errno = 0; - while (waitpid(pid, &status, 0) == -1) { - if (errno == EINTR) { - errno = 0; - continue; - } - oerrno = errno; - error_f("waitpid: %s", strerror(errno)); - errno = oerrno; - return SSH_ERR_SYSTEM_ERROR; - } - if (!WIFEXITED(status)) { - error_f("helper exited abnormally"); - return SSH_ERR_AGENT_FAILURE; - } else if (WEXITSTATUS(status) != 0) { - error_f("helper exited with non-zero exit status"); - return SSH_ERR_AGENT_FAILURE; - } - return 0; -} - -static int -client_converse(struct sshbuf *msg, struct sshbuf **respp, u_int type) -{ - int oerrno, fd, r2, ll, r = SSH_ERR_INTERNAL_ERROR; - u_int rtype, rerr; - pid_t pid; - u_char version; - void (*osigchld)(int); - struct sshbuf *req = NULL, *resp = NULL; - *respp = NULL; - - if ((r = start_helper(&fd, &pid, &osigchld)) != 0) - return r; - - if ((req = sshbuf_new()) == NULL || (resp = sshbuf_new()) == NULL) { - r = SSH_ERR_ALLOC_FAIL; - goto out; - } - /* Request preamble: type, log_on_stderr, log_level */ - ll = log_level_get(); - if ((r = sshbuf_put_u32(req, type)) != 0 || - (r = sshbuf_put_u8(req, log_is_on_stderr() != 0)) != 0 || - (r = sshbuf_put_u32(req, ll < 0 ? 0 : ll)) != 0 || - (r = sshbuf_putb(req, msg)) != 0) { - error_fr(r, "compose"); - goto out; - } - if ((r = ssh_msg_send(fd, SSH_SK_HELPER_VERSION, req)) != 0) { - error_fr(r, "send"); - goto out; - } - if ((r = ssh_msg_recv(fd, resp)) != 0) { - error_fr(r, "receive"); - goto out; - } - if ((r = sshbuf_get_u8(resp, &version)) != 0) { - error_fr(r, "parse version"); - goto out; - } - if (version != SSH_SK_HELPER_VERSION) { - error_f("unsupported version: got %u, expected %u", - version, SSH_SK_HELPER_VERSION); - r = SSH_ERR_INVALID_FORMAT; - goto out; - } - if ((r = sshbuf_get_u32(resp, &rtype)) != 0) { - error_fr(r, "parse message type"); - goto out; - } - if (rtype == SSH_SK_HELPER_ERROR) { - if ((r = sshbuf_get_u32(resp, &rerr)) != 0) { - error_fr(r, "parse"); - goto out; - } - debug_f("helper returned error -%u", rerr); - /* OpenSSH error values are negative; encoded as -err on wire */ - if (rerr == 0 || rerr >= INT_MAX) - r = SSH_ERR_INTERNAL_ERROR; - else - r = -(int)rerr; - goto out; - } else if (rtype != type) { - error_f("helper returned incorrect message type %u, " - "expecting %u", rtype, type); - r = SSH_ERR_INTERNAL_ERROR; - goto out; - } - /* success */ - r = 0; - out: - oerrno = errno; - close(fd); - if ((r2 = reap_helper(pid)) != 0) { - if (r == 0) { - r = r2; - oerrno = errno; - } - } - if (r == 0) { - *respp = resp; - resp = NULL; - } - sshbuf_free(req); - sshbuf_free(resp); - ssh_signal(SIGCHLD, osigchld); - errno = oerrno; - return r; - -} - -int -sshsk_sign(const char *provider, struct sshkey *key, - u_char **sigp, size_t *lenp, const u_char *data, size_t datalen, - u_int compat, const char *pin) -{ - int oerrno, r = SSH_ERR_INTERNAL_ERROR; - struct sshbuf *kbuf = NULL, *req = NULL, *resp = NULL; - - *sigp = NULL; - *lenp = 0; - -#ifndef ENABLE_SK - return SSH_ERR_KEY_TYPE_UNKNOWN; -#endif - - if ((kbuf = sshbuf_new()) == NULL || - (req = sshbuf_new()) == NULL) { - r = SSH_ERR_ALLOC_FAIL; - goto out; - } - - if ((r = sshkey_private_serialize(key, kbuf)) != 0) { - error_fr(r, "encode key"); - goto out; - } - if ((r = sshbuf_put_stringb(req, kbuf)) != 0 || - (r = sshbuf_put_cstring(req, provider)) != 0 || - (r = sshbuf_put_string(req, data, datalen)) != 0 || - (r = sshbuf_put_cstring(req, NULL)) != 0 || /* alg */ - (r = sshbuf_put_u32(req, compat)) != 0 || - (r = sshbuf_put_cstring(req, pin)) != 0) { - error_fr(r, "compose"); - goto out; - } - - if ((r = client_converse(req, &resp, SSH_SK_HELPER_SIGN)) != 0) - goto out; - - if ((r = sshbuf_get_string(resp, sigp, lenp)) != 0) { - error_fr(r, "parse signature"); - r = SSH_ERR_INVALID_FORMAT; - goto out; - } - if (sshbuf_len(resp) != 0) { - error_f("trailing data in response"); - r = SSH_ERR_INVALID_FORMAT; - goto out; - } - /* success */ - r = 0; - out: - oerrno = errno; - if (r != 0) { - freezero(*sigp, *lenp); - *sigp = NULL; - *lenp = 0; - } - sshbuf_free(kbuf); - sshbuf_free(req); - sshbuf_free(resp); - errno = oerrno; - return r; -} - -int -sshsk_enroll(int type, const char *provider_path, const char *device, - const char *application, const char *userid, uint8_t flags, - const char *pin, struct sshbuf *challenge_buf, - struct sshkey **keyp, struct sshbuf *attest) -{ - int oerrno, r = SSH_ERR_INTERNAL_ERROR; - struct sshbuf *kbuf = NULL, *abuf = NULL, *req = NULL, *resp = NULL; - struct sshkey *key = NULL; - - *keyp = NULL; - if (attest != NULL) - sshbuf_reset(attest); - -#ifndef ENABLE_SK - return SSH_ERR_KEY_TYPE_UNKNOWN; -#endif - - if (type < 0) - return SSH_ERR_INVALID_ARGUMENT; - - if ((abuf = sshbuf_new()) == NULL || - (kbuf = sshbuf_new()) == NULL || - (req = sshbuf_new()) == NULL) { - r = SSH_ERR_ALLOC_FAIL; - goto out; - } - - if ((r = sshbuf_put_u32(req, (u_int)type)) != 0 || - (r = sshbuf_put_cstring(req, provider_path)) != 0 || - (r = sshbuf_put_cstring(req, device)) != 0 || - (r = sshbuf_put_cstring(req, application)) != 0 || - (r = sshbuf_put_cstring(req, userid)) != 0 || - (r = sshbuf_put_u8(req, flags)) != 0 || - (r = sshbuf_put_cstring(req, pin)) != 0 || - (r = sshbuf_put_stringb(req, challenge_buf)) != 0) { - error_fr(r, "compose"); - goto out; - } - - if ((r = client_converse(req, &resp, SSH_SK_HELPER_ENROLL)) != 0) - goto out; - - if ((r = sshbuf_get_stringb(resp, kbuf)) != 0 || - (r = sshbuf_get_stringb(resp, abuf)) != 0) { - error_fr(r, "parse"); - r = SSH_ERR_INVALID_FORMAT; - goto out; - } - if (sshbuf_len(resp) != 0) { - error_f("trailing data in response"); - r = SSH_ERR_INVALID_FORMAT; - goto out; - } - if ((r = sshkey_private_deserialize(kbuf, &key)) != 0) { - error_fr(r, "encode"); - goto out; - } - if (attest != NULL && (r = sshbuf_putb(attest, abuf)) != 0) { - error_fr(r, "encode attestation information"); - goto out; - } - - /* success */ - r = 0; - *keyp = key; - key = NULL; - out: - oerrno = errno; - sshkey_free(key); - sshbuf_free(kbuf); - sshbuf_free(abuf); - sshbuf_free(req); - sshbuf_free(resp); - errno = oerrno; - return r; -} - -static void -sshsk_free_resident_key(struct sshsk_resident_key *srk) -{ - if (srk == NULL) - return; - sshkey_free(srk->key); - freezero(srk->user_id, srk->user_id_len); - free(srk); -} - - -void -sshsk_free_resident_keys(struct sshsk_resident_key **srks, size_t nsrks) -{ - size_t i; - - if (srks == NULL || nsrks == 0) - return; - - for (i = 0; i < nsrks; i++) - sshsk_free_resident_key(srks[i]); - free(srks); -} - -int -sshsk_load_resident(const char *provider_path, const char *device, - const char *pin, u_int flags, struct sshsk_resident_key ***srksp, - size_t *nsrksp) -{ - int oerrno, r = SSH_ERR_INTERNAL_ERROR; - struct sshbuf *kbuf = NULL, *req = NULL, *resp = NULL; - struct sshkey *key = NULL; - struct sshsk_resident_key *srk = NULL, **srks = NULL, **tmp; - u_char *userid = NULL; - size_t userid_len = 0, nsrks = 0; - - *srksp = NULL; - *nsrksp = 0; - - if ((kbuf = sshbuf_new()) == NULL || - (req = sshbuf_new()) == NULL) { - r = SSH_ERR_ALLOC_FAIL; - goto out; - } - - if ((r = sshbuf_put_cstring(req, provider_path)) != 0 || - (r = sshbuf_put_cstring(req, device)) != 0 || - (r = sshbuf_put_cstring(req, pin)) != 0 || - (r = sshbuf_put_u32(req, flags)) != 0) { - error_fr(r, "compose"); - goto out; - } - - if ((r = client_converse(req, &resp, SSH_SK_HELPER_LOAD_RESIDENT)) != 0) - goto out; - - while (sshbuf_len(resp) != 0) { - /* key, comment, user_id */ - if ((r = sshbuf_get_stringb(resp, kbuf)) != 0 || - (r = sshbuf_get_cstring(resp, NULL, NULL)) != 0 || - (r = sshbuf_get_string(resp, &userid, &userid_len)) != 0) { - error_fr(r, "parse"); - r = SSH_ERR_INVALID_FORMAT; - goto out; - } - if ((r = sshkey_private_deserialize(kbuf, &key)) != 0) { - error_fr(r, "decode key"); - goto out; - } - if ((srk = calloc(1, sizeof(*srk))) == NULL) { - error_f("calloc failed"); - goto out; - } - srk->key = key; - key = NULL; - srk->user_id = userid; - srk->user_id_len = userid_len; - userid = NULL; - userid_len = 0; - if ((tmp = recallocarray(srks, nsrks, nsrks + 1, - sizeof(*srks))) == NULL) { - error_f("recallocarray keys failed"); - goto out; - } - debug_f("srks[%zu]: %s %s uidlen %zu", nsrks, - sshkey_type(srk->key), srk->key->sk_application, - srk->user_id_len); - srks = tmp; - srks[nsrks++] = srk; - srk = NULL; - } - - /* success */ - r = 0; - *srksp = srks; - *nsrksp = nsrks; - srks = NULL; - nsrks = 0; - out: - oerrno = errno; - sshsk_free_resident_key(srk); - sshsk_free_resident_keys(srks, nsrks); - freezero(userid, userid_len); - sshkey_free(key); - sshbuf_free(kbuf); - sshbuf_free(req); - sshbuf_free(resp); - errno = oerrno; - return r; -} diff -ruN openssh-9.4p1/ssh-sk.h openssh-9.4p1+x509-14.2.1/ssh-sk.h --- openssh-9.4p1/ssh-sk.h 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/ssh-sk.h 1970-01-01 02:00:00.000000000 +0200 @@ -1,79 +0,0 @@ -/* $OpenBSD: ssh-sk.h,v 1.11 2021/10/28 02:54:18 djm Exp $ */ -/* - * Copyright (c) 2019 Google LLC - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#ifndef _SSH_SK_H -#define _SSH_SK_H 1 - -struct sshbuf; -struct sshkey; -struct sk_option; - -/* Version of protocol expected from ssh-sk-helper */ -#define SSH_SK_HELPER_VERSION 5 - -/* ssh-sk-helper messages */ -#define SSH_SK_HELPER_ERROR 0 /* Only valid H->C */ -#define SSH_SK_HELPER_SIGN 1 -#define SSH_SK_HELPER_ENROLL 2 -#define SSH_SK_HELPER_LOAD_RESIDENT 3 - -struct sshsk_resident_key { - struct sshkey *key; - uint8_t *user_id; - size_t user_id_len; -}; - -/* - * Enroll (generate) a new security-key hosted private key of given type - * via the specified provider middleware. - * If challenge_buf is NULL then a random 256 bit challenge will be used. - * - * Returns 0 on success or a ssherr.h error code on failure. - * - * If successful and the attest_data buffer is not NULL then attestation - * information is placed there. - */ -int sshsk_enroll(int type, const char *provider_path, const char *device, - const char *application, const char *userid, uint8_t flags, - const char *pin, struct sshbuf *challenge_buf, - struct sshkey **keyp, struct sshbuf *attest); - -/* - * Calculate an ECDSA_SK or ED25519_SK signature using the specified key - * and provider middleware. - * - * Returns 0 on success or a ssherr.h error code on failure. - */ -int sshsk_sign(const char *provider_path, struct sshkey *key, - u_char **sigp, size_t *lenp, const u_char *data, size_t datalen, - u_int compat, const char *pin); - -/* - * Enumerates and loads all SSH-compatible resident keys from a security - * key. - * - * Returns 0 on success or a ssherr.h error code on failure. - */ -int sshsk_load_resident(const char *provider_path, const char *device, - const char *pin, u_int flags, struct sshsk_resident_key ***srksp, - size_t *nsrksp); - -/* Free an array of sshsk_resident_key (as returned from sshsk_load_resident) */ -void sshsk_free_resident_keys(struct sshsk_resident_key **srks, size_t nsrks); - -#endif /* _SSH_SK_H */ - diff -ruN openssh-9.4p1/ssh-sk-helper.0 openssh-9.4p1+x509-14.2.1/ssh-sk-helper.0 --- openssh-9.4p1/ssh-sk-helper.0 2023-08-10 04:11:19.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/ssh-sk-helper.0 1970-01-01 02:00:00.000000000 +0200 @@ -1,34 +0,0 @@ -SSH-SK-HELPER(8) System Manager's Manual SSH-SK-HELPER(8) - -NAME - ssh-sk-helper M-bM-^@M-^S OpenSSH helper for FIDO authenticator support - -SYNOPSIS - ssh-sk-helper [-v] - -DESCRIPTION - ssh-sk-helper is used by ssh(1), ssh-agent(1), and ssh-keygen(1) to - access keys provided by a FIDO authenticator. - - ssh-sk-helper is not intended to be invoked directly by the user. - - A single option is supported: - - -v Verbose mode. Causes ssh-sk-helper to print debugging messages - about its progress. This is helpful in debugging problems. - Multiple -v options increase the verbosity. The maximum is 3. - - Note that ssh(1), ssh-agent(1), and ssh-keygen(1) will - automatically pass the -v flag to ssh-sk-helper when they have - themselves been placed in debug mode. - -SEE ALSO - ssh(1), ssh-agent(1), ssh-keygen(1) - -HISTORY - ssh-sk-helper first appeared in OpenBSD 6.7. - -AUTHORS - Damien Miller - -OpenBSD 7.3 April 29, 2022 OpenBSD 7.3 diff -ruN openssh-9.4p1/ssh-sk-helper.8 openssh-9.4p1+x509-14.2.1/ssh-sk-helper.8 --- openssh-9.4p1/ssh-sk-helper.8 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/ssh-sk-helper.8 1970-01-01 02:00:00.000000000 +0200 @@ -1,71 +0,0 @@ -.\" $OpenBSD: ssh-sk-helper.8,v 1.4 2022/04/29 03:24:30 djm Exp $ -.\" -.\" Copyright (c) 2010 Markus Friedl. All rights reserved. -.\" -.\" Permission to use, copy, modify, and distribute this software for any -.\" purpose with or without fee is hereby granted, provided that the above -.\" copyright notice and this permission notice appear in all copies. -.\" -.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -.\" -.Dd $Mdocdate: April 29 2022 $ -.Dt SSH-SK-HELPER 8 -.Os -.Sh NAME -.Nm ssh-sk-helper -.Nd OpenSSH helper for FIDO authenticator support -.Sh SYNOPSIS -.Nm -.Op Fl v -.Sh DESCRIPTION -.Nm -is used by -.Xr ssh 1 , -.Xr ssh-agent 1 , -and -.Xr ssh-keygen 1 -to access keys provided by a FIDO authenticator. -.Pp -.Nm -is not intended to be invoked directly by the user. -.Pp -A single option is supported: -.Bl -tag -width Ds -.It Fl v -Verbose mode. -Causes -.Nm -to print debugging messages about its progress. -This is helpful in debugging problems. -Multiple -.Fl v -options increase the verbosity. -The maximum is 3. -.Pp -Note that -.Xr ssh 1 , -.Xr ssh-agent 1 , -and -.Xr ssh-keygen 1 -will automatically pass the -.Fl v -flag to -.Nm -when they have themselves been placed in debug mode. -.El -.Sh SEE ALSO -.Xr ssh 1 , -.Xr ssh-agent 1 , -.Xr ssh-keygen 1 -.Sh HISTORY -.Nm -first appeared in -.Ox 6.7 . -.Sh AUTHORS -.An Damien Miller Aq Mt djm@openbsd.org diff -ruN openssh-9.4p1/ssh-sk-helper.c openssh-9.4p1+x509-14.2.1/ssh-sk-helper.c --- openssh-9.4p1/ssh-sk-helper.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/ssh-sk-helper.c 1970-01-01 02:00:00.000000000 +0200 @@ -1,367 +0,0 @@ -/* $OpenBSD: ssh-sk-helper.c,v 1.14 2022/12/04 11:03:11 dtucker Exp $ */ -/* - * Copyright (c) 2019 Google LLC - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -/* - * This is a tiny program used to isolate the address space used for - * security key middleware signing operations from ssh-agent. It is similar - * to ssh-pkcs11-helper.c but considerably simpler as the operations for - * security keys are stateless. - * - * Please crank SSH_SK_HELPER_VERSION in sshkey.h for any incompatible - * protocol changes. - */ - -#include "includes.h" - -#include -#include -#include -#include -#include -#include -#include - -#include "xmalloc.h" -#include "log.h" -#include "sshkey.h" -#include "authfd.h" -#include "misc.h" -#include "sshbuf.h" -#include "msg.h" -#include "uidswap.h" -#include "ssherr.h" -#include "ssh-sk.h" - -#ifdef ENABLE_SK -extern char *__progname; - -static struct sshbuf *reply_error(int r, char *fmt, ...) - __attribute__((__format__ (printf, 2, 3))); - -static struct sshbuf * -reply_error(int r, char *fmt, ...) -{ - char *msg; - va_list ap; - struct sshbuf *resp; - - va_start(ap, fmt); - xvasprintf(&msg, fmt, ap); - va_end(ap); - debug("%s: %s", __progname, msg); - free(msg); - - if (r >= 0) - fatal_f("invalid error code %d", r); - - if ((resp = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new failed", __progname); - if (sshbuf_put_u32(resp, SSH_SK_HELPER_ERROR) != 0 || - sshbuf_put_u32(resp, (u_int)-r) != 0) - fatal("%s: buffer error", __progname); - return resp; -} - -/* If the specified string is zero length, then free it and replace with NULL */ -static void -null_empty(char **s) -{ - if (s == NULL || *s == NULL || **s != '\0') - return; - - free(*s); - *s = NULL; -} - -static struct sshbuf * -process_sign(struct sshbuf *req) -{ - int r = SSH_ERR_INTERNAL_ERROR; - struct sshbuf *resp, *kbuf; - struct sshkey *key = NULL; - uint32_t compat; - const u_char *message; - u_char *sig = NULL; - size_t msglen, siglen = 0; - char *provider = NULL, *pin = NULL; - - if ((r = sshbuf_froms(req, &kbuf)) != 0 || - (r = sshbuf_get_cstring(req, &provider, NULL)) != 0 || - (r = sshbuf_get_string_direct(req, &message, &msglen)) != 0 || - (r = sshbuf_get_cstring(req, NULL, NULL)) != 0 || /* alg */ - (r = sshbuf_get_u32(req, &compat)) != 0 || - (r = sshbuf_get_cstring(req, &pin, NULL)) != 0) - fatal_r(r, "%s: parse", __progname); - if (sshbuf_len(req) != 0) - fatal("%s: trailing data in request", __progname); - - if ((r = sshkey_private_deserialize(kbuf, &key)) != 0) - fatal_r(r, "%s: Unable to parse private key", __progname); - if (!sshkey_is_sk(key)) { - fatal("%s: Unsupported key type %s", - __progname, sshkey_ssh_name(key)); - } - - debug_f("ready to sign with key %s, provider %s: " - "msg len %zu, compat 0x%lx", sshkey_type(key), - provider, msglen, (u_long)compat); - - null_empty(&pin); - - if ((r = sshsk_sign(provider, key, &sig, &siglen, - message, msglen, compat, pin)) != 0) { - resp = reply_error(r, "Signing failed: %s", ssh_err(r)); - goto out; - } - - if ((resp = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new failed", __progname); - - if ((r = sshbuf_put_u32(resp, SSH_SK_HELPER_SIGN)) != 0 || - (r = sshbuf_put_string(resp, sig, siglen)) != 0) - fatal_r(r, "%s: compose", __progname); - out: - sshkey_free(key); - sshbuf_free(kbuf); - free(provider); - if (sig != NULL) - freezero(sig, siglen); - if (pin != NULL) - freezero(pin, strlen(pin)); - return resp; -} - -static struct sshbuf * -process_enroll(struct sshbuf *req) -{ - int r; - u_int type; - char *provider, *application, *pin, *device, *userid; - uint8_t flags; - struct sshbuf *challenge, *attest, *kbuf, *resp; - struct sshkey *key; - - if ((attest = sshbuf_new()) == NULL || - (kbuf = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new failed", __progname); - - if ((r = sshbuf_get_u32(req, &type)) != 0 || - (r = sshbuf_get_cstring(req, &provider, NULL)) != 0 || - (r = sshbuf_get_cstring(req, &device, NULL)) != 0 || - (r = sshbuf_get_cstring(req, &application, NULL)) != 0 || - (r = sshbuf_get_cstring(req, &userid, NULL)) != 0 || - (r = sshbuf_get_u8(req, &flags)) != 0 || - (r = sshbuf_get_cstring(req, &pin, NULL)) != 0 || - (r = sshbuf_froms(req, &challenge)) != 0) - fatal_r(r, "%s: parse", __progname); - if (sshbuf_len(req) != 0) - fatal("%s: trailing data in request", __progname); - - if (type > INT_MAX) - fatal("%s: bad type %u", __progname, type); - if (sshbuf_len(challenge) == 0) { - sshbuf_free(challenge); - challenge = NULL; - } - null_empty(&device); - null_empty(&userid); - null_empty(&pin); - - if ((r = sshsk_enroll((int)type, provider, device, application, userid, - flags, pin, challenge, &key, attest)) != 0) { - resp = reply_error(r, "Enrollment failed: %s", ssh_err(r)); - goto out; - } - - if ((resp = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new failed", __progname); - if ((r = sshkey_private_serialize(key, kbuf)) != 0) - fatal_r(r, "%s: encode key", __progname); - if ((r = sshbuf_put_u32(resp, SSH_SK_HELPER_ENROLL)) != 0 || - (r = sshbuf_put_stringb(resp, kbuf)) != 0 || - (r = sshbuf_put_stringb(resp, attest)) != 0) - fatal_r(r, "%s: compose", __progname); - - out: - sshkey_free(key); - sshbuf_free(kbuf); - sshbuf_free(attest); - sshbuf_free(challenge); - free(provider); - free(application); - if (pin != NULL) - freezero(pin, strlen(pin)); - - return resp; -} - -static struct sshbuf * -process_load_resident(struct sshbuf *req) -{ - int r; - char *provider, *pin, *device; - struct sshbuf *kbuf, *resp; - struct sshsk_resident_key **srks = NULL; - size_t nsrks = 0, i; - u_int flags; - - if ((kbuf = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new failed", __progname); - - if ((r = sshbuf_get_cstring(req, &provider, NULL)) != 0 || - (r = sshbuf_get_cstring(req, &device, NULL)) != 0 || - (r = sshbuf_get_cstring(req, &pin, NULL)) != 0 || - (r = sshbuf_get_u32(req, &flags)) != 0) - fatal_r(r, "%s: parse", __progname); - if (sshbuf_len(req) != 0) - fatal("%s: trailing data in request", __progname); - - null_empty(&device); - null_empty(&pin); - - if ((r = sshsk_load_resident(provider, device, pin, flags, - &srks, &nsrks)) != 0) { - resp = reply_error(r, "sshsk_load_resident failed: %s", - ssh_err(r)); - goto out; - } - - if ((resp = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new failed", __progname); - - if ((r = sshbuf_put_u32(resp, SSH_SK_HELPER_LOAD_RESIDENT)) != 0) - fatal_r(r, "%s: compose", __progname); - - for (i = 0; i < nsrks; i++) { - debug_f("key %zu %s %s uidlen %zu", i, - sshkey_type(srks[i]->key), srks[i]->key->sk_application, - srks[i]->user_id_len); - sshbuf_reset(kbuf); - if ((r = sshkey_private_serialize(srks[i]->key, kbuf)) != 0) - fatal_r(r, "%s: encode key", __progname); - if ((r = sshbuf_put_stringb(resp, kbuf)) != 0 || - (r = sshbuf_put_cstring(resp, "")) != 0 || /* comment */ - (r = sshbuf_put_string(resp, srks[i]->user_id, - srks[i]->user_id_len)) != 0) - fatal_r(r, "%s: compose key", __progname); - } - - out: - sshsk_free_resident_keys(srks, nsrks); - sshbuf_free(kbuf); - free(provider); - free(device); - if (pin != NULL) - freezero(pin, strlen(pin)); - return resp; -} - -int -main(int argc, char **argv) -{ - SyslogFacility log_facility = SYSLOG_FACILITY_AUTH; - LogLevel log_level = SYSLOG_LEVEL_ERROR; - struct sshbuf *req, *resp; - int in, out, ch, r, vflag = 0; - u_int rtype, ll = 0; - uint8_t version, log_stderr = 0; - - sanitise_stdfd(); - log_init(__progname, log_level, log_facility, log_stderr); - - while ((ch = getopt(argc, argv, "v")) != -1) { - switch (ch) { - case 'v': - vflag = 1; - if (log_level == SYSLOG_LEVEL_ERROR) - log_level = SYSLOG_LEVEL_DEBUG1; - else if (log_level < SYSLOG_LEVEL_DEBUG3) - log_level++; - break; - default: - fprintf(stderr, "usage: %s [-v]\n", __progname); - exit(1); - } - } - log_init(__progname, log_level, log_facility, vflag); - - /* - * Rearrange our file descriptors a little; we don't trust the - * providers not to fiddle with stdin/out. - */ - closefrom(STDERR_FILENO + 1); - if ((in = dup(STDIN_FILENO)) == -1 || (out = dup(STDOUT_FILENO)) == -1) - fatal("%s: dup: %s", __progname, strerror(errno)); - close(STDIN_FILENO); - close(STDOUT_FILENO); - sanitise_stdfd(); /* resets to /dev/null */ - - if ((req = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new failed", __progname); - if (ssh_msg_recv(in, req) < 0) - fatal("ssh_msg_recv failed"); - close(in); - debug_f("received message len %zu", sshbuf_len(req)); - - if ((r = sshbuf_get_u8(req, &version)) != 0) - fatal_r(r, "%s: parse version", __progname); - if (version != SSH_SK_HELPER_VERSION) { - fatal("unsupported version: received %d, expected %d", - version, SSH_SK_HELPER_VERSION); - } - - if ((r = sshbuf_get_u32(req, &rtype)) != 0 || - (r = sshbuf_get_u8(req, &log_stderr)) != 0 || - (r = sshbuf_get_u32(req, &ll)) != 0) - fatal_r(r, "%s: parse", __progname); - - if (!vflag && log_level_name((LogLevel)ll) != NULL) - log_init(__progname, (LogLevel)ll, log_facility, log_stderr); - - switch (rtype) { - case SSH_SK_HELPER_SIGN: - resp = process_sign(req); - break; - case SSH_SK_HELPER_ENROLL: - resp = process_enroll(req); - break; - case SSH_SK_HELPER_LOAD_RESIDENT: - resp = process_load_resident(req); - break; - default: - fatal("%s: unsupported request type %u", __progname, rtype); - } - sshbuf_free(req); - debug_f("reply len %zu", sshbuf_len(resp)); - - if (ssh_msg_send(out, SSH_SK_HELPER_VERSION, resp) == -1) - fatal("ssh_msg_send failed"); - sshbuf_free(resp); - close(out); - - return (0); -} -#else /* ENABLE_SK */ -#include - -int -main(int argc, char **argv) -{ - fprintf(stderr, "ssh-sk-helper: disabled at compile time\n"); - return -1; -} -#endif /* ENABLE_SK */ diff -ruN openssh-9.4p1/ssh-x509.c openssh-9.4p1+x509-14.2.1/ssh-x509.c --- openssh-9.4p1/ssh-x509.c 1970-01-01 02:00:00.000000000 +0200 +++ openssh-9.4p1+x509-14.2.1/ssh-x509.c 2023-08-20 10:07:01.000000000 +0300 @@ -0,0 +1,2304 @@ +/* + * Copyright (c) 2002-2022 Roumen Petrov. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#define SSHKEY_INTERNAL +#include "ssh-x509.h" +#include +#include + +#include +#include +#include "evp-compat.h" + +#include "ssh-xkalg.h" +#include "x509store.h" +#include "compat.h" +#include "xmalloc.h" +#include "ssherr.h" +#include "log.h" + +#ifndef ISSPACE +# define ISSPACE(ch) (isspace((int)(unsigned char)(ch))) +#endif + +/* pointer to x509store function to minimize build dependencies */ +int (*pssh_x509store_verify_cert)(X509 *cert, STACK_OF(X509) *untrusted) = NULL; +STACK_OF(X509)* (*pssh_x509store_build_certchain)(X509 *cert, STACK_OF(X509) *untrusted) = NULL; + +/* functions for internal use only */ +extern struct sshkey* x509_to_key(X509 *x509); +extern int X509_from_blob(const u_char *blob, size_t blen, X509 **xp); + + +static int xkey_to_buf2(const SSHX509KeyAlgs *xkalg, const struct sshkey *key, struct sshbuf *b); + + +static inline int +check_rsa2048_sha256(const SSHX509KeyAlgs *xkalg, const struct sshkey *key) { +#ifdef HAVE_EVP_SHA256 + /* extra check for algorithms like x509v3-rsa2048-sha256 */ + if ( + /* TODO generic */ + (key->type == KEY_RSA) && + (sshkey_size(key) < 2048) && + (EVP_MD_size(xkalg->dgst->md()) >= SHA256_DIGEST_LENGTH) + ) + return 0; +#else + UNUSED(xkalg); + UNUSED(key); +#endif /*def HAVE_EVP_SHA256*/ + return 1; +} + + +struct ssh_x509_st { + X509 *cert; /* key certificate */ + STACK_OF(X509) *chain; /* reserved for future use */ +}; + + +SSH_X509* +SSH_X509_new() { + SSH_X509 *xd; + + xd = xmalloc(sizeof(SSH_X509)); /*fatal on error*/ + xd->cert = NULL; + xd->chain = NULL; + + return xd; +} + + +static inline void +SSH_X509_free_data(SSH_X509* xd) { + if (xd->cert != NULL) { + X509_free(xd->cert); + xd->cert = NULL; + } + + if (xd->chain != NULL) { + sk_X509_pop_free(xd->chain, X509_free); + xd->chain = NULL; + } +} + + +void +SSH_X509_free(SSH_X509* xd) { + if (xd == NULL) return; + + SSH_X509_free_data(xd); + free(xd); +} + + +X509* +SSH_X509_get_cert(SSH_X509 *xd) { + return (xd != NULL) ? xd->cert : NULL; +} + + +int +ssh_X509_NAME_print(BIO* bio, X509_NAME *xn) { + static u_long print_flags = ((XN_FLAG_ONELINE & \ + ~ASN1_STRFLGS_ESC_MSB & \ + ~XN_FLAG_SPC_EQ & \ + ~XN_FLAG_SEP_MASK) | \ + XN_FLAG_SEP_COMMA_PLUS); + + if (xn == NULL) return -1; + + X509_NAME_print_ex(bio, xn, 0, print_flags); + (void)BIO_flush(bio); + + return BIO_pending(bio); +} + + +char* +ssh_X509_NAME_oneline(X509_NAME *xn) { + char *buf = NULL; + int size; + BIO* mbio = NULL; + + if (xn == NULL) return NULL; + + mbio = BIO_new(BIO_s_mem()); + if (mbio == NULL) return buf; + + size = ssh_X509_NAME_print(mbio, xn); + if (size <= 0) { + error_f("no data in buffer"); + goto done; + } + + buf = xmalloc(size + 1); /*fatal on error*/ + + /* we should request one byte more !?!? */ + if (size != BIO_gets(mbio, buf, size + 1)) { + error_f("cannot get data from buffer"); + goto done; + } + buf[size] = '\0'; + +done: + /* This call will walk the chain freeing all the BIOs */ + BIO_free_all(mbio); + + return buf; +} + + +static inline int +ssh_x509_support_plain_type(int k_type) { + return ( + (k_type == KEY_RSA) || +#ifdef OPENSSL_HAS_ECC + (k_type == KEY_ECDSA) || +#endif +#ifdef OPENSSL_HAS_ED25519 + (k_type == KEY_ED25519) || +#endif + (k_type == KEY_DSA) + ) ? 1 : 0; +} + + +static const char* +x509key_find_subject(const char* s) { + static const char * const keywords[] = { + "subject", + "distinguished name", + "distinguished-name", + "distinguished_name", + "distinguishedname", + "dn", + NULL + }; + const char * const *q, *p; + size_t len; + + if (s == NULL) { + error_f("no input data"); + return NULL; + } + for (; *s && ISSPACE(*s); s++) + {/*skip space*/} + + for (q=keywords; *q; q++) { + len = strlen(*q); + if (strncasecmp(s, *q, len) != 0) continue; + + for (p = s + len; *p && ISSPACE(*p); p++) + {/*skip space*/} + if (!*p) { + error_f("no data after keyword"); + return NULL; + } + if (*p == ':' || *p == '=') { + for (p++; *p && ISSPACE(*p); p++) + {/*skip space*/} + if (!*p) { + error_f("no data after separator"); + return NULL; + } + } + if (*p == '/' || *p == ',') { + /*skip leading [Relative]DistinguishedName elements separator*/ + for (p++; *p && ISSPACE(*p); p++) + {/*skip space*/} + if (!*p) { + error_f("no data"); + return NULL; + } + } + return p; + } + return NULL; +} + + +static unsigned long +ssh_hctol(u_char ch) { +/* '0'-'9' = 0x30 - 0x39 (ascii) */ +/* 'A'-'F' = 0x41 - 0x46 (ascii) */ +/* 'a'-'f' = 0x61 - 0x66 (ascii) */ +/* should work for EBCDIC */ + if (('0' <= ch) && (ch <= '9')) return (long)(ch - '0'); + if (('A' <= ch) && (ch <= 'F')) return (long)(ch - ('A' - 10)); + if (('a' <= ch) && (ch <= 'f')) return (long)(ch - ('a' - 10)); + + return -1; +} + + +static unsigned long +ssh_hatol(const u_char *str, size_t maxsize) { + int k; + long v, ret = 0; + + for(k = maxsize; k > 0; k--, str++) { + v = ssh_hctol(*str); + if (v < 0) return -1; + ret = (ret << 4) + v; + } + return ret; +} + + +static int +get_escsymbol(const u_char* str, size_t len, u_long *value) { + const char ch = *str; + long v; + + if (len < 1) { + error_f("missing characters in escape sequence"); + return -1; + } + + /*escape formats: + "{\\}\\W%08lX" + "{\\}\\U%04lX" + "{\\}\\%02X" + "{\\}\\x%02X" - X509_NAME_oneline format + */ + if (ch == '\\') { + if (value) *value = ch; + return 1; + } + if (ch == 'W') { + if (len < 9) { + error_f("to short 32-bit escape sequence"); + return -1; + } + v = ssh_hatol(++str, 8); + if (v < 0) { + error_f("invalid character in 32-bit hex sequence"); + return -1; + } + if (value) *value = v; + return 9; + } + if (ch == 'U') { + if (len < 5) { + error_f("to short 16-bit escape sequence"); + return -1; + } + v = ssh_hatol(++str, 4); + if (v < 0) { + error_f("invalid character in 16-bit hex sequence"); + return -1; + } + if (value) *value = v; + return 5; + } + v = ssh_hctol(*str); + if (v < 0) { + /*a character is escaped ?*/ + if (*str > 127) { /*ASCII comparison !*/ + /* there is no reason symbol above 127 + to be escaped in this way */ + error_f("non-ascii character in escape sequence"); + return -1; + } + if (value) *value = *str; + return 1; + } + + /*two hex numbers*/ + { + long vlo; + if (len < 2) { + error_f("to short 8-bit escape sequence"); + return -1; + } + vlo = ssh_hctol(*++str); + if (vlo < 0) { + error_f("invalid character in 8-bit hex sequence"); + return -1; + } + v = (v << 4) + vlo; + } + if (value) *value = v; + return 2; +} + + +static int/*bool*/ +ssh_X509_NAME_add_entry_by_NID(X509_NAME* name, int nid, const u_char* str, size_t len) { +/* default maxsizes: + C: 2 + L, ST: 128 + O, OU, CN: 64 + emailAddress: 128 +*/ + u_char buf[129*6+1]; /*enough for 128 UTF-8 symbols*/ + int ret = 0; + int type = MBSTRING_ASC; + u_long ch; + u_char *p; + const u_char *q; + size_t k; + + /*this is internal method and we don't check validity of some arguments*/ + + p = buf; + q = str; + k = sizeof(buf); + + while ((len > 0) && (k > 0)) { + int ch_utf8 = 1; + if (*q == '\0') { + error_f("unsupported zero(NIL) symbol in name"); + return 0; + } + if (*q == '\\') { + len--; + if (len <= 0) { + error_f("escape sequence without data"); + return 0; + } + + ret = get_escsymbol(++q, len, &ch); + if (ret < 0) return 0; + if (ret == 2) { + /*escaped two hex numbers*/ + ch_utf8 = 0; + } + } else { + ret = UTF8_getc(q, len, &ch); + if(ret < 0) { + error_f("cannot get next symbol(%.32s)", q); + return 0; + } + } + len -= ret; + q += ret; + + if (ch_utf8) { + /* UTF8_putc return negative if buffer is too short */ + ret = UTF8_putc(p, k, ch); + if (ret < 0) { + error_f("UTF8_putc fail for symbol %ld", ch); + return 0; + } + } else { + *p = (u_char)ch; + ret = 1; + } + k -= ret; + p += ret; + } + if (len > 0) { + error_f("too long data"); + return 0; + } + *p = '\0'; + + for (p = buf; *p; p++) { + if (*p > 127) { + type = MBSTRING_UTF8; + break; + } + } + k = strlen((char*)buf); + + /* this method will fail if string exceed max size limit for nid */ + ret = X509_NAME_add_entry_by_NID(name, nid, type, buf, (int)k, -1, 0); + if (!ret) + error_crypto_fmt("X509_NAME_add_entry_by_NID", + "nid=%d/%.32s, data='%.512s'", + nid, OBJ_nid2ln(nid), str); + return ret; +} + + +static int/*bool*/ +x509key_str2X509NAME(const char* _str, X509_NAME *_name) { + int ret = 1; + char *str = NULL; + char *p, *q, *token; + int has_more = 0; + + str = xmalloc(strlen(_str) + 1); /*fatal on error*/ + strcpy(str, _str); + + p = (char*)str; + while (*p) { + int nid; + for (; *p && ISSPACE(*p); p++) + {/*skip space*/} + if (!*p) break; + + /* get shortest token */ + { + char *tokenA = strchr(p, ','); + char *tokenB = strchr(p, '/'); + + if (tokenA == NULL) { + token = tokenB; + } else if (tokenB == NULL) { + token = tokenA; + } else { + token = (tokenA < tokenB) ? tokenA : tokenB; + } + } + if (token) { + has_more = 1; + *token = 0; + } else { + has_more = 0; + token = p + strlen(p); + } + q = strchr(p, '='); + if (!q) { + error_f("cannot parse '%.200s' ...", p); + ret = 0; + break; + } + { + char *s = q; + for(--s; ISSPACE(*s) && (s > p); s--) + {/*skip trailing space*/} + *++s = 0; + } + nid = OBJ_txt2nid(p); + if (nid == NID_undef) { + error_f("cannot get nid from string '%.200s'", p); + ret = 0; + break; + } + + p = q + 1; + if (!*p) { + error_f("no data"); + ret = 0; + break; + } + + for (; *p && ISSPACE(*p); p++) + {/*skip space*/} + for (q = token - 1; (q >= p) && ISSPACE(*q); q--) + {/*skip unexpected \n, etc. from end*/} + *++q = 0; + + ret = ssh_X509_NAME_add_entry_by_NID(_name, nid, (u_char*)p, (size_t)(q - p)); + if (!ret) { + break; + } + + p = token; + if (has_more) p++; + } + + free(str); + debug3_f("return %d", ret); + return ret; +} + + +static struct sshkey* +x509key_from_subject(int basetype, const char* _cp) { + const char *subject; + struct sshkey *key; + X509 *x; + + debug3_f("%d, [%.1024s] called", basetype, (_cp ? _cp : "")); + subject = x509key_find_subject(_cp); + if (subject == NULL) + return NULL; + + debug3_f("subject=[%.1024s]", subject); + key = sshkey_new(KEY_UNSPEC); + if (key == NULL) { + error_f("out of memory"); + return NULL; + } + + x = X509_new(); + if (x == NULL) { + error_f("out of memory X509_new()"); + goto err; + } + + + { /*set distinguished name*/ + X509_NAME *xn = X509_get_subject_name(x); + + if (xn == NULL) { + error_f("X.509 certificate without subject"); + goto err; + } + + if (!x509key_str2X509NAME(subject, xn)) { + error_f("x509key_str2X509NAME fail"); + goto err; + } + } + + key->type = basetype; + if (!ssh_x509_set_cert(key, x, NULL)) { + error_f("ssh_x509_set_cert fail"); + goto err; + } + goto done; + +err: + if (x != NULL) + X509_free(x); + if (key != NULL) { + sshkey_free(key); + key = NULL; + } + +done: + debug3_f("return %p", (void*)key); + return key; +} + + +struct sshkey* +X509key_from_subject(const char *pkalg, const char *cp, char **ep) { + struct sshkey *ret; + +{ /* check if public algorithm is with X.509 certificates */ + const SSHX509KeyAlgs *p; + + if (ssh_xkalg_nameind(pkalg, &p, -1) < 0) + return NULL; + + ret = x509key_from_subject(p->basetype, cp); +} + + if (ret != NULL && ep != NULL) { + /* NOTE line with subject lack comment part */ + *ep = (char*)cp + strlen(cp); + } + + return ret; +} + + +struct sshkey* +x509_to_key(X509 *x509) { + struct sshkey *key = NULL; + EVP_PKEY *env_pkey; + int r; + + env_pkey = X509_get_pubkey(x509); + if (env_pkey == NULL) { + error_crypto("X509_get_pubkey"); + return NULL; + } + + r = sshkey_from_pkey(env_pkey, &key); + if (r != 0) goto err; + + (void)ssh_x509_set_cert(key, x509, NULL); + + return key; + +err: + EVP_PKEY_free(env_pkey); + sshkey_free(key); + return NULL; +} + + +int +X509_from_blob(const u_char *blob, size_t blen, X509 **xp) { + int r; + BIO *mbio; + X509 *x; + + if (xp != NULL) *xp = NULL; + + if (blob == NULL) return SSH_ERR_INVALID_ARGUMENT; + if (!(blen > 0)) return SSH_ERR_INVALID_ARGUMENT; + +{ int mlen = (int)blen; + if ((size_t)mlen != blen) return SSH_ERR_INVALID_ARGUMENT; + + mbio = BIO_new_mem_buf((void*)blob, mlen); + if (mbio == NULL) return SSH_ERR_ALLOC_FAIL; +} + + /* read X509 certificate from BIO data */ + x = d2i_X509_bio(mbio, NULL); + if (x == NULL) { + debug3_crypto("d2i_X509_bio"); + r = SSH_ERR_INVALID_FORMAT; + goto done; + } + +{ size_t k = BIO_ctrl_pending(mbio); + if (k > 0) { + error_f("remaining bytes in X.509 blob %d", (int) k); + r = SSH_ERR_UNEXPECTED_TRAILING_DATA; + goto done; + } +} + + if (xp != NULL) { + *xp = x; + x = NULL; + } + r = SSH_ERR_SUCCESS; + +done: + /* This call will walk the chain freeing all the BIOs */ + BIO_free_all(mbio); + X509_free(x); + return r; +} + + +int +X509key_from_blob(const u_char *blob, size_t blen, struct sshkey **keyp) { + int r; + X509 *x = NULL; + struct sshkey *key = NULL; + + if (keyp != NULL) *keyp = NULL; + + r = X509_from_blob(blob, blen, &x); + if (r != SSH_ERR_SUCCESS) return r; + + key = x509_to_key(x); + if (key == NULL) { + X509_free(x); + return SSH_ERR_ALLOC_FAIL; + } + + if (keyp != NULL) + *keyp = key; + else + sshkey_free(key); + + return SSH_ERR_SUCCESS; +} + + +static int +X509key_from_buf2_common(struct sshbuf *b, struct sshkey **keyp, char **pkalgp) { + int r; + u_int nc, no, k; + const SSHX509KeyAlgs *xkalg = NULL; + char *pkalg = NULL; + struct sshkey *key = NULL; + +if ((SSHX_RFC6187_MISSING_KEY_IDENTIFIER & xcompat) == 0) { + /* RFC6187: string "algorithm-identifier" */ + r = sshbuf_get_cstring(b, &pkalg, NULL); + if (r != 0) return SSH_ERR_INVALID_FORMAT; + +{ /* check if algorithm is supported */ + int loc = -1; + while ((loc = ssh_xkalg_nameind(pkalg, &xkalg, loc)) >= 0) { + if (xkalg->chain) break; + } + if (loc < 0) { + free(pkalg); + return SSH_ERR_KEY_TYPE_UNKNOWN; + } +} +} + + /* RFC6187: uint32 certificate-count */ + r = sshbuf_get_u32(b, &nc); + if (r != 0) goto err; + debug3_f("certificate-count: %u", nc); + + if (nc > 100) { + error_f("the number of X.509 certificates exceed limit(%d > 100)", nc); + r = SSH_ERR_INVALID_FORMAT; + goto err; + } + if (nc < 1) { + error_f("at least one X.509 certificate must present"); + r = SSH_ERR_INVALID_FORMAT; + goto err; + } + +{ /* RFC6187: string certificate[1..certificate-count] */ + const u_char *xs; + size_t xlen; + + X509 *x; + STACK_OF(X509) *pchain; + + r = sshbuf_get_string_direct(b, &xs, &xlen); + if (r != SSH_ERR_SUCCESS) goto err; + + r = X509_from_blob(xs, xlen, &x); + if (r != SSH_ERR_SUCCESS) goto err; + + debug3_f("certificate[0]=%p", (void*)x); + + key = x509_to_key(x); + if (key == NULL) { + X509_free(x); + r = SSH_ERR_INVALID_FORMAT; + goto err; + } + + if (xkalg != NULL) { + /* check if key match algorithm */ + if ( + (key->type != xkalg->basetype) || + (key->ecdsa_nid != xkalg->subtype) + ) { + r = SSH_ERR_KEY_TYPE_MISMATCH; + goto err; + } + } else { + /* check if algorithm is supported (compatibility case) */ + if (ssh_xkalg_keyfrmind(key, X509FORMAT_RFC6187, &xkalg, -1) < 0) { + r = SSH_ERR_KEY_TYPE_UNKNOWN; + goto err; + } + } + + if (!check_rsa2048_sha256(xkalg, key)) { + r = SSH_ERR_KEY_LENGTH; + goto err; + } + +{ SSH_X509 *xd = key->x509_data; + + if (xd == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto err; + } + + pchain = sk_X509_new_null(); + if (pchain == NULL) { + error_f("out of memory (chain)"); + r = SSH_ERR_ALLOC_FAIL; + goto err; + } + xd->chain = pchain; +} + + for (k = 1; k < nc; k++) { + r = sshbuf_get_string_direct(b, &xs, &xlen); + if (r != SSH_ERR_SUCCESS) goto err; + + r = X509_from_blob(xs, xlen, &x); + debug3_f("certificate[%d]=%p", k, (void*)x); + if (r != SSH_ERR_SUCCESS) goto err; + + sk_X509_insert(pchain, x, -1 /*last*/); + } +} + + /* RFC6187: uint32 ocsp-response-count */ + r = sshbuf_get_u32(b, &no); + if (r != 0) goto err; + debug3_f("ocsp-response-count: %u", no); + + /* The number of OCSP responses MUST NOT exceed the number of certificates. */ + if (no > nc) { + error_f("the number of OCSP responses(%d) exceed the number of certificates(%d)", no, nc); + r = SSH_ERR_INVALID_FORMAT; + goto err; + } + + /* RFC6187: string ocsp-response[0..ocsp-response-count] */ + for (k = 0; k < no; k++) { + const u_char *os; + r = sshbuf_get_string_direct(b, &os, NULL); + if (r != 0) goto err; + + /* nop */ + } + +{ size_t l = sshbuf_len(b); + if (l > 0) { + error_f("remaining bytes in key blob %zu", l); + r = SSH_ERR_UNEXPECTED_TRAILING_DATA; + } +} + +err: + if (r != SSH_ERR_SUCCESS) { + sshkey_free(key); + free(pkalg); + return r; + } + + if (keyp != NULL) + *keyp = key; + if (pkalgp != NULL) { + /* compatibility: if key identifier is missing */ + if (pkalg == NULL) + pkalg = xstrdup(xkalg->name); + *pkalgp = pkalg; + pkalg = NULL; + } + free(pkalg); + return SSH_ERR_SUCCESS; +} + + +static int +X509key_from_blob2(const char *pkalg, const u_char *blob, size_t blen, struct sshkey **keyp) { + int r; + struct sshkey *key = NULL; + char *xpkalg = NULL; + + if (keyp != NULL) *keyp = NULL; + +{ struct sshbuf *b = sshbuf_from(blob, blen); + if (b == NULL) return SSH_ERR_ALLOC_FAIL; + + r = X509key_from_buf2_common(b, &key, &xpkalg); + sshbuf_free(b); +} + if (r != SSH_ERR_SUCCESS) goto done; + + if (strcmp(pkalg, xpkalg) != 0) { + error_f("public-key algorithm mismatch: expected %.100s extracted %.100s", pkalg, xpkalg); + r = SSH_ERR_KEY_TYPE_MISMATCH; + goto done; + } + + if (keyp != NULL) { + *keyp = key; + key= NULL; + } + +done: + free(xpkalg); + return r; +} + + +static int +x509key_check(const char *file, const char *func, int line, + const struct sshkey *key +) { + SSH_X509 *xd; + + if (key == NULL) { + sshlog_f(file, func, line, SYSLOG_LEVEL_ERROR, + "no key"); + return 0; + } + + xd = key->x509_data; + if (xd == NULL) { + sshlog_f(file, func, line, SYSLOG_LEVEL_ERROR, + "no X.509 identity"); + return 0; + } + + if (xd->cert == NULL) { + sshlog_f(file, func, line, SYSLOG_LEVEL_ERROR, + "no X.509 certificate"); + return 0; + } + + return 1; +} + +#define X509KEY_CHECK(key) \ + x509key_check(__FILE__, __func__, __LINE__, key) + + +static int +sshbuf_put_x509_f( + struct sshbuf *b, X509 *x, + int (*f)(struct sshbuf *, const void *, size_t) +) { + void *p; + int l, k; + int r; + + l = i2d_X509(x, NULL); + p = xmalloc(l); /*fatal on error*/ + { + u_char *q = p; + k = i2d_X509(x, &q); + } + + if (l == k) + r = f(b, p, l); + else + r = SSH_ERR_ALLOC_FAIL; + + free(p); + + return r; +} + + +static inline int +sshbuf_put_x509(struct sshbuf *b, X509 *x) { + return sshbuf_put_x509_f(b, x, sshbuf_put_string); +} + + +int +X509key_encode_identity(const char *pkalg, const struct sshkey *key, struct sshbuf *b) { + const SSHX509KeyAlgs *xkalg; + int ret; + + if (!sshkey_is_x509(key)) + return SSH_ERR_SUCCESS; + + if (ssh_xkalg_nameind(pkalg, &xkalg, -1) < 0) + return SSH_ERR_SUCCESS; + + if (xkalg->chain) { /* RFC6187 format */ + struct sshbuf *d; + + d = sshbuf_new(); + if (d == NULL) + return SSH_ERR_ALLOC_FAIL; + + ret = xkey_to_buf2(xkalg, key, d); + if (ret != SSH_ERR_SUCCESS) + debug3_f("xkey_to_buf2 fail"); + + if (ret == SSH_ERR_SUCCESS) + ret = sshbuf_put_stringb(b, d); + + sshbuf_free(d); + } else + ret = sshbuf_put_x509(b, key->x509_data->cert); + + return ret; +} + + +int +X509key_decode_identity(const char *pkalg, struct sshbuf *b, struct sshkey *k) { + int RFC6187_format; + struct sshkey *tkey = NULL; + int ret; + +{ /* check if public algorithm is with X.509 certificates */ + const SSHX509KeyAlgs *p; + + if (ssh_xkalg_nameind(pkalg, &p, -1) < 0) + return SSH_ERR_SUCCESS; + + RFC6187_format = p->chain; +} + +{ /* fetch X.509 key */ + u_char *blob = NULL; + size_t blen; + + ret = sshbuf_get_string(b, &blob, &blen); + if (ret != SSH_ERR_SUCCESS) goto end_key; + + ret = RFC6187_format + ? X509key_from_blob2(pkalg, blob, blen, &tkey) + : X509key_from_blob(blob, blen, &tkey); +end_key: + free(blob); +} + if (ret == SSH_ERR_SUCCESS) { + SSH_X509_free(k->x509_data); + k->x509_data = tkey->x509_data; + tkey->x509_data = NULL; + } + sshkey_free(tkey); + + return ret; +} + + +void +x509key_move_identity(struct sshkey *from, struct sshkey *to) { + /* Temporary controls for key types based on enumerate. + * + * Caller is responsible to perform all controls before to call this + * method. For instance public key of X.509 certificate has to match + * plain public key. + * NOTE X.509 certificate may contain only distinguished name! + */ + if (!X509KEY_CHECK(from)) return; + + SSH_X509_free(to->x509_data); + to->x509_data = from->x509_data; + from->x509_data = NULL; +} + + +void +x509key_copy_identity(const struct sshkey *from, struct sshkey *to) { + X509 *x; + SSH_X509 *xd; + STACK_OF(X509) *chain; + STACK_OF(X509) *pchain; + int n; + + if (!sshkey_is_x509(from)) return; + + if (!X509KEY_CHECK(from)) + fatal_f("no X.509 identity"); + + xd = to->x509_data; + if (xd) + SSH_X509_free_data(xd); + else { + xd = SSH_X509_new(); /*fatal on error*/ + to->x509_data = xd; + } + + x = X509_dup(from->x509_data->cert); + if (x == NULL) + fatal_f("X509_dup failed"); + xd->cert = x; + + /* legacy keys does not use chain */ + chain = from->x509_data->chain; + if (chain == NULL) + return; + + pchain = sk_X509_new_null(); + if (pchain == NULL) + fatal_f("sk_X509_new_null failed"); + xd->chain = pchain; + + for (n = 0; n < sk_X509_num(chain); n++) { + x = sk_X509_value(chain, n); + x = X509_dup(x); + if (x == NULL) + fatal_f("X509_dup failed"); + sk_X509_insert(pchain, x, -1 /*last*/); + } +} + + +void +x509key_demote(const struct sshkey *k, struct sshkey *pk) { + x509key_copy_identity(k, pk); +} + + +int +X509key_to_buf(const struct sshkey *key, struct sshbuf *b) { + X509 *x; + + /* ensure that caller checks for non-null key argument */ +{ SSH_X509 *xd; + xd = key->x509_data; + if (xd == NULL) return SSH_ERR_INVALID_FORMAT; + if (xd->cert == NULL) return SSH_ERR_INVALID_FORMAT; + x = xd->cert; +} + return sshbuf_put_x509_f(b, x, sshbuf_put); +} + + +static int +xkey_to_buf2(const SSHX509KeyAlgs *xkalg, const struct sshkey *key, struct sshbuf *b) { + STACK_OF(X509) *chain; + int r; + u_int n; + + if (!X509KEY_CHECK(key)) return 0; + + if (!check_rsa2048_sha256(xkalg, key)) + return SSH_ERR_KEY_LENGTH; + + /* RFC6187 key format */ + chain = key->x509_data->chain; + if (chain == NULL) { + /* NOTE Historic key algorithm use only one X.509 + * certificate. Empty chain is protocol error for + * keys in RFC6187 format, but we accept them. + */ + verbose("X.509 certificate chain is not set." + " Remote host may refuse key."); + } + + /* NOTE: sk_num returns -1 if argument is null */ + n = chain ? sk_X509_num(chain) : 0; + +if ((SSHX_RFC6187_MISSING_KEY_IDENTIFIER & xcompat) == 0) { + /* string "algorithm-identifier" */ + r = sshbuf_put_cstring(b, xkalg->name); + if (r != 0) goto end; +} + + /* uint32 certificate-count */ + r = sshbuf_put_u32(b, 1 + n); + if (r != 0) goto end; + +{ /* string certificate[1..certificate-count] */ + X509 *x; + u_int i; + + x = key->x509_data->cert; + r = sshbuf_put_x509(b, x); + if (r != 0) goto end; + for (i = 0; i < n; i++) { + x = sk_X509_value(chain, i); + r = sshbuf_put_x509(b, x); + if (r != 0) goto end; + } +} + + /* uint32 ocsp-response-count */ + r = sshbuf_put_u32(b, 0); + if (r != 0) goto end; + + /* string ocsp-response[0..ocsp-response-count] */ + /* nop */ + +end: + return r; +} + + +char* +x509key_subject(const struct sshkey *key) { + X509_NAME *dn; + + if (!X509KEY_CHECK(key)) return NULL; + + /* match format used in Xkey_write_subject */ + dn = X509_get_subject_name(key->x509_data->cert); + return ssh_X509_NAME_oneline(dn); +} + + +int +x509key_write(const struct sshkey *key, struct sshbuf *b) { + int r; + struct sshbuf *b64; + char *uu = NULL; + + b64 = sshbuf_new(); + if (b64 == NULL) return SSH_ERR_ALLOC_FAIL; + + r = X509key_to_buf(key, b64); + if (r != 0) goto done; + + uu = sshbuf_dtob64_string(b64, 0); + if (uu == NULL) goto done; + + r = sshbuf_putf(b, "%s %s", sshkey_ssh_name(key), uu); + +done: + free(uu); + sshbuf_free(b64); + + return r; +} + + +int +Xkey_write_subject(const char *pkalg, const struct sshkey *key, FILE *f) { + BIO *out; + + if (!X509KEY_CHECK(key)) return 0; + + if (pkalg == NULL) pkalg = sshkey_ssh_name(key); + + out = BIO_new_fp(f, BIO_NOCLOSE); + if (out == NULL) return 0; +#ifdef VMS + { + BIO *tmpbio = BIO_new(BIO_f_linebuffer()); + out = BIO_push(tmpbio, out); + } +#endif + + BIO_puts(out, pkalg); + BIO_puts(out, " Subject:"); + ssh_X509_NAME_print(out, X509_get_subject_name(key->x509_data->cert)); + + BIO_free_all(out); + return 1; +} + + +static int +x509key_load_certs_bio(struct sshkey *key, BIO *bio) { + int ret = 0; + STACK_OF(X509) *chain; + + chain = sk_X509_new_null(); + if (chain == NULL) { + fatal_f("out of memory"); + return -1; /*unreachable code*/ + } + + do { + X509 *x = PEM_read_bio_X509(bio, NULL, NULL, NULL); + if (x == NULL) break; + + sk_X509_insert(chain, x, -1 /*last*/); + } while (1); + debug3_f("loaded %d certificates", sk_X509_num(chain)); + + /* clear OpenSSL "error buffer" */ + ERR_clear_error(); + + key->x509_data->chain = chain; + + x509key_build_chain(key); + + ret = sk_X509_num(chain); + + return ret; +} + + +void +x509key_parse_cert(struct sshkey *key, BIO *bio) { + X509 *x; + SSH_X509 *xd; + + if (key == NULL) return; + + if (!ssh_x509_support_plain_type(key->type)) + return; + + debug3("read X.509 certificate begin"); + x = PEM_read_bio_X509(bio, NULL, NULL, NULL); + if (x == NULL) { + debug3_crypto("PEM_read_bio_X509"); + return; + } + + if (!X509_check_private_key(x, key->pk)) { + fatal("X.509 certificate don't match private key"); + /*unreachable code*/ + } + + xd = key->x509_data = SSH_X509_new(); /*fatal on error*/ + xd->cert = x; + + (void)x509key_load_certs_bio(key, bio); + + debug3("read X.509 certificate done: type %s", sshkey_type(key)); + return; +} + + +void +x509key_load_certs(const char *pkalg, struct sshkey *key, const char *filename) { + size_t len; + + debug3_f("pkalg=%s, filename=%s", pkalg, (filename ? filename : "?!?")); +{ /* check if public algorithm is with X.509 certificates */ + const SSHX509KeyAlgs *p; + + if (ssh_xkalg_nameind(pkalg, &p, -1) < 0) + return; + +#if 0 +/* NOTE always load extra certificates as key may be used in either + * in legacy format or in RFC6187 format! + */ + /* return if public key algorithm is not in RFC6187 format */ + if (!p->chain) + return; +#endif +} + + len = strlen(filename); + if ((len > 9) && + (strcmp (filename + len - 9,"-cert.pub") == 0) + ) return; + if ((len > 4) && + (strcmp (filename + len - 4,".pub") != 0) + ) return; + +{ /* Remove .pub suffix and try to extract certificates from + * "private" key file. Note that for pkcs11 module we may + * have only "public" part. + */ + char file[PATH_MAX]; + + if (strlcpy(file, filename, sizeof(file)) < len) { + fatal_f("length of filename exceed PATH_MAX"); + return; /*unreachable code*/ + } + file[len - 4] = '\0'; + +{ BIO *bio = BIO_new_file(file, "r"); + if (bio != NULL) { + (void)x509key_load_certs_bio(key, bio); + BIO_free_all(bio); + } +} +} + + return; +} + + +void +x509key_build_chain(struct sshkey *key) { + SSH_X509 *x509_data; + STACK_OF(X509)* chain; + + if (pssh_x509store_build_certchain == NULL) return; + + x509_data = key->x509_data; + if (x509_data == NULL) return; + + chain = (*pssh_x509store_build_certchain)(x509_data->cert, x509_data->chain); + if (chain == NULL) return; + + sk_X509_pop_free(x509_data->chain, X509_free); + x509_data->chain = chain; + + debug3_f("length=%d", sk_X509_num(chain)); +} + + +void +x509key_prepare_chain(const char *pkalg, struct sshkey *key) { + + if (pssh_x509store_build_certchain == NULL) return; + +{ + const SSHX509KeyAlgs *xkalg = NULL; + if (ssh_xkalg_nameind(pkalg, &xkalg, -1) < 0) return; + if (!xkalg->chain) return; +} + /* Key will be used with RFC6187 algorithm */ +{ + SSH_X509 *x509_data; + STACK_OF(X509)* chain; + + x509_data = key->x509_data; + if (x509_data == NULL) return; + + if (x509_data->chain != NULL) return; + + chain = (*pssh_x509store_build_certchain)(x509_data->cert, x509_data->chain); + if (chain == NULL) return; + + sk_X509_pop_free(x509_data->chain, X509_free); + x509_data->chain = chain; + + debug3_f("length=%d", sk_X509_num(chain)); +} +} + + +static int +x509key_write_bio_cert(BIO *out, X509 *x509) { + int ret = 0; + + BIO_puts(out, "issuer= "); + ssh_X509_NAME_print(out, X509_get_issuer_name(x509)); + BIO_puts(out, "\n"); + + BIO_puts(out, "subject= "); + ssh_X509_NAME_print(out, X509_get_subject_name(x509)); + BIO_puts(out, "\n"); + + { + const char *alstr = (const char*)X509_alias_get0(x509, NULL); + if (alstr == NULL) alstr = ""; + BIO_puts(out, alstr); + BIO_puts(out, "\n"); + } + + ret = PEM_write_bio_X509(out, x509); + if (!ret) + error_crypto("PEM_write_bio_X509"); + + return ret; +} + + +int/*bool*/ +x509key_write_identity_bio_pem( + BIO *bio, + const struct sshkey *key +) { + int flag = 0; + X509 *x; + STACK_OF(X509) *chain; + int k; + + if (!X509KEY_CHECK(key)) return 0; + + x = key->x509_data->cert; + flag = x509key_write_bio_cert(bio, x); + if (!flag) + goto done; + + chain = key->x509_data->chain; + if (chain == NULL) + goto done; + + for (k = 0; k < sk_X509_num(chain); k++) { + x = sk_X509_value(chain, k); + flag = x509key_write_bio_cert(bio, x); + if (!flag) + goto done; + } + +done: + return flag; +} + + +/* + * We can check only by Subject (Distinguished Name): + * - sshd receive from client only x509 certificate !!! + * - sshadd -d ... send only x509 certificate !!! + * - otherwise key might contain private key + */ +int +ssh_x509_equal(const struct sshkey *a, const struct sshkey *b) { + X509 *xa; + X509 *xb; + + if (!X509KEY_CHECK(a)) return 1; + if (!X509KEY_CHECK(b)) return -1; + + xa = a->x509_data->cert; + xb = b->x509_data->cert; +#if 1 +/* + * We must use own method to compare two X509_NAMEs instead of OpenSSL + * function[s]! See notes before body of "ssh_X509_NAME_cmp()". + */ + { + X509_NAME *nameA = X509_get_subject_name(xa); + X509_NAME *nameB = X509_get_subject_name(xb); + return ssh_X509_NAME_cmp(nameA, nameB); + } +#else + return X509_subject_name_cmp(xa, xb); +#endif +} + + +int +ssh_x509key_type(const char *name) { + const SSHX509KeyAlgs *p; + + if (name == NULL) { + fatal_f("name is NULL"); + return KEY_UNSPEC; /*unreachable code*/ + } + + if (ssh_xkalg_nameind(name, &p, -1) < 0) + return KEY_UNSPEC; + + return p->basetype; +} + + +const char* +ssh_x509key_name(const struct sshkey *k) { + const SSHX509KeyAlgs *p; + int n; + + if (k == NULL) { + fatal_f("key is NULL"); + return NULL; /*unreachable code*/ + } + if (!sshkey_is_x509(k)) return NULL; + + n = ssh_xkalg_keyind(k, &p, -1); + if (n >= 0) return p->name; + + return NULL; +} + + +const char** +Xkey_algoriths(const struct sshkey *key) { + const char **ret; + int n; + + if (key == NULL) return NULL; + + /* array with (n + 1) items, last item is always NULL */ + ret = xmalloc(sizeof(*ret)); /*fatal on error*/ + n = 0; + ret[n] = NULL; + + if (!sshkey_is_x509(key)) goto plain_alg; +{ /* list all X.509 algorithms first */ + const SSHX509KeyAlgs *xkalg; + int loc; + + for ( + loc = ssh_xkalg_keyind(key, &xkalg, -1); + loc >= 0; + loc = ssh_xkalg_keyind(key, &xkalg, loc) + ) { + const char *s = xkalg->name; + int k; + + if (!check_rsa2048_sha256(xkalg, key)) + continue; + + /* avoid duplicates */ + for (k = 0; k < n; k++) { + if (strcmp(s, ret[k]) == 0) + break; + } + if (k < n) continue; + + ret = realloc(ret, sizeof(*ret) * (n + 2)); + if (ret == NULL) return NULL; + ret[n++] = s; + ret[n] = NULL; + } +} + +plain_alg: +{ /* add plain algorithm */ + ret = realloc(ret, sizeof(*ret) * (n + 2)); + if (ret == NULL) return NULL; + + ret[n++] = sshkey_ssh_name_plain(key); + ret[n] = NULL; + + /* add extra algorithms */ +#ifdef HAVE_EVP_SHA256 + switch (key->type) { + case KEY_RSA: { + /* for RSA we also support SHA2 algorithms */ + ret = realloc(ret, sizeof(*ret) * (n + 3)); + if (ret == NULL) return NULL; + + ret[n++] = "rsa-sha2-256"; + ret[n++] = "rsa-sha2-512"; + ret[n] = NULL; + } break; + } +#endif /*def HAVE_EVP_SHA256*/ +} + + return ret; +} + + +static int +ssh_x509_sign( + const SSHX509KeyAlgs *xkalg, ssh_sign_ctx *ctx, + u_char **sigp, size_t *lenp, const u_char *data, size_t datalen +) { + int r; + const struct sshkey *key = ctx->key; + int keylen = 0; + u_char *sigret = NULL; + size_t siglen; + + debug3_f("key alg/type/name: %s/%s/%s", + ctx->alg, sshkey_type(key), sshkey_ssh_name(key)); + debug3_f("compatibility: { 0x%08x, 0x%08x }", + ctx->compat->datafellows, ctx->compat->extra); + + r = sshkey_validate_public(key); + if (r != 0) return r; + + /* compute signature */ + keylen = EVP_PKEY_size(key->pk); + if (keylen <= 0) { + error_f("cannot get key size"); + do_log_crypto_errors(SYSLOG_LEVEL_ERROR); + r = SSH_ERR_LIBCRYPTO_ERROR; + goto done; + } + + /* NOTE: + * allocate extra size as signature like this for ecdsa + * keys contain bytes with size of encoded items + */ + siglen = keylen + 20/*?*/; + sigret = xmalloc(siglen); /*fatal on error*/ + + debug3_f("alg=%.50s, dgst->id=%d", xkalg->name, xkalg->dgst->id); + +{ ssh_evp_md dgst; + + ssh_xkalg_dgst_compat(&dgst, xkalg->dgst, ctx->compat); + +#ifdef HAVE_EVP_DIGESTSIGNINIT /* OpenSSL >= 1.0 */ +{ size_t slen; + if (ssh_pkey_sign(&dgst, key->pk, NULL, &slen, data, datalen) <= 0) { + r = SSH_ERR_LIBCRYPTO_ERROR; + goto done; + } + /* paranoid check */ + if (slen > siglen) { + r = SSH_ERR_INTERNAL_ERROR; + goto done; + } +} +#endif /*def HAVE_EVP_DIGESTSIGNINIT*/ + if (ssh_pkey_sign(&dgst, key->pk, sigret, &siglen, data, datalen) <= 0) { + do_log_crypto_errors(SYSLOG_LEVEL_ERROR); + r = SSH_ERR_LIBCRYPTO_ERROR; + goto done; + } +} + + r = ssh_encode_signature(sigp, lenp, + X509PUBALG_SIGNAME(xkalg), sigret, siglen); + +done: + if (sigret != NULL) { + memset(sigret, 's', keylen+20); + free(sigret); + } + + debug3_f("return %d", r); + return r; +} + + +static int +ssh_x509_verify( + ssh_verify_ctx *ctx, + const u_char *sig, size_t siglen, + const u_char *data, size_t datalen +) { + int r = SSH_ERR_INTERNAL_ERROR; + const struct sshkey *key; + const SSHX509KeyAlgs *xkalg; + int loc; + EVP_PKEY* pubkey; + u_char *sigblob = NULL; + size_t len = 0; + + key = ctx->key; + debug3_f("key alg/type/name: %s/%s/%s", + ctx->alg, sshkey_type(key), sshkey_ssh_name(key)); + debug3_f("compatibility: { 0x%08x, 0x%08x }", + ctx->compat->datafellows, ctx->compat->extra); + + loc = ssh_xkalg_nameind(ctx->alg, &xkalg, -1); + if (loc < 0) { + error_f("cannot handle algorithm" + " '%s' for key type %d[, curve %d]", + ctx->alg, key->type, key->ecdsa_nid); + return SSH_ERR_INVALID_ARGUMENT; + } + + r = sshkey_validate_public(key); + if (r != 0) return r; + + pubkey = X509_get_pubkey(key->x509_data->cert); + if (pubkey == NULL) { + error_f("no 'X.509 public-key'"); + return SSH_ERR_INVALID_ARGUMENT; + } + + /* process signature */ +{ struct sshbuf *buf; + + buf = sshbuf_new(); + if (buf == NULL) { + error_f("out of memory - sshbuf_new"); + return SSH_ERR_ALLOC_FAIL; + } + + r = sshbuf_put(buf, sig, siglen); + if (r != 0) goto end_sign_blob; + + /* check signature name */ +{ u_char *sigformat; + + r = sshbuf_get_string(buf, &sigformat, NULL); + if (r != 0) goto end_sign_blob; + + debug3_f("signature name = %.40s", sigformat); + if (!ssh_is_x509signame(sigformat)) { + error_f("cannot handle signature name %.40s", sigformat); + r = SSH_ERR_INVALID_FORMAT; + } + free(sigformat); +} + if (r != 0) goto end_sign_blob; + + r = sshbuf_get_string(buf, &sigblob, &len); + if (r != 0) goto end_sign_blob; + + /* check consistency */ +{ size_t rlen = sshbuf_len(buf); + if (rlen != 0) { + error_f("remaining bytes in signature %zu", rlen); + r = SSH_ERR_INVALID_FORMAT; + } +} + +end_sign_blob: + sshbuf_free(buf); +} + if (r != 0) goto done; + + /* verify signed data */ +{ int ret; + for (; loc >= 0; loc = ssh_xkalg_nameind(ctx->alg, &xkalg, loc)) { + ssh_evp_md dgst; + + debug3_f("dgst->id=%d, loc=%d", xkalg->dgst->id, loc); + + ssh_xkalg_dgst_compat(&dgst, xkalg->dgst, ctx->compat); + + ret = ssh_pkey_verify(&dgst, pubkey, sigblob, len, data, datalen); + if (ret > 0) break; + + do_log_crypto_errors(SYSLOG_LEVEL_ERROR); + } + if (ret <= 0) { + debug3_f("failed for all digests"); + r = SSH_ERR_SIGNATURE_INVALID; + } +} + +done: + if (sigblob) { + memset(sigblob, 's', len); + free(sigblob); + sigblob = NULL; + } + EVP_PKEY_free(pubkey); + + debug3_f("return %d", r); + return r; +} + + +int +Xkey_sign(ssh_sign_ctx *ctx, + u_char **sigp, size_t *lenp, + const u_char *data, size_t datalen +) { + struct sshkey *key = ctx->key; + const SSHX509KeyAlgs *xkalg; + + if (ctx->alg == NULL) + ctx->alg = sshkey_ssh_name(key); + + /* check if public algorithm is with X.509 certificates */ + if (ssh_xkalg_nameind(ctx->alg, &xkalg, -1) < 0) { + int ret = sshkey_sign(ctx, sigp, lenp, data, datalen); + if (ret == SSH_ERR_LIBCRYPTO_ERROR) + do_log_crypto_errors(SYSLOG_LEVEL_ERROR); + else + debug3_f("return %d", ret); + return ret; + } + +{ + int is_shielded = sshkey_is_shielded(key); + int ret; + + if ((ret = sshkey_unshield_private(key)) != 0) + goto done; + + ret = ssh_x509_sign(xkalg, ctx, sigp, lenp, data, datalen); + + if (is_shielded) { + int r = sshkey_shield_private(key); + if (ret == 0) ret = r; + } + +done: + debug3_f("return %d", ret); + return ret; +} +} + + +int +Xkey_check_sigalg(ssh_sign_ctx *ctx, const u_char *sig, size_t siglen) { + int r; + const SSHX509KeyAlgs *p; + + /* check if public algorithm is with X.509 certificates */ + if (ssh_xkalg_nameind(ctx->alg, &p, -1) < 0) + return sshkey_check_sigtype(sig, siglen, ctx->alg); + +{ char *sigalg = NULL; + const char *expalg; + + r = sshkey_sigtype(sig, siglen, &sigalg); + if (r < 0) goto out; + + expalg = X509PUBALG_SIGNAME(p); + if (strcmp(expalg, sigalg) != 0) { + r = SSH_ERR_SIGN_ALG_UNSUPPORTED; + error("different signature algorithm - expected %s, got %s", + expalg, sigalg); + } + free(sigalg); +} + +out: + return r; +} + + +int +Xkey_verify(ssh_verify_ctx *ctx, + const u_char *sig, size_t siglen, + const u_char *data, size_t dlen +) { + if (ctx->alg == NULL) + ctx->alg = sshkey_ssh_name(ctx->key); + +{ /* check if public algorithm is with X.509 certificates */ + const SSHX509KeyAlgs *p; + + if (ssh_xkalg_nameind(ctx->alg, &p, -1) < 0) { + if (ctx->key->type == KEY_RSA_CERT && + check_compat_fellows(ctx->compat, SSH_BUG_SIGTYPE)) { + ctx->alg = NULL; + } + return sshkey_verify(ctx, sig, siglen, data, dlen); + } +} + + return ssh_x509_verify(ctx, sig, siglen, data, dlen); +} + + +int +xkey_validate_cert(const struct sshkey *k) { + if (!X509KEY_CHECK(k)) + return SSH_ERR_INVALID_ARGUMENT; + + if (pssh_x509store_verify_cert == NULL) { + error_f("pssh_x509store_verify_cert is NULL"); + return SSH_ERR_INTERNAL_ERROR; + } + +{ SSH_X509 *xd = k->x509_data; + return pssh_x509store_verify_cert(xd->cert, xd->chain) > 0 + ? SSH_ERR_SUCCESS + : SSH_ERR_KEY_CERT_INVALID; +} +} + + +int/*bool*/ +ssh_x509_set_cert(struct sshkey *key, X509 *x509, STACK_OF(X509) *untrusted) { + int ret = 0; + SSH_X509 *xd; + + if (key == NULL) { + fatal_f("key is NULL"); + goto done; /*unreachable code*/ + } + +{ int k_type = sshkey_type_plain(key->type); + if (!ssh_x509_support_plain_type(k_type)) { + fatal_f("unsupported key type %d", key->type); + goto done; /*unreachable code*/ + } +} + + xd = key->x509_data; + if (xd != NULL) { + if (xd->cert != NULL) { + fatal_f("X.509 certificate is already set"); + goto done; /*unreachable code*/ + } + } else + xd = key->x509_data = SSH_X509_new(); /*fatal on error*/ + + xd->cert = x509; + + if (untrusted != NULL) { + for (x509 = sk_X509_pop(untrusted); x509 != NULL; x509 = sk_X509_pop(untrusted)) { + sk_X509_push(xd->chain, x509); + } + x509key_build_chain(key); + } + + ret = 1; +done: + return ret; +} + + +int +ssh_x509_cmp_cert(const struct sshkey *key1, const struct sshkey *key2) { + /* only dns.c call this function so skip checks ... + if (!X509KEY_CHECK(key1)) return -1; + if (!X509KEY_CHECK(key2)) return 1; + */ + return X509_cmp(key1->x509_data->cert, key2->x509_data->cert); +} + + +int +Xkey_from_blob(const char *pkalg, const u_char *blob, size_t blen, struct sshkey **keyp) { + int RFC6187_format; + + if (pkalg == NULL) { + error_f("pkalg is NULL"); + return SSH_ERR_INVALID_ARGUMENT; + } + + debug3_f("pkalg='%s', blen=%zu", pkalg, blen); + +{ /* check if public algorithm is with X.509 certificates */ + const SSHX509KeyAlgs *p; + + if (ssh_xkalg_nameind(pkalg, &p, -1) < 0) + return sshkey_from_blob(blob, blen, keyp); + + RFC6187_format = p->chain; +} + return RFC6187_format + ? X509key_from_blob2(pkalg, blob, blen, keyp) + : X509key_from_blob(blob, blen, keyp); +} + + +struct sshkey* +xkey_from_blob(const char *pkalg, const u_char *blob, u_int blen) { + struct sshkey* key; + int r; + + r = Xkey_from_blob(pkalg, blob, (size_t) blen, &key); + + return (r == SSH_ERR_SUCCESS) ? key : NULL; +} + + +int +Xkey_to_blob(const char *pkalg, const struct sshkey *key, u_char **blobp, size_t *lenp) { + const SSHX509KeyAlgs *xkalg; + + if (pkalg == NULL) return SSH_ERR_INVALID_ARGUMENT; + if (key == NULL) return SSH_ERR_INVALID_ARGUMENT; + + if (ssh_xkalg_nameind(pkalg, &xkalg, -1) < 0) + return sshkey_to_blob(key, blobp, lenp); + +{ struct sshbuf *b = sshbuf_new(); + if (b == NULL) return SSH_ERR_ALLOC_FAIL; + +{ int ret = xkalg->chain /* RFC6187 format */ + ? xkey_to_buf2(xkalg, key, b) + : X509key_to_buf(key, b); + if (ret != SSH_ERR_SUCCESS) return ret; +} + +{ size_t len = sshbuf_len(b); + if (lenp != NULL) *lenp = len; + if (blobp != NULL) { + *blobp = xmalloc(len); + memcpy(*blobp, sshbuf_ptr(b), len); + } +} + + sshbuf_free(b); + + return SSH_ERR_SUCCESS; +} +} + + +int +xkey_to_blob(const char *pkalg, const struct sshkey *key, u_char **blobp, u_int *lenp) { + size_t len; + +{ int r = Xkey_to_blob(pkalg, key, blobp, &len); + if (r != SSH_ERR_SUCCESS) return 0; +} + + if (lenp != NULL) *lenp = len; /*safe cast*/ + + return len; +} + + +int +X509key_from_buf(struct sshbuf *b, struct sshkey **keyp) { + int r; + struct sshkey *key; + + if (b == NULL) return SSH_ERR_INVALID_ARGUMENT; + +{ const u_char *blob = sshbuf_ptr(b); + size_t blen = sshbuf_len(b); + + r = X509key_from_blob(blob, blen, &key); + if (r != SSH_ERR_SUCCESS) goto done; +} +{ /* rewind buffer */ + size_t blen = i2d_X509(key->x509_data->cert, NULL); + + r = sshbuf_consume(b, blen); + if (r != SSH_ERR_SUCCESS) goto done; +} + + if (keyp != NULL) { + *keyp = key; + key = NULL; + } + +done: + sshkey_free(key); + return r; +} + + +int +Akey_puts_opts( + const struct sshkey *key, struct sshbuf *b, + enum sshkey_serialize_rep opts +) { + if (!sshkey_is_x509(key)) + return sshkey_puts_opts(key, b, opts); + +{ X509 *x; + SSH_X509 *xd; + + xd = key->x509_data; + if (xd == NULL) return SSH_ERR_INVALID_FORMAT; + + x = xd->cert; + if (x == NULL) return SSH_ERR_INVALID_FORMAT; + + return sshbuf_put_x509(b, x); +} +} + + +int +Akey_gets(struct sshbuf *b, struct sshkey **keyp) { + int r; + +{ const u_char *blob; + size_t blen; + + r = sshbuf_peek_string_direct(b, &blob, &blen); + if (r != 0) return r; + + r = X509key_from_blob(blob, blen, keyp); + if (r != SSH_ERR_INVALID_FORMAT) return r; +} + + return sshkey_froms(b, keyp); +} + + +int +Akey_to_blob(const struct sshkey *key, u_char **blobp, size_t *lenp) { + if (!sshkey_is_x509(key)) + return sshkey_to_blob(key, blobp, lenp); + +{ struct sshbuf *b; + int r; + + b = sshbuf_new(); + if (b == NULL) return SSH_ERR_ALLOC_FAIL; + + r = X509key_to_buf(key, b); + if (r != 0) goto done; + +{ size_t len = sshbuf_len(b); + + if (blobp != NULL) { + u_char *blob = malloc(len); + if (blob == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto done; + } + memmove(blob, sshbuf_ptr(b), len); + *blobp = blob; + } + + if (lenp != NULL) *lenp = len; +} +done: + sshbuf_free(b); + return r; +} +} + + +int +Akey_from_blob(const u_char *blob, size_t blen, struct sshkey **keyp) { + int r = 0; + /* Note specific agent serialization for X.509 keys: + * process_request_identities() + * -> sshkey_puts() //=Akey_puts + * -> to_blob_buf() + * -> X509key_to_buf() + */ + /* for X.509 certificate encoded in DER: 0x30 - SEQUENCE */ + if ((blen > 1) && (blob[0] == 0x30)) { + r = X509key_from_blob(blob, blen, keyp); +#if 0 + /* We will postpone build of chain here. + * If configuration is with IdentityFile it will be tested first + * and corresponding agent key is ignored. If IdentityFile has + * private and public files chain is already build on load. + * Note IdentityFile may point to public file if identity is + * stored into PKCS#11 device - see x509key_prepare_chain use. + */ + if (r == 0) + x509key_build_chain(*keyp); +#endif + return r; + } + + return sshkey_from_blob(blob, blen, keyp); +} + + +int +Xkey_puts(const char *pkalg, const struct sshkey *key, struct sshbuf *b) { + const SSHX509KeyAlgs *xkalg; + int r; + + if (pkalg == NULL) return SSH_ERR_INVALID_ARGUMENT; + if (key == NULL) return SSH_ERR_INVALID_ARGUMENT; + + if (ssh_xkalg_nameind(pkalg, &xkalg, -1) < 0) + return sshkey_puts(key, b); + + if (xkalg->chain) { /* RFC6187 format */ + struct sshbuf *d = sshbuf_new(); + if (d == NULL) return SSH_ERR_ALLOC_FAIL; + + r = xkey_to_buf2(xkalg, key, d); + if (r != SSH_ERR_SUCCESS) + debug3_f("xkey_to_buf2 fail"); + else + r = sshbuf_put_stringb(b, d); + + sshbuf_free(d); + } else + r = sshbuf_put_x509(b, key->x509_data->cert); + + return r; +} + + +int +Xkey_putb(const char *pkalg, const struct sshkey *key, struct sshbuf *b) { + const SSHX509KeyAlgs *xkalg; + + if (pkalg == NULL) return SSH_ERR_INVALID_ARGUMENT; + if (key == NULL) return SSH_ERR_INVALID_ARGUMENT; + + if (ssh_xkalg_nameind(pkalg, &xkalg, -1) < 0) + return sshkey_putb(key, b); + + return xkalg->chain /* RFC6187 format */ + ? xkey_to_buf2(xkalg, key, b) + : X509key_to_buf(key, b); +} + + +int +parse_key_from_blob( + const u_char *blob, size_t blen, + struct sshkey **keyp, char **pkalgp +) { + int r; + +if ((blen > 1) && (blob[0] == 0x30)) { + /* try legacy X.509 keys - blob is an certificate + encoded in DER format: 0x30 - SEQUENCE */ + r = X509key_from_blob(blob, blen, keyp); + if ((r == SSH_ERR_SUCCESS) && (pkalgp != NULL) && (keyp != NULL)) { + const SSHX509KeyAlgs *p; + + if (ssh_xkalg_keyfrmind(*keyp, X509FORMAT_LEGACY, &p, -1) < 0) + return SSH_ERR_KEY_TYPE_UNKNOWN; + + *pkalgp = xstrdup(p->name); + } + if (r != SSH_ERR_INVALID_FORMAT) return r; +} +{ /* try RFC 6187 formats */ + { struct sshbuf *b = sshbuf_from(blob, blen); + if (b == NULL) return SSH_ERR_ALLOC_FAIL; + r = X509key_from_buf2_common(b, keyp, pkalgp); + sshbuf_free(b); + } + + if (r == SSH_ERR_SUCCESS) return r; +} + + /* try non X.509 key formats */ + r = sshkey_from_blob(blob, blen, keyp); + if ((r == SSH_ERR_SUCCESS) && (pkalgp != NULL) && (keyp != NULL)) + *pkalgp = xstrdup(sshkey_ssh_name(*keyp)); + + return r; +} + +int +parse_x509_from_private_fileblob(struct sshbuf *blob, + struct sshkey **keyp +) { + int r = 0; + BIO *mbio; + X509 *x509; + + if (keyp != NULL) *keyp = NULL; + +{ size_t bloblen = sshbuf_len(blob); + int len = (int)bloblen; + /* NOTE -1 is impossible value with buffer */ + if (len <= 0 || (size_t)len != bloblen) + return SSH_ERR_INVALID_ARGUMENT; + /* NOTE constant argument in OpenSSL patch 1.0.2g! */ + mbio = BIO_new_mem_buf((void*)sshbuf_ptr(blob), len); +} + if (mbio == NULL) return SSH_ERR_ALLOC_FAIL; + + x509 = PEM_read_bio_X509(mbio, NULL, NULL, NULL); + if (x509 == NULL) { + r = SSH_ERR_INVALID_FORMAT; + goto err; + } + +{ struct sshkey *key = x509_to_key(x509); + if (key == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto err; + } + if (keyp != NULL) + *keyp = key; + else + sshkey_free(key); +} + +err: + BIO_free_all(mbio); + return r; +} diff -ruN openssh-9.4p1/ssh-x509.h openssh-9.4p1+x509-14.2.1/ssh-x509.h --- openssh-9.4p1/ssh-x509.h 1970-01-01 02:00:00.000000000 +0200 +++ openssh-9.4p1+x509-14.2.1/ssh-x509.h 2023-08-20 10:07:00.000000000 +0300 @@ -0,0 +1,107 @@ +#ifndef SSH_X509_H +#define SSH_X509_H +/* + * Copyright (c) 2002-2019 Roumen Petrov. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "includes.h" + +#include + +#include "sshxkey.h" +#include "sshkey.h" +#include "sshbuf.h" + + +/* + * Method return a key(x509) only with "Subject"("Distinguished Name") ! + */ +struct sshkey* X509key_from_subject(const char *pkalg, const char *cp, char **ep); + + +/* draft-ietf-secsh-transport-12.txt */ +int X509key_from_blob(const u_char *blob, size_t blen, struct sshkey **keyp); + +int X509key_to_buf(const struct sshkey *key, struct sshbuf *b); +int X509key_from_buf(struct sshbuf *b, struct sshkey **keyp); + +int X509key_encode_identity(const char *pkalg, const struct sshkey *key, struct sshbuf *b); +int X509key_decode_identity(const char *pkalg, struct sshbuf *b, struct sshkey *k); + +void x509key_move_identity(struct sshkey *from, struct sshkey *to); +void x509key_copy_identity(const struct sshkey *from, struct sshkey *to); +void x509key_demote(const struct sshkey *k, struct sshkey *pk); + +char* x509key_subject(const struct sshkey *key); + +/* + * Method write base 64 encoded X.509 identity of key. + */ +int x509key_write(const struct sshkey *key, struct sshbuf *b); +/* + * Method write subject of key X.509 certificate. + */ +int Xkey_write_subject(const char *pkalg, const struct sshkey *key, FILE *f); + +void x509key_parse_cert(struct sshkey *key, BIO *bio); +void x509key_load_certs(const char *pkalg, struct sshkey *key, const char *filename); +void x509key_build_chain(struct sshkey *key); +void x509key_prepare_chain(const char *pkalg, struct sshkey *key); + +int/*bool*/ x509key_write_identity_bio_pem(BIO *bio, const struct sshkey *key); + +int ssh_x509_equal(const struct sshkey *a, const struct sshkey *b); + +int ssh_x509key_type(const char *name); +const char* ssh_x509key_name(const struct sshkey *k); + +/* NOTE caller is responsible to ensure that X.509 certificate match private key */ +int/*bool*/ ssh_x509_set_cert(struct sshkey *key, X509 *x509, STACK_OF(X509) *untrusted); +int ssh_x509_cmp_cert(const struct sshkey *key1, const struct sshkey *key2); + + +/* backward compatibility for extended key format support */ +struct sshkey *xkey_from_blob(const char *pkalg, const u_char *blob, u_int blen); + +int xkey_to_blob(const char *pkalg, const struct sshkey *key, u_char **blobp, u_int *lenp); + +int parse_key_from_blob(const u_char *blob, size_t blen, + struct sshkey **keyp, char **pkalgp); +int parse_x509_from_private_fileblob(struct sshbuf *blob, + struct sshkey **keyp); + + +int xkey_validate_cert(const struct sshkey *k); + + +static inline int/*bool*/ +sshkey_is_x509(const struct sshkey *key) { + return (key != NULL) && (key->x509_data != NULL); +} + + +SSH_X509* SSH_X509_new(void); +void SSH_X509_free(SSH_X509* xd); +X509* SSH_X509_get_cert(SSH_X509 *xd); + +#endif /* SSH_X509_H */ diff -ruN openssh-9.4p1/ssh-xkalg.c openssh-9.4p1+x509-14.2.1/ssh-xkalg.c --- openssh-9.4p1/ssh-xkalg.c 1970-01-01 02:00:00.000000000 +0200 +++ openssh-9.4p1+x509-14.2.1/ssh-xkalg.c 2023-08-20 10:07:01.000000000 +0300 @@ -0,0 +1,624 @@ +/* + * Copyright (c) 2005-2022 Roumen Petrov. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "ssh-xkalg.h" +#include +#include +#include + +#include "sshxkey.h" +#include "sshbuf.h" +#include "log.h" +#include "match.h" +#include "myproposal.h" +#include "xmalloc.h" + + +/* SSH X509 public key algorithms*/ +static int x509keyalgs_initialized = 0; +static SSHX509KeyAlgs x509keyalgs[20]; + + +static void +initialize_xkalg(void) { + SSHX509KeyAlgs *p = x509keyalgs; + int k; + + if (x509keyalgs_initialized) return; + +#ifdef TRACE_XKALG +logit("TRACE_XKALG initialize_xkalg:"); +#endif + k = sizeof(x509keyalgs) / sizeof(x509keyalgs[0]); + for (; k > 0; k--, p++) { + p->name = NULL; + p->dgst = NULL; + p->signame = NULL; + p->basetype = KEY_UNSPEC; + p->subtype = -1; + p->chain = 0; + } + x509keyalgs_initialized = 1; +} + + +static void +add_default_xkalg(void) { +#ifdef TRACE_XKALG +logit("TRACE_XKALG add_default_xkalg:"); +#endif + + /* EC public key algorithm: */ + /* - RFC6187: ssh opaque signature */ +# ifdef OPENSSL_HAS_NISTP256 + if (ssh_add_x509key_alg("x509v3-ecdsa-sha2-nistp256,ssh-sha256,ecdsa-sha2-nistp256") < 0) + fatal_f("oops"); +# endif +# ifdef OPENSSL_HAS_NISTP384 + if (ssh_add_x509key_alg("x509v3-ecdsa-sha2-nistp384,ssh-sha384,ecdsa-sha2-nistp384") < 0) + fatal_f("oops"); +# endif +# ifdef OPENSSL_HAS_NISTP521 + if (ssh_add_x509key_alg("x509v3-ecdsa-sha2-nistp521,ssh-sha512,ecdsa-sha2-nistp521") < 0) + fatal_f("oops"); +# endif + + /* RSA public key algorithm: */ + /* - RFC6187 */ +#ifdef HAVE_EVP_SHA256 + if (ssh_add_x509key_alg("x509v3-rsa2048-sha256,rsa2048-sha256,rsa2048-sha256") < 0) + fatal_f("oops"); +#endif + if (ssh_add_x509key_alg("x509v3-ssh-rsa,rsa-sha1,ssh-rsa") < 0) + fatal_f("oops"); + /* - draft-ietf-secsh-transport-NN.txt where NN <= 12 + * does not define explicitly signature format. + * - starting from version 7.1 first is rsa-sha1 + */ + if (ssh_add_x509key_alg("x509v3-sign-rsa,rsa-sha1") < 0) + fatal_f("oops"); +#ifdef OPENSSL_FIPS + if(!FIPS_mode()) +#endif + if (ssh_add_x509key_alg("x509v3-sign-rsa,rsa-md5") < 0) + fatal_f("oops"); + + /* DSA public key algorithm: */ + /* - RFC6187 */ + if (ssh_add_x509key_alg("x509v3-ssh-dss,dss-raw,ssh-dss") < 0) + fatal_f("oops"); + /* compatible with draft-ietf-secsh-transport-NN.txt + * where NN <= 12 + */ + if (ssh_add_x509key_alg("x509v3-sign-dss,dss-asn1") < 0) + fatal_f("oops"); + /* - some secsh implementations incompatible with + * draft-ietf-secsh-transport-NN.txt where NN <= 12 + */ + if (ssh_add_x509key_alg("x509v3-sign-dss,dss-raw") < 0) + fatal_f("oops"); + +#ifdef OPENSSL_HAS_ED25519 + /* NOTE: OPENSSL_HAS_ED25519 implies HAVE_EVP_DIGESTSIGN */ + if (ssh_add_x509key_alg("x509v3-ssh-ed25519,none,ssh-ed25519") < 0) + fatal_f("oops"); +#endif +} + + +void +fill_default_xkalg(void) { + SSHX509KeyAlgs *p = x509keyalgs; + +#ifdef TRACE_XKALG +logit("TRACE_XKALG fill_default_xkalg:"); +#endif + initialize_xkalg(); + if (p[0].name == NULL) add_default_xkalg(); +} + + +static int +ssh_x509key_alg_digest(SSHX509KeyAlgs* p, const char *dgstname) { + int id; + + if (dgstname == NULL) { + fatal_f("dgstname is NULL"); + return(-1); /*unreachable code*/ + } + + if (strcasecmp("rsa-sha1", dgstname) == 0) { + id = SSH_MD_RSA_SHA1; goto done; } + if (strcasecmp("rsa-md5" , dgstname) == 0) { + id = SSH_MD_RSA_MD5; goto done; } +#ifdef HAVE_EVP_SHA256 + if (strcasecmp("rsa2048-sha256", dgstname) == 0) { + id = SSH_MD_RSA_SHA256; goto done; } +#endif + +#ifdef OPENSSL_HAS_NISTP256 + if (strcasecmp("ssh-sha256" , dgstname) == 0) { + id = SSH_MD_EC_SHA256_SSH; goto done; } + if (strcasecmp("sha256" , dgstname) == 0) { + id = SSH_MD_EC_SHA256; goto done; } +#endif +#ifdef OPENSSL_HAS_NISTP384 + if (strcasecmp("ssh-sha384" , dgstname) == 0) { + id = SSH_MD_EC_SHA384_SSH; goto done; + } + if (strcasecmp("sha384" , dgstname) == 0) { + id = SSH_MD_EC_SHA384; goto done; } +#endif +#ifdef OPENSSL_HAS_NISTP521 + if (strcasecmp("ssh-sha512" , dgstname) == 0) { + id = SSH_MD_EC_SHA512_SSH; goto done; + } + if (strcasecmp("sha512" , dgstname) == 0) { + id = SSH_MD_EC_SHA512; goto done; } +#endif + + if (strcasecmp("dss-asn1", dgstname) == 0) { + id = SSH_MD_DSA_SHA1; goto done; } + if (strcasecmp("dss-raw" , dgstname) == 0) { + id = SSH_MD_DSA_RAW; goto done; } + +#ifdef HAVE_EVP_DIGESTSIGN + if (strcasecmp("none", dgstname) == 0) { + id = SSH_MD_NONE; goto done; } +#endif + + return -1; + +done: + p->dgst = ssh_evp_md_find(id); + + return 0; +} + + +int +ssh_add_x509key_alg(const char *data) { + char *name, *mdname, *signame; + SSHX509KeyAlgs* p; + int nid = -1; + + if (data == NULL) { + error_f("data is NULL"); + return(-1); + } + + name = xstrdup(data); /*fatal on error*/ + + mdname = strchr(name, ','); + if (mdname == NULL) { + error_f("cannot parse digest"); + goto err; + } + *mdname++ = '\0'; + + signame = strchr(mdname, ','); + if (signame != NULL) *signame++ = '\0'; + + initialize_xkalg(); + p = x509keyalgs; + { + int k = sizeof(x509keyalgs) / sizeof(x509keyalgs[0]); + + for (; k > 0; k--, p++) { + if (p->name == NULL) break; + } + if (k <= 0) { + error_f("insufficient slots"); + goto err; + } + } + + if (strncmp(name, "x509v3-ecdsa-sha2-", 18) == 0) { + const char *ec_name = name + 18; + + nid = sshkey_curve_name_to_nid(ec_name); + if (nid < 0) { + fatal_f("unsupported curve %s", ec_name); + } + + p->basetype = KEY_ECDSA; + p->chain = 1; + } else +#ifdef HAVE_EVP_SHA256 + if (strcmp(name, "x509v3-rsa2048-sha256") == 0) { + p->basetype = KEY_RSA; + p->chain = 1; + } else +#endif + if (strncmp(name, "x509v3-ssh-rsa", 14) == 0) { + p->basetype = KEY_RSA; + p->chain = 1; + } else + if (strncmp(name, "x509v3-sign-rsa", 15) == 0) { + p->basetype = KEY_RSA; + p->chain = 0; + } else + if (strncmp(name, "x509v3-ssh-dss", 14) == 0) { + p->basetype = KEY_DSA; + p->chain = 1; + } else + if (strncmp(name, "x509v3-sign-dss", 15) == 0) { + p->basetype = KEY_DSA; + p->chain = 0; + } else +#ifdef OPENSSL_HAS_ED25519 + if (strncmp(name, "x509v3-ssh-ed25519", 18) == 0) { + p->basetype = KEY_ED25519; + p->chain = 1; + } else +#endif + { + error_f("unsupported public key algorithm '%s'", name); + goto err; + } + + if (ssh_x509key_alg_digest(p, mdname) < 0) { + error_f("unsupported digest %.50s", mdname); + goto err; + } + +#ifdef OPENSSL_FIPS + if (FIPS_mode()) { + if ((EVP_MD_flags(p->dgst->md()) & EVP_MD_FLAG_FIPS) == 0) { + error_f("%s in not enabled in FIPS mode ", mdname); + goto err; + } + } +#endif + p->name = name; + p->signame = signame; + p->subtype = nid; + + return (1); + +err: + free((void*)name); + return (-1); +} + + +int/*bool*/ +ssh_is_x509signame(const char *signame) { + SSHX509KeyAlgs *xkalg; + int k; + + if (signame == NULL) { + fatal_f("signame is NULL"); + return(0); /*unreachable code*/ + } + + initialize_xkalg(); + xkalg = x509keyalgs; + k = sizeof(x509keyalgs) / sizeof(x509keyalgs[0]); + + for (; k > 0; k--, xkalg++) { + if (xkalg->name == NULL) return(0); + if (strcmp(signame, X509PUBALG_SIGNAME(xkalg)) == 0) return(1); + } + return(0); +} + + +int +ssh_xkalg_nameind(const char *name, const SSHX509KeyAlgs **q, int loc) { + int k, n; + const SSHX509KeyAlgs *p; + + if (name == NULL) return (-1); + + initialize_xkalg(); + k = (loc < 0) ? 0 : (loc + 1); + n = sizeof(x509keyalgs) / sizeof(x509keyalgs[0]); + if (k < n) p = &x509keyalgs[k]; + + for (; k < n; k++, p++) { + if (p->name == NULL) return(-1); + if (strcmp(p->name, name) == 0) { + if (q) *q = p; + return(k); + } + } + return(-1); +} + + +static int +ssh_xkalg_typeind(int type, int subtype, const SSHX509KeyAlgs **q, int loc) { + int k, n; + const SSHX509KeyAlgs *p; + + initialize_xkalg(); + k = (loc < 0) ? 0 : (loc + 1); + n = sizeof(x509keyalgs) / sizeof(x509keyalgs[0]); + if (k < n) p = &x509keyalgs[k]; + + type = sshkey_type_plain(type); + for (; k < n; k++, p++) { + if (p->name == NULL) break; + if (type != p->basetype) continue; + + if ((subtype > 0) && (subtype != p->subtype)) + continue; + + if (q) *q = p; + return(k); + } + return(-1); +} + + +int +ssh_xkalg_keyind(const struct sshkey *key, const SSHX509KeyAlgs **q, int loc) { + return ssh_xkalg_typeind(key->type, key->ecdsa_nid, q, loc); +} + + +int +ssh_xkalg_keyfrmind(const struct sshkey *key, int frm, const SSHX509KeyAlgs **q, int loc) { + + while ((loc = ssh_xkalg_typeind(key->type, key->ecdsa_nid, q, loc)) >= 0) { + int found = 0; + + switch (frm) { + case X509FORMAT_FIRSTMATCH: found = 1; + break; + case X509FORMAT_LEGACY : found = !(*q)->chain; + break; + case X509FORMAT_RFC6187 : found = (*q)->chain; + break; + } + if (found) break; + } + return(loc); +} + + +int +ssh_xkalg_ind(const SSHX509KeyAlgs **q, int loc) { + int k, n; + + initialize_xkalg(); + k = (loc < 0) ? 0 : (loc + 1); + n = sizeof(x509keyalgs) / sizeof(x509keyalgs[0]); + + if (k < n) { + const SSHX509KeyAlgs *p; + + p = &x509keyalgs[k]; + if (p->name != NULL) { + if (q) *q = p; + return(k); + } + } + return(-1); +} + + +static void +ssh_xkalg_list(int type, struct sshbuf *b, const char *sep) { + const SSHX509KeyAlgs *xkalg; + int loc; + int seplen; + + if (b == NULL) { + error_f("buffer is NULL"); + return; + } + +/* +IMPORTANT NOTE: + For every unique "key name" we MUST define unique "key type" +otherwise cannot distinguish them ! +As example structure Kex contain integer attribute "kex_type" +and kex use method "load_host_key" to find hostkey. When client +request hostkey algorithms (comma separated list with names) +server should be able to find first hostkey that match one of them. +Note to "load_host_key" is assigned method "get_hostkey_by_type" +defined in "sshd.c". +*/ + + if (sep == NULL) sep = ","; + seplen = strlen(sep); + + for ( + loc = ssh_xkalg_typeind(type, -1, &xkalg, -1); + loc >= 0; + loc = ssh_xkalg_typeind(type, -1, &xkalg, loc) + ) { + const char *p; + int dupl, k, r; + + /* exclude duplicate names */ + p = xkalg->name; + dupl = 0; + for ( + k = ssh_xkalg_typeind(type, -1, &xkalg, -1); + (k >= 0) && (k < loc); + k = ssh_xkalg_typeind(type, -1, &xkalg, k) + ) { + if (strcmp(p, xkalg->name) == 0) { + dupl = 1; + break; + } + } + if (dupl) continue; + + if (sshbuf_len(b) > 0) { + if ((r = sshbuf_put(b, sep, seplen)) != 0) + fatal_fr(r, "buffer error"); + } + if ((r = sshbuf_put(b, p, strlen(p))) != 0) + fatal_fr(r, "buffer error"); + } +} + + +void +ssh_xkalg_listall(struct sshbuf *b, const char *sep) { + ssh_xkalg_list(KEY_ECDSA, b, sep); + ssh_xkalg_list(KEY_RSA, b, sep); + ssh_xkalg_list(KEY_DSA, b, sep); +#ifdef OPENSSL_HAS_ED25519 + ssh_xkalg_list(KEY_ED25519, b, sep); +#endif +} + + +char* +default_hostkey_algorithms(void) { + struct sshbuf *b; + char *p; + int r; + + b = sshbuf_new(); + if (b == NULL) + fatal_f("sshbuf_new failed"); + + ssh_xkalg_listall(b, ","); + + +{ char *allalgs = sshkey_alg_list(0, 0, 1, ','); + /* NOTE + * - Define KEX_DEFAULT_PK_ALG list only key-based + * algorithms (in order of precedence). + * - Since PKIX-SSH 12.4 KEX_DEFAULT_PK_ALG list even + * unsupported algorithms! + * - Since PKIX-SSH 8.5 ssh-dss is not listed by default. + */ + /* filter unsupported by build */ + p = match_filter_allowlist(KEX_DEFAULT_PK_ALG",ssh-dss", allalgs); + free(allalgs); +} + + if ((r = sshbuf_put(b, ",", 1)) != 0 || + (r = sshbuf_put(b, p, strlen(p))) != 0) + fatal_fr(r, "buffer error"); + + p = xstrdup(sshbuf_ptr(b)); + + sshbuf_free(b); + + return p; +} + + +char* +ssh_get_allnames(char sep, int sigflag, const char* pattern) { + const char **list = NULL;; + int loc; + size_t k, n = 0, len = 0; + + if (pattern == NULL) pattern= "*"; + +{ const SSHX509KeyAlgs *xkalg; + for ( + loc = ssh_xkalg_ind(&xkalg, -1); + loc >= 0; + loc = ssh_xkalg_ind(&xkalg, loc) + ) { + const char *p; + + if (match_pattern_list(xkalg->name, pattern, 0) != 1) + continue; + + p = sigflag ? X509PUBALG_SIGNAME(xkalg) : xkalg->name; + for (k = 0; k < n; k++) { + if (strcmp(p, list[k]) == 0) { + p = NULL; + break; + } + } + if (p == NULL) continue; + + k = n++; + list = realloc(list, n * sizeof(char*)); + if (list == NULL) + fatal_f("realloc fail for xkalg"); + list[k] = p; + len += 1 + strlen(p); + } +} +{ const char *name; + /* + * According RFC8308 protocol extension "server-sig-algs", + * despite of it name, list public key algorithms that the + * server is able to process. + * OpenBSD version is still broken and does not list algorithms + * that use custom certificates. Broken behaviour will be keep + * until is fixed in OpenBSD version. Note that brokenness is + * keep as well in check for allowed keys - see sshconnect2.c + * function try_identity(). + */ + for ( + loc = sshkey_algind(&name, SSHKEY_ALG_PLAINKEY, -1); + loc >= 0; + loc = sshkey_algind(&name, SSHKEY_ALG_PLAINKEY, loc) + ) { + const char *p; + + if (match_pattern_list(name, pattern, 0) != 1) + continue; + + p = name; + for (k = 0; k < n; k++) { + if (strcmp(p, list[k]) == 0) { + p = NULL; + break; + } + } + if (p == NULL) continue; + + k = n++; + list = realloc(list, n * sizeof(char*)); + if (list == NULL) + fatal_f("realloc fail for alg"); + list[k] = p; + len += 1 + strlen(p); + } +} +{ char *s = NULL, *p; + + if (n > 0) { + s = p = malloc(len); + if (s == NULL) + fatal_f("out of memory"); + } + for (k = 0; k < n; k++) { + size_t l = strlen(list[k]); + memmove(p, list[k], l); + p += l; + *p++ = sep; + } + if (n > 0) + *(--p) = '\0'; + + free(list); + return s; +} +} diff -ruN openssh-9.4p1/ssh-xkalg.h openssh-9.4p1+x509-14.2.1/ssh-xkalg.h --- openssh-9.4p1/ssh-xkalg.h 1970-01-01 02:00:00.000000000 +0200 +++ openssh-9.4p1+x509-14.2.1/ssh-xkalg.h 2023-08-20 10:07:00.000000000 +0300 @@ -0,0 +1,64 @@ +#ifndef SSH_XKALG_H +#define SSH_XKALG_H +/* + * Copyright (c) 2005-2022 Roumen Petrov. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "includes.h" + +#include "sshkey.h" + + +typedef struct { + const char *name; + ssh_evp_md *dgst; + const char *signame; + int basetype; + int chain; + int subtype; /* curve nid for EC keys */ +} SSHX509KeyAlgs; +#define X509PUBALG_SIGNAME(p) (p->signame ? p->signame : p->name) + + +void fill_default_xkalg(void); + /* format "name,dgst_name[,sig_name]" */ +int ssh_add_x509key_alg(const char *data); + + +int/*bool*/ ssh_is_x509signame(const char *signame); + +int ssh_xkalg_nameind(const char *name, const SSHX509KeyAlgs **q, int loc); +int ssh_xkalg_keyind(const struct sshkey *key, const SSHX509KeyAlgs **q, int loc); +#define X509FORMAT_FIRSTMATCH 1 +#define X509FORMAT_LEGACY 2 +#define X509FORMAT_RFC6187 3 +int ssh_xkalg_keyfrmind(const struct sshkey *key, int frm, const SSHX509KeyAlgs **q, int loc); +int ssh_xkalg_ind(const SSHX509KeyAlgs **q, int loc); + +void ssh_xkalg_listall(struct sshbuf *b, const char *sep); + +char* default_hostkey_algorithms(void); + +char* ssh_get_allnames(char sep, int sigflag, const char* pattern); + +#endif /* SSH_XKALG_H */ diff -ruN openssh-9.4p1/sshxkey.h openssh-9.4p1+x509-14.2.1/sshxkey.h --- openssh-9.4p1/sshxkey.h 1970-01-01 02:00:00.000000000 +0200 +++ openssh-9.4p1+x509-14.2.1/sshxkey.h 2023-08-20 10:07:00.000000000 +0300 @@ -0,0 +1,96 @@ +#ifndef SSHXKEY_H +#define SSHXKEY_H +/* + * Copyright (c) 2017-2022 Roumen Petrov. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "includes.h" +#include "sshkey.h" +#include "sshbuf.h" + +/* extended key support */ + +const char** Xkey_algoriths(const struct sshkey *k); + +int Xkey_from_blob(const char *pkalg, const u_char *blob, size_t blen, struct sshkey **keyp); +int Xkey_to_blob(const char *pkalg, const struct sshkey *key, u_char **blobp, size_t *lenp); + +int Xkey_puts(const char *pkalg, const struct sshkey *key, struct sshbuf *b); +int Xkey_putb(const char *pkalg, const struct sshkey *key, struct sshbuf *b); + +int Akey_puts_opts(const struct sshkey *key, struct sshbuf *b, enum sshkey_serialize_rep opts); +int Akey_gets(struct sshbuf *b, struct sshkey **keyp); + +int Akey_to_blob(const struct sshkey *key, u_char **blobp, size_t *lenp); +int Akey_from_blob(const u_char *blob, size_t blen, struct sshkey **keyp); + + +int Xkey_sign(ssh_sign_ctx *ctx, u_char **sigp, size_t *lenp, const u_char *data, size_t datalen); +int Xkey_check_sigalg(ssh_sign_ctx *ctx, const u_char *sig, size_t siglen); + + +int Xkey_verify(ssh_verify_ctx *ctx, const u_char *sig, size_t siglen, const u_char *data, size_t dlen); + + +/* extended digest support */ +#define SSH_MD_RSA_MD5 1 +#define SSH_MD_RSA_SHA1 2 +#define SSH_MD_DSA_SHA1 3 /* ASN1 */ +#define SSH_MD_DSA_RAW 4 +#define SSH_MD_EC_SHA256 11 /* ASN1 */ +#define SSH_MD_EC_SHA384 12 /* ASN1 */ +#define SSH_MD_EC_SHA512 13 /* ASN1 */ +#define SSH_MD_EC_SHA256_SSH 20 +#define SSH_MD_EC_SHA384_SSH 21 +#define SSH_MD_EC_SHA512_SSH 22 +#define SSH_MD_RSA_SHA256 23 +#define SSH_MD_RSA_SHA512 24 +#define SSH_MD_NONE 30 + +#ifdef HAVE_EVP_DIGESTSIGNINIT +typedef int (*fSSH_SignFinal)(EVP_MD_CTX *ctx, unsigned char *sig, size_t *siglen); +typedef int (*fSSH_VerifyFinal)(EVP_MD_CTX *ctx, const unsigned char *sig, size_t siglen); +#else +typedef int (*fSSH_SignFinal)(EVP_MD_CTX *ctx, unsigned char *md, size_t *s, EVP_PKEY *pkey); +typedef int (*fSSH_VerifyFinal)(EVP_MD_CTX *ctx, const unsigned char *sigbuf, size_t siglen, EVP_PKEY *pkey); +#endif + +struct ssh_evp_md_st { + int id; + const EVP_MD *(*md)(void); + fSSH_SignFinal SignFinal; + fSSH_VerifyFinal VerifyFinal; +}; + +ssh_evp_md* ssh_evp_md_find(int id); + + +void ssh_xkalg_dgst_compat(ssh_evp_md *dest, const ssh_evp_md *src, ssh_compat *compat); + + +int ssh_pkey_sign(const ssh_evp_md *dgst, EVP_PKEY *privkey, + u_char *sig, size_t *siglen, const u_char *data, size_t datalen); +int ssh_pkey_verify(const ssh_evp_md *dgst, EVP_PKEY *pubkey, + const u_char *sig, size_t siglen, const u_char *data, size_t datalen); + +#endif /* SSHXKEY_H */ diff -ruN openssh-9.4p1/ssh-xmss.c openssh-9.4p1+x509-14.2.1/ssh-xmss.c --- openssh-9.4p1/ssh-xmss.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/ssh-xmss.c 2023-08-20 10:07:01.000000000 +0300 @@ -2,6 +2,7 @@ /* * Copyright (c) 2017 Stefan-Lukas Gazdag. * Copyright (c) 2017 Markus Friedl. + * Copyright (c) 2022 Roumen Petrov. All rights reserved. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -25,9 +26,6 @@ #include #include #include -#ifdef HAVE_STDINT_H -# include -#endif #include #include "log.h" @@ -39,17 +37,87 @@ #include "xmss_fast.h" +static int +sshbuf_read_xmss_name(struct sshbuf *buf, struct sshkey *key) { + int r; + char *xmss_name = NULL; + + r = sshbuf_get_cstring(buf, &xmss_name, NULL); + if (r != 0) return r; + + r = sshkey_xmss_init(key, xmss_name); + + free(xmss_name); + return r; +} + +static inline int +sshbuf_write_xmss_name(struct sshbuf *buf, const struct sshkey *key) { + return sshbuf_put_cstring(buf, key->xmss_name); +} + + +static int +sshbuf_read_pub_xmss(struct sshbuf *buf, struct sshkey *key) { + int r; + u_char *xmss_pk = NULL; + size_t pklen; + + r = sshbuf_get_string(buf, &xmss_pk, &pklen); + if (r != 0) return r; + + if (pklen == 0 || pklen != sshkey_xmss_pklen(key)) { + freezero(xmss_pk, pklen); + return SSH_ERR_INVALID_FORMAT; + } + + key->xmss_pk = xmss_pk; + return 0; +} + +static inline int +sshbuf_write_pub_xmss(struct sshbuf *buf, const struct sshkey *key) { + return sshbuf_put_string(buf, key->xmss_pk, sshkey_xmss_pklen(key)); +} + + +static int +sshbuf_read_priv_xmss(struct sshbuf *buf, struct sshkey *key) { + int r; + u_char *xmss_sk = NULL; + size_t sklen = 0; + + r = sshbuf_get_string(buf, &xmss_sk, &sklen); + if (r != 0) return r; + + if (sklen != sshkey_xmss_sklen(key)) { + freezero(xmss_sk, sklen); + return SSH_ERR_INVALID_FORMAT; + } + + key->xmss_sk = xmss_sk; + return 0; +} + +static inline int +sshbuf_write_priv_xmss(struct sshbuf *buf, const struct sshkey *key) { + return sshbuf_put_string(buf, key->xmss_sk, sshkey_xmss_sklen(key)); +} + + +/* key implementation */ + static void ssh_xmss_cleanup(struct sshkey *k) { freezero(k->xmss_pk, sshkey_xmss_pklen(k)); + k->xmss_pk = NULL; freezero(k->xmss_sk, sshkey_xmss_sklen(k)); + k->xmss_sk = NULL; sshkey_xmss_free_state(k); free(k->xmss_name); - free(k->xmss_filename); - k->xmss_pk = NULL; - k->xmss_sk = NULL; k->xmss_name = NULL; + free(k->xmss_filename); k->xmss_filename = NULL; } @@ -66,7 +134,7 @@ } static int -ssh_xmss_serialize_public(const struct sshkey *key, struct sshbuf *b, +ssh_xmss_serialize_public(const struct sshkey *key, struct sshbuf *buf, enum sshkey_serialize_rep opts) { int r; @@ -74,135 +142,111 @@ if (key->xmss_name == NULL || key->xmss_pk == NULL || sshkey_xmss_pklen(key) == 0) return SSH_ERR_INVALID_ARGUMENT; - if ((r = sshbuf_put_cstring(b, key->xmss_name)) != 0 || - (r = sshbuf_put_string(b, key->xmss_pk, - sshkey_xmss_pklen(key))) != 0 || - (r = sshkey_xmss_serialize_pk_info(key, b, opts)) != 0) - return r; + if ((r = sshbuf_write_xmss_name(buf, key)) != 0 || + (r = sshbuf_write_pub_xmss(buf,key)) != 0 || + (r = sshkey_xmss_serialize_pk_info(key, buf, opts)) != 0) + return r; return 0; } static int -ssh_xmss_serialize_private(const struct sshkey *key, struct sshbuf *b, +ssh_xmss_serialize_private(const struct sshkey *key, struct sshbuf *buf, enum sshkey_serialize_rep opts) { int r; - if (key->xmss_name == NULL) - return SSH_ERR_INVALID_ARGUMENT; - /* Note: can't reuse ssh_xmss_serialize_public because of sk order */ - if ((r = sshbuf_put_cstring(b, key->xmss_name)) != 0 || - (r = sshbuf_put_string(b, key->xmss_pk, - sshkey_xmss_pklen(key))) != 0 || - (r = sshbuf_put_string(b, key->xmss_sk, - sshkey_xmss_sklen(key))) != 0 || - (r = sshkey_xmss_serialize_state_opt(key, b, opts)) != 0) + /* NOTE !cert */ + if ((r = sshbuf_write_xmss_name(buf, key)) != 0 || + (r = sshbuf_write_pub_xmss(buf, key)) != 0 || + (r = sshbuf_write_priv_xmss(buf, key)) != 0 || + (r = sshkey_xmss_serialize_state_opt(key, buf, opts)) != 0) return r; - return 0; } +static void +ssh_xmss_move_public(struct sshkey *from, struct sshkey *to) { + free(to->xmss_pk); + to->xmss_pk = from->xmss_pk; + from->xmss_pk = NULL; + free(to->xmss_state); + to->xmss_state = from->xmss_state; + from->xmss_state = NULL; + free(to->xmss_name); + to->xmss_name = from->xmss_name; + from->xmss_name = NULL; + free(to->xmss_filename); + to->xmss_filename = from->xmss_filename; + from->xmss_filename = NULL; +} + static int ssh_xmss_copy_public(const struct sshkey *from, struct sshkey *to) { - int r = SSH_ERR_INTERNAL_ERROR; - u_int32_t left; - size_t pklen; + int r; if ((r = sshkey_xmss_init(to, from->xmss_name)) != 0) return r; if (from->xmss_pk == NULL) return 0; /* XXX SSH_ERR_INTERNAL_ERROR ? */ - if ((pklen = sshkey_xmss_pklen(from)) == 0 || - sshkey_xmss_pklen(to) != pklen) +{ size_t pklen = sshkey_xmss_pklen(from); + if (pklen == 0 || sshkey_xmss_pklen(to) != pklen) return SSH_ERR_INTERNAL_ERROR; if ((to->xmss_pk = malloc(pklen)) == NULL) return SSH_ERR_ALLOC_FAIL; memcpy(to->xmss_pk, from->xmss_pk, pklen); - /* simulate number of signatures left on pubkey */ - left = sshkey_xmss_signatures_left(from); +} +{ /* simulate number of signatures left on pubkey */ + u_int32_t left = sshkey_xmss_signatures_left(from); if (left) sshkey_xmss_enable_maxsign(to, left); +} return 0; } static int -ssh_xmss_deserialize_public(const char *ktype, struct sshbuf *b, +ssh_xmss_deserialize_public(const char *pkalg, struct sshbuf *buf, struct sshkey *key) { - size_t len = 0; - char *xmss_name = NULL; - u_char *pk = NULL; - int ret = SSH_ERR_INTERNAL_ERROR; + int r; - if ((ret = sshbuf_get_cstring(b, &xmss_name, NULL)) != 0) - goto out; - if ((ret = sshkey_xmss_init(key, xmss_name)) != 0) - goto out; - if ((ret = sshbuf_get_string(b, &pk, &len)) != 0) - goto out; - if (len == 0 || len != sshkey_xmss_pklen(key)) { - ret = SSH_ERR_INVALID_FORMAT; - goto out; + UNUSED(pkalg); + if ((r = sshbuf_read_xmss_name(buf, key)) != 0 || + (r = sshbuf_read_pub_xmss(buf, key))) + return r; + + if (!sshkey_is_cert(key)) { + if ((r = sshkey_xmss_deserialize_pk_info(key, buf)) != 0) + return r; } - key->xmss_pk = pk; - pk = NULL; - if (!sshkey_is_cert(key) && - (ret = sshkey_xmss_deserialize_pk_info(key, b)) != 0) - goto out; - /* success */ - ret = 0; - out: - free(xmss_name); - freezero(pk, len); - return ret; + return 0; } static int -ssh_xmss_deserialize_private(const char *ktype, struct sshbuf *b, +ssh_xmss_deserialize_private(const char *pkalg, struct sshbuf *buf, struct sshkey *key) { int r; - char *xmss_name = NULL; - size_t pklen = 0, sklen = 0; - u_char *xmss_pk = NULL, *xmss_sk = NULL; - /* Note: can't reuse ssh_xmss_deserialize_public because of sk order */ - if ((r = sshbuf_get_cstring(b, &xmss_name, NULL)) != 0 || - (r = sshbuf_get_string(b, &xmss_pk, &pklen)) != 0 || - (r = sshbuf_get_string(b, &xmss_sk, &sklen)) != 0) - goto out; - if (!sshkey_is_cert(key) && - (r = sshkey_xmss_init(key, xmss_name)) != 0) - goto out; - if (pklen != sshkey_xmss_pklen(key) || - sklen != sshkey_xmss_sklen(key)) { - r = SSH_ERR_INVALID_FORMAT; - goto out; - } - key->xmss_pk = xmss_pk; - key->xmss_sk = xmss_sk; - xmss_pk = xmss_sk = NULL; + UNUSED(pkalg); + /* NOTE !cert */ + if ((r = sshbuf_read_xmss_name(buf, key)) != 0 || + (r = sshbuf_read_pub_xmss(buf, key)) != 0 || + (r = sshbuf_read_priv_xmss(buf, key)) != 0 || /* optional internal state */ - if ((r = sshkey_xmss_deserialize_state_opt(key, b)) != 0) - goto out; - /* success */ - r = 0; - out: - free(xmss_name); - freezero(xmss_pk, pklen); - freezero(xmss_sk, sklen); - return r; + (r = sshkey_xmss_deserialize_state_opt(key, buf) != 0)) + return r; + return 0; } static int -ssh_xmss_sign(struct sshkey *key, +ssh_xmss_sign(const ssh_sign_ctx *ctx, u_char **sigp, size_t *lenp, - const u_char *data, size_t datalen, - const char *alg, const char *sk_provider, const char *sk_pin, u_int compat) + const u_char *data, size_t datalen) { + const struct sshkey *key = ctx->key; u_char *sig = NULL; size_t slen = 0, len = 0, required_siglen; unsigned long long smlen; @@ -256,10 +300,8 @@ out: if ((ret = sshkey_xmss_update_state(key, 1)) != 0) { /* discard signature since we cannot update the state */ - if (r == 0 && sigp != NULL && *sigp != NULL) { - explicit_bzero(*sigp, len); - free(*sigp); - } + if (r == 0 && sigp != NULL && *sigp != NULL) + freezero(*sigp, len); if (sigp != NULL) *sigp = NULL; if (lenp != NULL) @@ -274,11 +316,11 @@ } static int -ssh_xmss_verify(const struct sshkey *key, +ssh_xmss_verify(const ssh_verify_ctx *ctx, const u_char *sig, size_t siglen, - const u_char *data, size_t dlen, const char *alg, u_int compat, - struct sshkey_sig_details **detailsp) + const u_char *data, size_t dlen) { + const struct sshkey *key = ctx->key; struct sshbuf *b = NULL; char *ktype = NULL; const u_char *sigblob; @@ -350,17 +392,18 @@ static const struct sshkey_impl_funcs sshkey_xmss_funcs = { /* .size = */ NULL, - /* .alloc = */ NULL, + /* .alloc = NULL, */ /* .cleanup = */ ssh_xmss_cleanup, /* .equal = */ ssh_xmss_equal, - /* .ssh_serialize_public = */ ssh_xmss_serialize_public, - /* .ssh_deserialize_public = */ ssh_xmss_deserialize_public, - /* .ssh_serialize_private = */ ssh_xmss_serialize_private, - /* .ssh_deserialize_private = */ ssh_xmss_deserialize_private, + /* .serialize_public = */ ssh_xmss_serialize_public, + /* .deserialize_public = */ ssh_xmss_deserialize_public, + /* .serialize_private = */ ssh_xmss_serialize_private, + /* .deserialize_private = */ ssh_xmss_deserialize_private, /* .generate = */ sshkey_xmss_generate_private_key, + /* .move_public = */ ssh_xmss_move_public, /* .copy_public = */ ssh_xmss_copy_public, /* .sign = */ ssh_xmss_sign, - /* .verify = */ ssh_xmss_verify, + /* .verify = */ ssh_xmss_verify }; const struct sshkey_impl sshkey_xmss_impl = { @@ -372,7 +415,7 @@ /* .cert = */ 0, /* .sigonly = */ 0, /* .keybits = */ 256, - /* .funcs = */ &sshkey_xmss_funcs, + /* .funcs = */ &sshkey_xmss_funcs }; const struct sshkey_impl sshkey_xmss_cert_impl = { @@ -384,6 +427,10 @@ /* .cert = */ 1, /* .sigonly = */ 0, /* .keybits = */ 256, - /* .funcs = */ &sshkey_xmss_funcs, + /* .funcs = */ &sshkey_xmss_funcs }; +#else + +typedef int ssh_xmss_empty_translation_unit; + #endif /* WITH_XMSS */ diff -ruN openssh-9.4p1/tests/CA/1-cre_cadb.sh openssh-9.4p1+x509-14.2.1/tests/CA/1-cre_cadb.sh --- openssh-9.4p1/tests/CA/1-cre_cadb.sh 1970-01-01 02:00:00.000000000 +0200 +++ openssh-9.4p1+x509-14.2.1/tests/CA/1-cre_cadb.sh 2023-08-20 10:07:00.000000000 +0300 @@ -0,0 +1,433 @@ +#! /bin/sh +# Copyright (c) 2002-2023 Roumen Petrov, Sofia, Bulgaria +# All rights reserved. +# +# Redistribution and use of this script, with or without modification, is +# permitted provided that the following conditions are met: +# +# 1. Redistributions of this script must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED +# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +# EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# DESCRIPTION: Create a new certificate authority config and database. +# + +CWD=`pwd` +SCRIPTDIR=`echo $0 | sed 's/1-cre_cadb.sh$//'` +. "${SCRIPTDIR}config" +. "${SCRIPTDIR}functions" + +# === +# args: +# $1 - type +# $2 - policy section +echo_CA_section_start () { + printf '\n\n[ ca_test_%s ]\n' "$1" +cat < /dev/null ; then + port=`expr $port + 1` + printf ",OCSP;URI:http://$SSHD_LISTENADDRESS:$port" + fi + if expr "$SSH_CAKEY_TYPES" : .*ed25519 > /dev/null ; then + port=`expr $port + 1` + printf ",OCSP;URI:http://$SSHD_LISTENADDRESS:$port" + fi + if expr "$SSH_CAKEY_TYPES" : .*ed448 > /dev/null ; then + port=`expr $port + 1` + printf ",OCSP;URI:http://$SSHD_LISTENADDRESS:$port" + fi +) + printf "\n" +fi +} + + +# === +cre_config () { +cat << EOF > "$1" +# Where everything is kept: +dir = $SSH_CAROOT + +[ ca ] +#md5 is not allowed in FIPSmode +#default_ca = ca_test_rsa_md5 +default_ca = ca_test_rsa_sha1 + + +# For the CA policy +[ policy_match ] +countryName = match +stateOrProvinceName = match +organizationName = match +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +[ ca_policy_match ] +countryName = match +stateOrProvinceName = match +localityName = match +organizationName = match +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + + +[ req ] +default_bits = 1024 +distinguished_name = req_distinguished_name +attributes = req_attributes +#prompt = no +#string_mask = MASK: | nombstr | pkix | utf8only | default(=0xFFFFFFFFL) +string_mask = utf8only +utf8 = yes + +# The extensions to add to a certificate request: +#???req_extensions = usr_cert + + +[ req_distinguished_name ] +countryName = Country Name (2 letter code) +countryName_default = $SSH_DN_C +countryName_min = 2 +countryName_max = 2 + +stateOrProvinceName = State or Province Name (full name) +stateOrProvinceName_default = $SSH_DN_ST + +localityName = Locality Name (eg, city) +localityName_default = $SSH_DN_L + +0.organizationName = Organization Name (eg, company) +0.organizationName_default = $SSH_DN_O + +0.organizationalUnitName = Organizational Unit1 Name (eg, section1 - optional) +0.organizationalUnitName_default = ${SSH_DN_OU}-1 + +1.organizationalUnitName = Organizational Unit2 Name (eg, section2 - optional) +1.organizationalUnitName_default = ${SSH_DN_OU}-2 + +2.organizationalUnitName = Organizational Unit3 Name (eg, section3 - optional) +2.organizationalUnitName_default = ${SSH_DN_OU}-3 + +commonName = Common Name (eg, YOUR name) +commonName_min = 2 +commonName_max = 64 + +emailAddress = Email Address (optional) +emailAddress_max = 40 +emailAddress_default = $SSH_DN_EM + + +[ req_attributes ] +challengePassword = A challenge password +challengePassword_min = 4 +challengePassword_max = 20 + + +[ ca_root_cert ] +# PKIX recommendation. + +# This is what PKIX recommends but some broken software chokes on critical +# extensions. +#basicConstraints = critical,CA:true +# So we do this instead. + +# As we generate test CA we could comment next line. +basicConstraints=CA:true + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Test CA Root Certificate" + +# Key usage: this is typical for a CA certificate. However since it will +# prevent it being used as an test self-signed certificate it is best +# left out by default. +# Since we verify CRL signatures cRLSign must present +keyUsage = keyCertSign, cRLSign + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid:always,issuer:always + + +[ ca_cert ] +# PKIX recommendation. + +# This is what PKIX recommends but some broken software chokes on critical +# extensions. +#basicConstraints = critical,CA:true +# So we do this instead. + +# As we generate test CA we could comment next line. +basicConstraints=CA:true + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Test CA Certificate" + +# Key usage: this is typical for a CA certificate. However since it will +# prevent it being used as an test self-signed certificate it is best +# left out by default. +# Since we verify CRL signatures cRLSign must present +keyUsage = keyCertSign, cRLSign + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid:always,issuer:always + +# To test CRL presence this extension should exist +# NOTE: Some OpenSSL compatible libraries choke on next line: +#crlDistributionPoints = URI:attribute_only_exist +# NOTE: As work-around for broken OpenSSL compatible libraries +# use syntax with authority. +crlDistributionPoints = URI:none://attribute_only_exist + +EOF + + +# X.509 extensions: SSH client certificates +cat << EOF >> "$1" + + +[ usr_cert ] +# These extensions are added when 'ca' signs a request. +basicConstraints = CA:false +nsCertType = client, email + +# This is typical in keyUsage for a client certificate. +# keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Test Client Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid,issuer:always +EOF + +echo_CA_ocsp_options >> "$1" + + +# X.509 extensions: SSH server certificates +cat << EOF >> "$1" + + +[ srv_cert ] +# These extensions are added when 'ca' signs a request. +basicConstraints = CA:false + +# To test hostbased authentication we need +# following certificate purposes: +nsCertType = server,client +# Normal for server certificate is: +#nsCertType = server +# but in last case me must disable check of certificate purposes +# in sshd_config otherwise hostbased fail. + +# This is typical in keyUsage for a client certificate. +# keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Test Server Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid,issuer:always + +# Some SSH clients require server certificate to contain +# correct alternate name of type DNS (FQDN) +subjectAltName = DNS:localhost +EOF + +echo_CA_ocsp_options >> "$1" + + +# X.509 extensions: SSH self-issued certificates +cat << EOF >> "$1" + + +[ self_cert ] +# These extensions are added when 'ca' signs a request. +basicConstraints = CA:false +nsCertType = client, email + +# This is typical in keyUsage for a client certificate. +# keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Test Client Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid,issuer:always +EOF + +echo_CA_ocsp_options >> "$1" + + +# X.509 extensions: OCSP Validator certificates +if $SSH_OCSP_ENABLED ; then +cat << EOF >> "$1" + + +[ ocsp_cert ] +# These extensions are added when 'ca' signs a request. +basicConstraints = CA:false + +# Normal for validator certificate is: +nsCertType = objsign + +# This is typical in keyUsage for a validator certificate. +keyUsage = nonRepudiation, digitalSignature + +# This should present for a validator certificate. +extendedKeyUsage = OCSPSigning + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Test OCSP Responder Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid,issuer:always +EOF +fi + + +echo_CA_section root ca_policy_match sha1 root0 root0 >> "$1" + +for DIGEST in $RSA_DIGEST_LIST ; do + echo_CA_section rsa_$DIGEST policy_match $DIGEST rsa rsa_$DIGEST >> "$1" +done + +if expr "$SSH_CAKEY_TYPES" : .*dsa > /dev/null ; then + echo_CA_section dsa policy_match sha1 dsa dsa >> "$1" +fi + +if expr "$SSH_CAKEY_TYPES" : .*ed25519 > /dev/null ; then + echo_CA_section ed25519 policy_match null ed25519 ed25519 >> "$1" +fi + +if expr "$SSH_CAKEY_TYPES" : .*ed448 > /dev/null ; then + echo_CA_section ed448 policy_match null ed448 ed448 >> "$1" +fi +} + + +# === +cre_db () { +( + var="${SSH_CAROOT}" + + if test ! -d "$var"; then + mkdir -p "$var" || exit $? + else + count=`getNextDirName "${var}"` || exit $? + if test -d "${var}"; then + printf '%s' "saving old directory as ${attn}${var}.${warn}${count}${norm} ... " + mv "${var}" "${var}.${count}"; show_status $? || exit $? + fi + fi + + mkdir -p "$var" && + mkdir "$var/crt" && + mkdir "$var/crl" || + exit $? + + create_empty_file "$var/index-root.txt" || exit $? + + for type in ${SSH_SIGN_TYPES}; do + create_empty_file "$var/index-${type}.txt" || exit $? + done + + mkdir "$var/newcerts" && + echo '200402160906000001' > "$var/serial" +) +} + + +# === + +cre_config "${TMPDIR}/${CACONFIG}" && +cre_db && +update_file "${TMPDIR}/${CACONFIG}" "${SSH_CACFGFILE}"; retval=$? + +show_status $retval "${extd}Creating${norm} ${warn}TEST${norm} ${attn}Certificate Authority Database${norm}" diff -ruN openssh-9.4p1/tests/CA/2-cre_cakeys.sh openssh-9.4p1+x509-14.2.1/tests/CA/2-cre_cakeys.sh --- openssh-9.4p1/tests/CA/2-cre_cakeys.sh 1970-01-01 02:00:00.000000000 +0200 +++ openssh-9.4p1+x509-14.2.1/tests/CA/2-cre_cakeys.sh 2023-08-20 10:07:00.000000000 +0300 @@ -0,0 +1,427 @@ +#! /bin/sh +# Copyright (c) 2002-2023 Roumen Petrov, Sofia, Bulgaria +# All rights reserved. +# +# Redistribution and use of this script, with or without modification, is +# permitted provided that the following conditions are met: +# +# 1. Redistributions of this script must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED +# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +# EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# DESCRIPTION: Create "Test Certificate Authority" private keys and certificates. +# + +CWD=`pwd` +SCRIPTDIR=`echo $0 | sed 's/2-cre_cakeys.sh$//'` +. "${SCRIPTDIR}config" +. "${SCRIPTDIR}functions" + + +CA_LOG="$CWD/ca-2.log" +create_empty_file .delmy && +update_file .delmy "$CA_LOG" > /dev/null || exit $? + + +# === +top_srcdir=`cd $SCRIPTDIR/../..; pwd` + +install_sh () { + $top_srcdir/install-sh ${1+"$@"} +} + + +# === +echo_SSH_CA_DN () { +cat < "$2" + show_status $? || return $? + + rm -f "$1" + return 0 +} + + +# === +#args: +# $1 - key file +# $2 - key algorithm +# NOTE: available in OpenSSL >= 1.0.0 +gen_pkey () { +( umask 077 + + rm -f "$1" 2>/dev/null + + if $openssl_nopkcs8_keys ; then + rm -f "$1"-trad 2>/dev/null + $OPENSSL genpkey -algorithm $2 \ + -out "$1"-trad && + $OPENSSL pkcs8 -topk8 -v2 aes256 -in "$1"-trad \ + -out "$1" -passout pass:$KEY_PASS && + rm "$1"-trad + else + $OPENSSL genpkey -algorithm $2 \ + -out "$1" -pass pass:$KEY_PASS -aes-128-cbc + fi +) 2>> "$CA_LOG" +} + + +# === +#args: +# $1 - rsa keyfile +gen_rsa_key () { +( umask 077 + + rm -f "$1" 2>/dev/null + + if $openssl_use_pkey ; then + $OPENSSL genpkey -algorithm RSA \ + -out "$1" -pass pass:$KEY_PASS -aes-128-cbc \ + -pkeyopt rsa_keygen_bits:1024 + return $? + fi + + if $openssl_nopkcs8_keys ; then + rm -f "$1"-trad 2>/dev/null + $OPENSSL genrsa \ + -out "$1"-trad 1024 && + $OPENSSL pkcs8 -topk8 \ + -in "$1"-trad \ + -out "$1" -passout pass:$KEY_PASS \ + -v1 PBE-SHA1-3DES && + rm "$1"-trad + else + $OPENSSL genrsa -des3 \ + -passout pass:$KEY_PASS \ + -out "$1" 1024 + fi +) 2>> "$CA_LOG" +} + + +# === +cre_root () { + gen_rsa_key "$TMPDIR/$CAKEY_PREFIX"-root0.key \ + ; show_status $? "generating ${extd}TEST ROOT CA${norm} ${attn}rsa${norm} private key" \ + || return $? + + echo_SSH_CAROOT_DN "0" | \ + $OPENSSL req -config "$SSH_CACFGFILE" \ + -new -x509 \ + -days $SSH_CACERTDAYS \ + -key "$TMPDIR/$CAKEY_PREFIX-root0.key" -passin pass:$KEY_PASS \ + -sha1 \ + -out "$TMPDIR/$CAKEY_PREFIX-root0.crt" \ + -extensions ca_root_cert \ + 2>> "$CA_LOG" \ + ; show_status $? "generating ${extd}TEST CA${norm} ${attn}root${norm} certificate" \ + || return $? + + F="$CAKEY_PREFIX"-root0.key + update_file "$TMPDIR/$F" "$SSH_CAROOT/keys/$F" + + F="$CAKEY_PREFIX"-root0.crt + move_as_trusted_x509 "$TMPDIR/$F" "$SSH_CAROOT/crt/$F.pem" +} + + +# === +gen_rsa () { + gen_rsa_key "$TMPDIR/$CAKEY_PREFIX"-rsa.key \ + ; show_status $? "generating ${extd}TEST CA${norm} ${attn}rsa${norm} private key" +} + + +# === +#args: +# $1 - dsa parameter file +get_dsa_prm () { +( umask 077 + + rm -f "$1" 2>/dev/null + + if $openssl_use_pkey ; then + $OPENSSL genpkey -genparam -algorithm DSA \ + -out "$1" -pkeyopt dsa_paramgen_bits:1024 + else + $OPENSSL dsaparam $DSA_OPT \ + -out "$1" 1024 + fi +) 2>> "$CA_LOG" +} + +# === +#args: +# $1 - dsa keyfile +# $2 - dsa parameter file +gen_dsa_key () { +( umask 077 + + rm -f "$1" 2>/dev/null + + if $openssl_use_pkey ; then + $OPENSSL genpkey -paramfile "$2" \ + -out "$1" -pass pass:$KEY_PASS -aes-128-cbc + return $? + fi + + if $openssl_nopkcs8_keys ; then + rm -f "$1"-trad 2>/dev/null + $OPENSSL gendsa \ + -out "$1"-trad "$2" && + $OPENSSL pkcs8 -topk8 \ + -in "$1"-trad \ + -out "$1" -passout pass:$KEY_PASS \ + -v1 PBE-SHA1-3DES && + rm "$1"-trad + else + $OPENSSL gendsa -des3 \ + -passout pass:$KEY_PASS \ + -out "$1" "$2" + fi +) 2>> "$CA_LOG" +} + + +# === +gen_dsa () { + get_dsa_prm \ + "$TMPDIR/$CAKEY_PREFIX-dsa.prm" \ + ; show_status $? "generating ${extd}DSA parameter file${norm}" + + gen_dsa_key \ + "$TMPDIR/$CAKEY_PREFIX"-dsa.key \ + "$TMPDIR/$CAKEY_PREFIX"-dsa.prm \ + ; show_status $? "generating ${extd}TEST CA${norm} ${attn}dsa${norm} private key" +} + + +# === +gen_ed25519 () { + expr "$SSH_CAKEY_TYPES" : .*ed25519 > /dev/null || return 0 + gen_pkey "$TMPDIR/$CAKEY_PREFIX"-ed25519.key ED25519 \ + ; show_status $? "generating ${extd}TEST CA${norm} ${attn}ed25519${norm} private key" +} + + +gen_ed448() { + expr "$SSH_CAKEY_TYPES" : .*ed448 > /dev/null || return 0 + gen_pkey "$TMPDIR/$CAKEY_PREFIX"-ed448.key ED448 \ + ; show_status $? "generating ${extd}TEST CA${norm} ${attn}ed448${norm} private key" +} + + +# === +cre_crt () { +for type in $SSH_SIGN_TYPES; do + TMP_CRT_FILE="$TMPDIR/$CAKEY_PREFIX-$type.crt" + TMP_CSR_FILE="$TMPDIR/$CAKEY_PREFIX-$type.csr" + + rm -f "$TMP_CRT_FILE" 2>/dev/null + + case $type in + *rsa*) keyfile="$TMPDIR/$CAKEY_PREFIX"-rsa.key;; + *dsa*) keyfile="$TMPDIR/$CAKEY_PREFIX"-dsa.key;; + *ed25519*) keyfile="$TMPDIR/$CAKEY_PREFIX"-ed25519.key;; + *ed448*) keyfile="$TMPDIR/$CAKEY_PREFIX"-ed448.key;; + *) return 99;; + esac + + echo_SSH_CA_DN "$type" | + $OPENSSL req -config "$SSH_CACFGFILE" \ + -new \ + -key "$keyfile" -passin pass:$KEY_PASS \ + -out "$TMP_CSR_FILE" \ + 2>> "$CA_LOG" \ + ; show_status $? "generating ${extd}TEST CA${norm} ${attn}${type}${norm} request" \ + || return $? + + $OPENSSL ca -config "$SSH_CACFGFILE" \ + -batch \ + -in "$TMP_CSR_FILE" \ + -name "ca_test_root" \ + -passin pass:$KEY_PASS \ + -out "$TMP_CRT_FILE" \ + -extensions ca_cert \ + 2>> "$CA_LOG" \ + ; show_status $? "generating ${extd}TEST CA${norm} ${attn}${type}${norm} certificate" || \ + { retval=$? + printf '%s' "${warn}" + grep 'ERROR:' "$CA_LOG" + printf '%s' "${norm}" + rm -f "$TMP_CSR_FILE" + rm -f "$TMP_CRT_FILE" + return $retval + } + + sync + $OPENSSL verify \ + -CAfile "$SSH_CAROOT/crt/$CAKEY_PREFIX-root0.crt.pem" \ + "$TMP_CRT_FILE" \ + ; retval=$? + # exit code always is 0 :( + + rm -f "$TMP_CSR_FILE" + +done + return $retval +} + + +# === +crt2bundle () { +( + val="$1" + test -z "$val" && { echo ${warn}missing DN${norm} >&2; return 1; } + + echo + echo $val + echo $val | sed -e 's/./=/g' + cat "$2" +) +} + + +# === +cre_dirs () { + install_sh -d "$SSH_CAROOT" && + install_sh -d -m 700 "$SSH_CAROOT/keys" && + install_sh -d "$SSH_CAROOT/crt" +} + + +install () { +( + update_file "$TMPDIR/${CAKEY_PREFIX}-dsa.prm" "$SSH_CAROOT/${CAKEY_PREFIX}-dsa.prm" || exit $? + + for type in $SSH_CAKEY_TYPES; do + F="$CAKEY_PREFIX-$type.key" + update_file "$TMPDIR/$F" "$SSH_CAROOT/keys/$F" || exit $? + done + + for type in $SSH_SIGN_TYPES; do + F="$CAKEY_PREFIX-$type.crt" + move_as_trusted_x509 "$TMPDIR/$F" "$SSH_CAROOT/crt/$F.pem" || exit $? + done + + create_empty_file "${TMPDIR}/${CACERTFILE}" && + for level in 0; do + F="$SSH_CAROOT/crt/$CAKEY_PREFIX-root${level}.crt.pem" + crt2bundle "$SSH_DN_O level $level" "$F" >> "$TMPDIR/$CACERTFILE" || exit $? + done + for type in ${SSH_SIGN_TYPES}; do + F="$SSH_CAROOT/crt/$CAKEY_PREFIX-$type.crt.pem" + crt2bundle "${SSH_DN_O}-${type}" "${F}" >> "${TMPDIR}/${CACERTFILE}" || exit $? + done + + update_file "${TMPDIR}/${CACERTFILE}" "${SSH_CAROOT}/${CACERTFILE}" +) +} + + +cre_hashs () { +#(!) openssl script "c_rehash" is missing in some installations :-( +# c_rehash "$SSH_CAROOT/crt" +( + cd "$SSH_CAROOT/crt" || exit $? + + for F in [0-9a-f]*.[0-9]; do + # we must use test -L, but on ?-OSes ... :-( + if test -h "$F"; then + rm -f "$F" || exit $? + fi + done + + for level in 0; do + cre_hash_link -log "$CAKEY_PREFIX-root$level.crt.pem" || exit $? + done + + for type in ${SSH_SIGN_TYPES}; do + cre_hash_link -log "$CAKEY_PREFIX-$type.crt.pem" || exit $? + done + + exit 0 +) +} + + +# === + +cre_dirs && +cre_root && +gen_rsa && +gen_dsa && +gen_ed25519 && +gen_ed448 && +cre_crt && +install && +cre_hashs; retval=$? + +show_status $retval "${extd}Creating${norm} ${warn}TEST${norm} ${attn}Certificate Authority${norm}" +echo "${warn}password for all private keys is ${attn}${KEY_PASS}${norm}" +exit $retval diff -ruN openssh-9.4p1/tests/CA/2-cre_key.sh openssh-9.4p1+x509-14.2.1/tests/CA/2-cre_key.sh --- openssh-9.4p1/tests/CA/2-cre_key.sh 1970-01-01 02:00:00.000000000 +0200 +++ openssh-9.4p1+x509-14.2.1/tests/CA/2-cre_key.sh 2023-08-20 10:07:00.000000000 +0300 @@ -0,0 +1,100 @@ +#! /bin/sh +# Copyright (c) 2011-2023 Roumen Petrov, Sofia, Bulgaria +# All rights reserved. +# +# Redistribution and use of this script, with or without modification, is +# permitted provided that the following conditions are met: +# +# 1. Redistributions of this script must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED +# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +# EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# DESCRIPTION: Create "Test Certificate Authority" private keys and certificates. +# + +CWD=`pwd` +SCRIPTDIR=`echo $0 | sed 's/2-cre_key.sh$//'` +. "${SCRIPTDIR}config" +. "${SCRIPTDIR}functions" + +test "x$TEST_SSH_SSHKEYGEN" = "x" && { echo "${warn}Please define ${attn}TEST_SSH_SSHKEYGEN${norm}" >&2 ; exit 1; } + +usage() { + cat <&2 + exit 1 + ;; +esac + +shift +test -z "$1" && usage +case $1 in +client) + infomsg="'Identity'" + ;; +server) + infomsg="host-key" + ;; +self) + infomsg="'Identity' for self-issued" + ;; +ocsp) + if $SSH_OCSP_ENABLED ; then : + else + echo "${warn}unsupported category: ${attn}$1${norm}" >&2 + usage + fi + infomsg="ocsp-key" + ;; +*) + echo "${warn}wrong category: ${attn}$1${norm}" >&2 + usage + ;; +esac + +shift +test -z "$1" && usage + + +echo +echo "Generating ${extd}$typemsg${norm} ${attn}$infomsg${norm} ..." + +# X.509 keys require portable PKCS#8 format instead proprietary +$TEST_SSH_SSHKEYGEN $opts -m PKCS8 -N "" -f "$1" diff -ruN openssh-9.4p1/tests/CA/3-cre_certs.sh openssh-9.4p1+x509-14.2.1/tests/CA/3-cre_certs.sh --- openssh-9.4p1/tests/CA/3-cre_certs.sh 1970-01-01 02:00:00.000000000 +0200 +++ openssh-9.4p1+x509-14.2.1/tests/CA/3-cre_certs.sh 2023-08-20 10:07:00.000000000 +0300 @@ -0,0 +1,334 @@ +#! /bin/sh +# Copyright (c) 2002-2023 Roumen Petrov, Sofia, Bulgaria +# All rights reserved. +# +# Redistribution and use of this script, with or without modification, is +# permitted provided that the following conditions are met: +# +# 1. Redistributions of this script must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED +# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +# EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# DESCRIPTION: Create test certificate(s). +# + +CWD=`pwd` +SCRIPTDIR=`echo $0 | sed 's/3-cre_certs.sh$//'` +. "${SCRIPTDIR}config" +. "${SCRIPTDIR}functions" + +usage () { + cat <&2 ; exit 1; } + + +test -z "$1" && usage +case "$1" in +rsa) key_type_name="RSA";; +dsa) key_type_name="DSA";; +ec256) key_type_name="ECDSA(nistp256)";; +ec384) key_type_name="ECDSA(nistp384)";; +ec521) key_type_name="ECDSA(nistp521)";; +ed25519) key_type_name="ED25519";; +*) echo "${warn}unsupported key type: ${attn}$1${norm}" >&2 + exit 1 + ;; +esac +msg="${extd}$key_type_name${norm}" + +shift +test -z "$1" && usage +SSH_SELFCERT=no +case $1 in +client) + SSH_X509V3_EXTENSIONS=usr_cert + SSH_BASE_DN_CN="SSH $key_type_name test certificate" + msg="$msg ${attn}client${norm}" + ;; +server) + SSH_X509V3_EXTENSIONS=srv_cert + SSH_BASE_DN_CN="localhost $key_type_name" + msg="$msg ${attn}server${norm}" + ;; +self) + SSH_SELFCERT=yes + SSH_X509V3_EXTENSIONS=self_cert + SSH_BASE_DN_CN="SSH $key_type_name test self-issued certificate" + msg="$msg ${attn}client self-issued${norm}" + ;; +ocsp) + if $SSH_OCSP_ENABLED ; then : + else + echo "${warn}unsupported category: ${attn}$1${norm}" >&2 + usage + fi + SSH_X509V3_EXTENSIONS=ocsp_cert + SSH_BASE_DN_CN="validator $key_type_name" + msg="$msg ${attn}ocsp responder${norm}" + ;; +*) + echo "${warn}wrong category: ${attn}$1${norm}" >&2 + usage + ;; +esac + +shift +test -z "$1" && usage +SSH_BASE_KEY="$1" +test ! -r "${SSH_BASE_KEY}" && { error_file_not_readable; exit 1; } + + +CA_LOG="$CWD/ca-3.$SSH_BASE_KEY.$SSH_X509V3_EXTENSIONS.log" +create_empty_file "$CA_LOG" > /dev/null || exit $? + + +# === +cre_crt () { + TMP_CRT_FILE="$TMPDIR/$SSH_X509V3_EXTENSIONS-$type$subtype.crt" + TMP_CSR_FILE="$TMPDIR/$SSH_X509V3_EXTENSIONS-$type$subtype.csr" + + echo "=== create a new CSR ===" >> "$CA_LOG" + ( + if test "$SSH_X509V3_EXTENSIONS" != "usr_cert"; then + SSH_DN_EM="." + fi + + cat <> "$CA_LOG" \ + ; show_status $? "- ${extd}CSR${norm}" || + return $? + + echo >> "$CA_LOG" + echo "=== create a new CRT ===" >> "$CA_LOG" + $OPENSSL ca -config "$SSH_CACFGFILE" \ + -batch \ + -in "$TMP_CSR_FILE" \ + -name "ca_test_$type" \ + -passin pass:$KEY_PASS \ + -out "$TMP_CRT_FILE" \ + -extensions $SSH_X509V3_EXTENSIONS \ + 2>> "$CA_LOG" \ + ; show_status $? "- ${extd}CRT${norm}" || + { retval=$? + printf '%s' "${warn}" + grep 'ERROR:' "$CA_LOG" + printf '%s' "${norm}" + return $retval + } + + sync + $OPENSSL verify \ + -CAfile "$SSH_CAROOT/$CACERTFILE" \ + "$TMP_CRT_FILE" || + { retval=$? + rm -f "$TMP_CSR_FILE" + return $retval + } + rm -f "$TMP_CSR_FILE" + + # openssl verify exit always with zero :( + + printf '%s' '- ' && + update_file \ + "$TMP_CRT_FILE" \ + "$SSH_BASE_KEY-$type$subtype.crt" || + return $? + + # openssl ca command does not support name option + F="$SSH_BASE_KEY-$type$subtype.crt" + mv "$F" t-"$F" && + $OPENSSL x509 \ + -in t-"$F" \ + -text $OPENSSL_NAMEOPT \ + > "$F" && + rm t-"$F" +} + + +# === +cre_self () { + TMP_CRT_FILE="$TMPDIR/$SSH_X509V3_EXTENSIONS-$type.crt" + + echo "=== create a new self-CRT ===" >> "$CA_LOG" + ( + cat <> "$CA_LOG" \ + ; show_status $? "- ${extd}self-CRT${norm}" \ + || return $? + + update_file \ + "$TMP_CRT_FILE" \ + "$SSH_BASE_KEY-$type.crt" +} + + +# === +cre_ssh_crt () { + printf '%s' "- ${extd}PKIX-SSH certificate${norm}" + ( cat "$SSH_BASE_KEY" + + $OPENSSL x509 \ + -in "$SSH_BASE_KEY-$type$subtype.crt" \ + -subject -issuer -alias $OPENSSL_NAMEOPT + ) > "$SSH_BASE_KEY-$type$subtype" && + chmod 600 "$SSH_BASE_KEY-$type$subtype" \ + ; show_status $? +} + + +cre_ssh_pubkey () { + printf '%s' "- ${extd}PKIX-SSH public key${norm}" + "$TEST_SSH_SSHKEYGEN" -y -f "${SSH_BASE_KEY}-${type}${subtype}" \ + > "${SSH_BASE_KEY}-${type}${subtype}.pub" \ + ; show_status $? +} + + +cre_p12 () { + P12_OPT= + # let use more "modern" ciphers with OpenSSL 1.1+ + # prevent needs to activate legacy provider in OpenSSL 3.0+ + if $openssl_use_pkey ; then + P12_OPT="$P12_OPT -keypbe AES-256-CBC -certpbe AES-256-CBC" + elif test -n "$OPENSSL_FIPS"; then + P12_OPT="$P12_OPT -keypbe PBE-SHA1-3DES -certpbe PBE-SHA1-3DES" + fi + printf '%s' "- ${extd}PKCS #12${norm} file" + ( cat "$SSH_BASE_KEY-$type$subtype" + if test "$SSH_SELFCERT" != "yes"; then + cat "$SSH_CAROOT/crt/$CAKEY_PREFIX-$type.crt.pem" + fi + ) | \ + $OPENSSL pkcs12 $P12_OPT \ + -passin pass: \ + -passout pass:$P12_PASS \ + -out "$SSH_BASE_KEY-$type$subtype".p12 \ + -export \ + ; show_status $? +} + + +revoke_crt () { + echo "=== revoke a CRT ===" >> "$CA_LOG" + printf '%s' "- ${extd}revoke${norm} certificate" + $OPENSSL ca -config "$SSH_CACFGFILE" \ + -name "ca_test_$type" \ + -passin pass:$KEY_PASS \ + -revoke "$SSH_BASE_KEY-$type$subtype.crt" \ + 2>> "$CA_LOG" \ + ; show_status $? +} + + +# === +cre_all2 () { + printf '%s\n' "creating ${extd}${SSH_X509V3_EXTENSIONS}${norm} for ${extd}${SSH_BASE_DN_CN}${norm}(${attn}${type}${norm}${warn}${subtype}${norm}) ..." + + if test "$SSH_SELFCERT" = "yes"; then + cre_self + else + cre_crt + fi || return $? + + test "$SSH_X509V3_EXTENSIONS" = "ocsp_cert" && return 0 + + cre_ssh_crt && + cre_ssh_pubkey && + cre_p12 +} + + +# === +cre_all () { +( + subtype= + if test "$SSH_SELFCERT" = "yes" ; then + # NOTE self-issued use name in format "selfid_${keytype}" + keytype=`echo $SSH_BASE_KEY | sed 's/^selfid_//'` + if test "$SSH_BASE_KEY" = "$keytype" ; then + echo "For self-issued ${warn}cannot obtain keytype from keyname - ${attn}$SSH_BASE_KEY${norm}" >&2 + exit 1 + fi + type=$keytype + cre_all2 || exit $? + else + for type in $SSH_SIGN_TYPES ; do + cre_all2 || exit $? + done + fi + + if test "$SSH_X509V3_EXTENSIONS" = "srv_cert" || \ + test "$SSH_SELFCERT" = "yes" \ + ; then + create_empty_file $SSH_BASE_KEY.certstamp + exit $? + fi + + subtype="-revoked" + for type in ${SSH_SIGN_TYPES}; do + cre_all2 && + revoke_crt || exit $? + done + + create_empty_file $SSH_BASE_KEY.certstamp +) +} + +# === +echo +echo "Generating $msg certificates, keys, etc..." + +cre_all; retval=$? + +show_status $retval "Creation of ${extd}$SSH_BASE_DN_CN${norm} certificates, keys, etc." +echo +exit $retval diff -ruN openssh-9.4p1/tests/CA/4-cre_crls.sh openssh-9.4p1+x509-14.2.1/tests/CA/4-cre_crls.sh --- openssh-9.4p1/tests/CA/4-cre_crls.sh 1970-01-01 02:00:00.000000000 +0200 +++ openssh-9.4p1+x509-14.2.1/tests/CA/4-cre_crls.sh 2023-08-20 10:07:00.000000000 +0300 @@ -0,0 +1,118 @@ +#! /bin/sh +# Copyright (c) 2002-2023 Roumen Petrov, Sofia, Bulgaria +# All rights reserved. +# +# Redistribution and use of this script, with or without modification, is +# permitted provided that the following conditions are met: +# +# 1. Redistributions of this script must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED +# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +# EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# DESCRIPTION: Create "Test Certificate Authority" CRLs. +# + +CWD=`pwd` +SCRIPTDIR=`echo $0 | sed 's/4-cre_crls.sh$//'` +. "${SCRIPTDIR}config" +. "${SCRIPTDIR}functions" + + +CA_LOG="$CWD/ca-4.log" +create_empty_file .delmy && +update_file .delmy "$CA_LOG" > /dev/null || exit $? + + +# === +cre_crlfile() { +( + type="$1" + + cd "$SSH_CAROOT/crl" || exit $? + + FILE="${CAKEY_PREFIX}-${type}.crl.pem" + + printf '%s' "- ${attn}${type}${norm} certificates" + ${OPENSSL} ca \ + -config "${SSH_CACFGFILE}" \ + -name "ca_test_$type" \ + -passin pass:${KEY_PASS} \ + -gencrl \ + -out "${FILE}" \ + 2>> "$CA_LOG" \ + ; show_status $? || exit $? + + cre_crl_hash_link "$FILE" +) +} + + +# === +cre_crlindir () { + echo "=== create a new CRL ===" >> "$CA_LOG" + rm -f "$SSH_CAROOT/crl"/* 2>/dev/null + + printf '%s\n' "creating ${extd}CA CRL file${norm} for ..." + for type in ${SSH_SIGN_TYPES}; do + cre_crlfile "${type}" || return $? + done + + return 0 +} + + +# === +cre_CAcrlfile () { +( + crlfile="$SSH_CAROOT/$CACRLFILE" + + # NOTE -nameopt is without effect over -text + # As work-around file will contain in addition + # issuer name. + + create_empty_file "$crlfile"-t && + for type in $SSH_SIGN_TYPES; do + ( + if test -n "$OPENSSL_NAMEOPT"; then + $OPENSSL crl $OPENSSL_NAMEOPT \ + -in "$SSH_CAROOT/crl/$CAKEY_PREFIX-$type.crl.pem" \ + -issuer -noout \ + 2>> "$CA_LOG" && + echo "============================================================" + fi && + $OPENSSL crl \ + -in "$SSH_CAROOT/crl/$CAKEY_PREFIX-$type.crl.pem" \ + -text \ + 2>> "$CA_LOG" \ + && echo && echo + ) >> "$crlfile"-t || exit $? + done + + mv "$crlfile"-t "$crlfile" +) +} + + +# === +cre_all () { + cre_crlindir || return $? + + printf '%s' "creating ${extd}CA CRL ${attn}common${norm} ${extd}file${norm} ..." + cre_CAcrlfile; show_status $? +} + + +# === +cre_all; retval=$? + +show_status $retval "${extd}Creating${norm} ${warn}TEST${norm} ${attn}Certificate Authority${norm} CRL files" diff -ruN openssh-9.4p1/tests/CA/5-cre_ldap.sh openssh-9.4p1+x509-14.2.1/tests/CA/5-cre_ldap.sh --- openssh-9.4p1/tests/CA/5-cre_ldap.sh 1970-01-01 02:00:00.000000000 +0200 +++ openssh-9.4p1+x509-14.2.1/tests/CA/5-cre_ldap.sh 2023-08-20 10:07:00.000000000 +0300 @@ -0,0 +1,113 @@ +#! /bin/sh +# Copyright (c) 2004-2023 Roumen Petrov, Sofia, Bulgaria +# All rights reserved. +# +# Redistribution and use of this script, with or without modification, is +# permitted provided that the following conditions are met: +# +# 1. Redistributions of this script must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED +# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +# EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# DESCRIPTION: Create LDAP files. +# + +CWD=`pwd` +SCRIPTDIR=`echo $0 | sed 's/5-cre_ldap.sh$//'` +. "${SCRIPTDIR}config" +. "${SCRIPTDIR}functions" + + +if test ! -d ldap/data; then + mkdir -p ldap/data || exit $? +fi + + +# === +cre_base_ldif() { +( + cat < ldap/base.ldif +} + + +# === + +cre_base_ldif && +: ; retval=$? + +show_status $retval "${extd}Creating${norm} ${warn}LDAP${norm} ${attn}files${norm}" diff -ruN openssh-9.4p1/tests/CA/config openssh-9.4p1+x509-14.2.1/tests/CA/config --- openssh-9.4p1/tests/CA/config 1970-01-01 02:00:00.000000000 +0200 +++ openssh-9.4p1+x509-14.2.1/tests/CA/config 2023-08-20 10:07:00.000000000 +0300 @@ -0,0 +1,275 @@ +# Copyright (c) 2002-2023 Roumen Petrov, Sofia, Bulgaria +# All rights reserved. +# +# Redistribution and use of this script, with or without modification, is +# permitted provided that the following conditions are met: +# +# 1. Redistributions of this script must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED +# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +# EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# DESCRIPTION: SSH X.509 tests configuration. +# + +. ${SCRIPTDIR}../compat + +# === setup from build environment: +. ../env + +# === main variables: +# on some system (with pam?, AIX?, when port is below 1024, etc.) we +# might use sudo command to start sshd when current user isn`t root or +# to run tests as root. +# Preferred user for tests is NOT root :-) ! +SUDO=${SUDO-} +# uncomment to override environment +#SUDO=sudo + + +#Old BSD shells, including the Ultrix `sh', don't accept the colon +#for any shell substitution, and complain and die. +##TMPDIR="${TMPDIR:-/tmp}" + +if test -n "$TMPDIR"; then + if test ! -d "$TMPDIR"; then + echo "error: $TMPDIR is not directory" + exit 1 + fi + if test ! -w "$TMPDIR"; then + echo "error: $TMPDIR is not writable" + exit 1 + fi +else + for D in /tmp /var/tmp /usr/tmp; do + test -d $D || continue + test -w $D || continue + TMPDIR=$D + break + done + if test -z "$TMPDIR"; then + echo "error: cannot set TMPDIR" + exit 1 + fi +fi + + +if test -z "$SSH_X509TESTS"; then +SSH_X509TESTS="\ + blob_auth + dn_auth_file + dn_auth_path + agent + crl + self + alg + hostalg + algfmt + store_file + ocsp +" +# uncomment next line if your system provides OpenLDAP server +# (requires LDAP enabled build) +#SSH_X509TESTS="$SSH_X509TESTS by_ldap" +fi + + +# === openssl: + +OPENSSL=${OPENSSL-openssl} +OPENSSL=`which $OPENSSL 2>/dev/null` +if test -z "$OPENSSL"; then + echo "error: cannot find openssl in your path !" >&2 + exit 1 +fi +export OPENSSL + +#NOTE: environment variable OPENSSL_FIPS is used as test flag +# in regression tests +if test yes = $OPENSSL_FIPS_MODE; then + : +else + # unset OPENSSL_FIPS for non-FIPS build, to avoid mis-use + # of flag in regression tests + unset OPENSSL_FIPS || : +fi + +printf "OpenSSL command: ${attn}%s${norm}\n" "$OPENSSL" +openssl_version=`$OPENSSL version` || exit $? +test -z "$openssl_version" && { echo "error: cannot determine OpenSSL version" >&2; exit 1; } +printf " version: ${attn}%s${norm}\n" "$openssl_version" + + +openssl_nopkcs8_keys=false +if test -n "$OPENSSL_FIPS"; then + # NOTES + # - OpenSSL 1.0.0* and 1.1.+ does not support FIPS build/mode; + # - Usually in FIPS mode keys are in PKCS#8 format by default; + # - OpenSSL 1.0.1* before 1.0.1d does not create keys in PKCS#8 format. + # => do conversion only for 1.0.1* + # Remark used in 2-cre_cakeys.sh. + case $openssl_version in + *"OpenSSL 1.0.1"*) + openssl_nopkcs8_keys=: + ;; + esac +fi + +# Starting from 1.1+ we will use pkey utilities. +# Remark: genpkey is available in OpenSSL 1.0.0. +openssl_use_pkey=${openssl_use_pkey-:} +case $openssl_version in +*"OpenSSL 0.9"*|\ +*"OpenSSL 1.0"*) + openssl_use_pkey=false + ;; +esac + + +# These are the known patent issues with OpenSSL: +# name # expires +# mdc2: 4,908,861 13/03/2007 - enabled in OpenSSL 1.x branches from 2009-08-12 +# idea: 5,214,703 25/05/2010 +# rc5: 5,724,428 03/03/2015 +# +# Note the MD2 hash algorithm is considered as weak (2009) and +# most vendors disable it in openssl. Also from 2009-07-08 +# OpenSSL team disable md2 by default in 0.9.8 and 1.x branches. +# This is reason md2 to be removed from list starting with +# "X.509 certificate support version 6.3". + +# With support for EC certificates we will limit RSA +# tests to sha1 only. Comment next line to restore. +RSA_DIGEST_LIST=${RSA_DIGEST_LIST-sha1} + +if test -z "$RSA_DIGEST_LIST"; then + for DIGEST in sha1 md5 mdc2 md4 rmd160; do + if "$OPENSSL" dgst -$DIGEST "$OPENSSL" >/dev/null 2>&1; then + RSA_DIGEST_LIST="$RSA_DIGEST_LIST $DIGEST" + fi + done +fi +if test -z "$RSA_DIGEST_LIST"; then + echo "RSA_DIGEST_LIST is empty" >&2 + exit 1 +fi +echo "RSA digest list: $RSA_DIGEST_LIST" + + +# === server section: + +if test -z "${SSHD_PORT}"; then + SSHD_PORT=20022 +fi + +SSHD_LISTENADDRESS=127.0.0.1 +#SSHD_LISTENADDRESS=::1 + +#"yes" or "no" +SSHSERVER_USEPRIVILEGESEPARATION="yes" +#SSHSERVER_USEPRIVILEGESEPARATION="no" + +SSHSERVER_SYSLOGFACILITY=AUTH +SSHSERVER_LOGLEVEL=FATAL +#SSHSERVER_SYSLOGFACILITY=LOCAL3 +#SSHSERVER_LOGLEVEL=DEBUG3 + + +# === certificates: + +KEY_PASS="change_it" +P12_PASS="p12_test" +RSAKEYBITS=2048 +CAKEY_PREFIX="catest" + +SSH_CAROOT="`pwd`/ca-test" + +CACERTFILE="catest-bundle.crt" +CACRLFILE="catest-bundle.crl" + +CACONFIG="catest.config" +SSH_CACFGFILE="${SSH_CAROOT}/${CACONFIG}" + +# always use intermediate CA with rsa key +SSH_CAKEY_TYPES=rsa +# comment next to skip intermediate CA with dsa key +SSH_CAKEY_TYPES="$SSH_CAKEY_TYPES dsa" +# uncomment next to allow intermediate CA with ed25519 key +# (requires OpenSSL >= 1.1.1) +#SSH_CAKEY_TYPES="$SSH_CAKEY_TYPES ed25519" +# uncomment next to allow intermediate CA with ed448 key +# (requires OpenSSL >= 1.1.1) +#SSH_CAKEY_TYPES="$SSH_CAKEY_TYPES ed448" + +SSH_SIGN_TYPES= +for DIGEST in $RSA_DIGEST_LIST ; do + SSH_SIGN_TYPES="$SSH_SIGN_TYPES rsa_${DIGEST}" +done +if expr "$SSH_CAKEY_TYPES" : .*dsa > /dev/null ; then + SSH_SIGN_TYPES="$SSH_SIGN_TYPES dsa" +fi +if expr "$SSH_CAKEY_TYPES" : .*ed25519 > /dev/null ; then + SSH_SIGN_TYPES="$SSH_SIGN_TYPES ed25519" +fi +if expr "$SSH_CAKEY_TYPES" : .*ed448 > /dev/null ; then + SSH_SIGN_TYPES="$SSH_SIGN_TYPES ed448" +fi + +SSH_CACERTDAYS=60 +SSH_CACRLDAYS=60 + +SSH_DN_C="XX" +SSH_DN_ST="World" +SSH_DN_L="Somewhere" +SSH_DN_O="SSH Test Team" +SSH_DN_OU="SSH Testers" +SSH_DN_EM="email@not.set" + +SSH_DN_SUF=" cyrillic-АБВ-Яабв-я greek-ΑΒΓ-Ωαβγ-ω" +SSH_DN_L="$SSH_DN_L$SSH_DN_SUF" +SSH_DN_O="$SSH_DN_O$SSH_DN_SUF" +SSH_DN_OU="$SSH_DN_OU$SSH_DN_SUF" + +OPENSSL_NAMEOPT="-nameopt utf8,sep_comma_plus" #ok +#OPENSSL_NAMEOPT="-nameopt esc_2253,esc_ctrl,esc_msb,utf8,dump_nostr,dump_der,use_quote,sep_comma_plus_space,sname" #fail - esc_msb should be removed +#OPENSSL_NAMEOPT="-nameopt esc_2253,esc_ctrl,utf8,dump_nostr,dump_der,use_quote,sep_comma_plus_space,sname" #ok +#OPENSSL_NAMEOPT="-nameopt esc_2253,esc_ctrl,-esc_msb,utf8,dump_nostr,dump_der,use_quote,sep_comma_plus_space,sname" #ok +#OPENSSL_NAMEOPT="-nameopt esc_2253,esc_ctrl,esc_msb,utf8,dump_nostr,dump_der,use_quote,sep_comma_plus_space,sname,-esc_msb" #ok +#OPENSSL_NAMEOPT="-nameopt oneline,-esc_msb,-space_eq" #ok +#OPENSSL_NAMEOPT="-nameopt oneline,-esc_msb" #now ok (spaces around '=') + +# === OCSP: +# OpenSSL OCSP test responders listen on BASE, BASE+1, ... +# Set the default base port if is not set by environment. +SSH_VA_BASEPORT=${SSH_VA_BASEPORT-20080} + +# OpenSSL OCSP responder don't use SO_REUSEADDR :-(, so ocsp tests +# must wait socket to close. +# Set the default timeout if is not set by environment. +SSH_OPENSSL_OCSP_TMOUT=${SSH_OPENSSL_OCSP_TMOUT-60} + +# === LDAP: +# "mdb" backend since openldap 2.4+ +SSH_LDAP_DB=${SSH_LDAP_DB-mdb} +# bdb and hdb removed in openldap 2.5+ +#SSH_LDAP_DB=${SSH_LDAP_DB-bdb} +# "hdb" backend since openldap 2.2+ +#SSH_LDAP_DB=hdb +# openldap 2.4+ deprecate "ldbm" backend +#SSH_LDAP_DB=ldbm +SSH_LDAP_DC="dc=example,dc=com" + +# LDAP test server listen on specified port. +# Set the default ldap port if is not set by environment. +LDAPD_PORT=${LDAPD_PORT-20389} + +LDAPD_URL="ldap://${SSHD_LISTENADDRESS}:${LDAPD_PORT}" diff -ruN openssh-9.4p1/tests/CA/functions openssh-9.4p1+x509-14.2.1/tests/CA/functions --- openssh-9.4p1/tests/CA/functions 1970-01-01 02:00:00.000000000 +0200 +++ openssh-9.4p1+x509-14.2.1/tests/CA/functions 2023-08-20 10:07:00.000000000 +0300 @@ -0,0 +1,354 @@ +# Copyright (c) 2002-2021 Roumen Petrov, Sofia, Bulgaria +# All rights reserved. +# +# Redistribution and use of this script, with or without modification, is +# permitted provided that the following conditions are met: +# +# 1. Redistributions of this script must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED +# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +# EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# DESCRIPTION: Useful functions. +# + + +# === +# +# define colors and more for echo commands +# +# \033 ascii ESCape +# \033[G move to column (linux console, xterm, not vt100) +# \033[C move columns forward but only up to last column +# \033[D move columns backward but only up to first column +# \033[A move rows up +# \033[B move rows down +# \033[1m switch bold on +# \033[31m switch red on +# \033[32m switch green on +# \033[33m switch yellow on +# \033[m switch color/bold off +# \017 exit alternate mode (xterm, vt100, linux console) +# \033[10m exit alternate mode (linux console) +# \015 carriage return (without newline) +# + +# get terminal settings in a portable way +# NOTE: stty size is not portable +if test -z "$LINES" -o -z "$COLUMNS" ; then + eval `stty size 2>/dev/null | (read L C; echo LINES=$L COLUMNS=$C)` +fi +test -z "$LINES" && LINES=`tput lines` +test -z "$COLUMNS"&& COLUMNS=`tput cols` +# set defaults +test -z "$LINES" && LINES=24 +test -z "$COLUMNS"&& COLUMNS=80 +export LINES COLUMNS + +if test "${TERM}" != "dumb" ; then + esc=`printf '\033'` + extd="${esc}[1m" + warn="${esc}[1;31m" + done="${esc}[1;32m" + attn="${esc}[1;34m" + norm=`printf '%s\017' "${esc}[m"` + stat=`printf '\015%s' "${esc}[${COLUMNS}C${esc}[10D"` + + msg_done="${stat}${done}done${norm}" + msg_failed="${stat}${warn}failed${norm}" + +else + esc="" + extd="" + warn="" + done="" + attn="" + norm="" + stat="" + + msg_done="..done" + msg_failed="..failed" + +fi + + +# === +error_file_not_found () { + echo "${warn}file ${attn}$1${warn} not found${norm}" >&2 + return 1 +} + + +# === +error_file_not_readable () { + echo "${warn}file ${attn}$1${warn} not found or not readable${norm}" >&2 + return 1 +} + + +# === +error_dir_not_found () { + echo "${warn}directory ${attn}$1${warn} not found${norm}" >&2 + return 1 +} + + +# === +printSeparator() { + echo "=======================================================================" +} + + +# === +show_status () { + if test -n "$2"; then + printf '%s' "$2" + fi + if test $1 -eq 0; then + echo "$msg_done" + else + echo "$msg_failed" + fi + return $1 +} + + +# === +getNextFreeName() { + var="$1" + limit="$2" + + if test -z "${limit}"; then + limit=10 + fi + + count=0 + while true; do + test ! -f "${var}${count}" && break + count=`expr ${count} + 1` + if test ${count} -ge ${limit}; then + echo "getNextFreeName: ${warn}limit reached${norm} for file ${attn}${var}${norm}" >&2 + + echo "" + return 33 + fi + done + + echo "${var}${count}" + return 0 +} + + +# === +getNextDirName() { + var="$1" + count=0 + while true; do + test ! -d "${var}.${count}" && break + count=`expr ${count} + 1` + done + if test ${count} -ge 10; then + echo "${warn}please remove ${attn}${var}${warn} backup directories !${norm}" >&2 + return 33 + fi + echo $count + return 0 +} + + +# === +create_empty_file () { + > "$1" +} + + +# === +update_file () { + var_new="$1" + var_old="$2" + + if test ! -f "${var_old}"; then + printf '%s' "creating file ${attn}${var_old}${norm}" + mv "${var_new}" "${var_old}"; show_status $? + return $? + fi + test -r "${var_new}" || { error_file_not_readable "${var_new}"; return 1; } + + if diff "${var_old}" "${var_new}" >/dev/null 2>&1; then + echo "no changes in ${attn}${var_old}${norm}" + rm -f "${var_new}" + return 0 + fi + + backup=`getNextFreeName "${var_old}."` || return $? + printf '%s' "saving old file as ${attn}${backup}${norm}" + cp -p "${var_old}" "${backup}"; show_status $? || return $? + + printf '%s' "updating file ${attn}${var_old}${norm}" + if test ! -w "${var_old}"; then + chmod u+w "${var_old}" + not_writable="yes" + fi + cat "${var_new}" > "${var_old}"; show_status $? || return $? + if test "$not_writable" = "yes"; then + chmod u-w "${var_old}" + fi + rm -f "${var_new}" + return 0 +} + + +# === +getSSHkeyType () { + identity_file="$1" + if test ! -r "$identity_file"; then + error_file_not_readable "${identity_file}" >&2; return $? + fi + + sshkeytype="unspec" + retval=0 + + sshkeytype=`"${TEST_SSH_SSHKEYGEN}" -f "${identity_file}" -y 2>/dev/null`; retval=$? + if test $retval -ne 0 ; then + echo "${warn}command${norm} ${TEST_SSH_SSHKEYGEN} ${warn}fail${norm}" >&2 + return $retval + fi + echo "${sshkeytype}" | cut -d ' ' -f 1 + return 0 +} + + +# === +getSubject () { + identity_file="$1" +#rest of arguments passed to openssl + + if test ! -r "$identity_file"; then + error_file_not_readable "${identity_file}" >&2 + return 1 + fi + shift + + retval=0 + +#SHELL bug or ?: when we assign command result to "local xxx=..." retval is always zero :-/ !!! +#unix sh don't like local :-) +# local subject=`"${OPENSSL}" x509 -noout -subject -in "${identity_file}" $*`; retval=$? +# + subject=`"$OPENSSL" x509 -noout -subject $OPENSSL_NAMEOPT -in "$identity_file" $* 2>/dev/null`; retval=$? + if test $retval -ne 0 ; then + echo "${warn}cannot get certificate subject${norm}" >&2 + return $retval + fi + +#on some ksh versions output is broken if utf8 string contain parenthesis. +#ksh 2007-03-28 fail. good versions are 2010-06-21 and 2011-02-08. + echo "$subject" | cut -d '=' -f 2- +} + + +#=== +creX509AuthorizedKeysFile () { + identity_file="$1" + + sshkeytype=`getSSHkeyType "${identity_file}"` || return $? + subject=`getSubject "${identity_file}"` || return $? + echo "${sshkeytype} subject ${subject}" > "${AUTHORIZEDKEYSFILE}" +} + + +# === +utf8base64() { + printf ':' + printf "$1" | $OPENSSL enc -a -e | xargs printf ' %s\n' +} + + +# === +cre_link () { + rm -f "$2" && + ln -s "$1" "$2" || return $? + #link might never fail ;-( + test -h "$2" +} + + +# === +cre_hash_link () { +# Issue with OpenSSL option -noout: +# Exit code from .../openssl ... -noout ... is sometime nonzero! +# May be only by .../openssl x509 ... -noout ... exit code is zero. +# sample: +# a) exit code is one - INCORRECT +# .../openssl crl -in a_crl_file -hash -noout +# b) exit code is zero - correct +# .../openssl crl -in a_crl_file -hash -out /dev/null +# +# May be work around is to use -out /dev/null? :-/ + if test "x$1" = "x-log" ; then + logit=: + shift + else + logit=false + fi + + HASH=`$OPENSSL x509 -hash -in "$1" -noout` || return $? + case `uname -s 2>/dev/null` in + CYGWIN*) + # On cygwin OpenSSL 1.1* output erroneously ends with + HASH=`echo $HASH | tr -d '\r'` + ;; + esac + hash_link=`getNextFreeName $HASH.` || return $? + + if test -n "$2" ; then + hash_link="$2/$hash_link" + fi + + if $logit ; then + echo "creating link ${attn}$hash_link${norm} to ${attn}$1${norm}" + fi + cre_link "$1" "$hash_link" +} + + +# === +cre_crl_hash_link () { + if test "x$1" = "x-log" ; then + logit=: + shift + else + logit=false + fi + + HASH=`$OPENSSL crl -hash -in "$1" -out /dev/null` || return $? + case `uname -s 2>/dev/null` in + CYGWIN*) + # On cygwin OpenSSL 1.1* output erroneously ends with + HASH=`echo $HASH | tr -d '\r'` + ;; + esac + hash_link=`getNextFreeName $HASH.r` || return $? + + if test -n "$2" ; then + hash_link="$2/$hash_link" + fi + + if $logit ; then + echo "creating link ${attn}$hash_link${norm} to ${attn}$1${norm} ..." + fi + cre_link "$1" "$hash_link" +} + + +# === +FUNCTIONS_INCLUDED="yes" diff -ruN openssh-9.4p1/tests/CA/.kateconfig openssh-9.4p1+x509-14.2.1/tests/CA/.kateconfig --- openssh-9.4p1/tests/CA/.kateconfig 1970-01-01 02:00:00.000000000 +0200 +++ openssh-9.4p1+x509-14.2.1/tests/CA/.kateconfig 2023-08-20 10:07:00.000000000 +0300 @@ -0,0 +1,2 @@ +kate-wildcard(*.sh): replace-tabs on; +kate-wildcard(*.inc): replace-tabs on; mode Bash; syntax Bash; diff -ruN openssh-9.4p1/tests/CA/Makefile.in openssh-9.4p1+x509-14.2.1/tests/CA/Makefile.in --- openssh-9.4p1/tests/CA/Makefile.in 1970-01-01 02:00:00.000000000 +0200 +++ openssh-9.4p1+x509-14.2.1/tests/CA/Makefile.in 2023-08-20 10:07:01.000000000 +0300 @@ -0,0 +1,229 @@ +SHELL=@SHELL@ +srcdir=@srcdir@ + + +all: + + +clean: ldap_clean + -rm -f testhostkey_* + -rm -f testid_* + -rm -f selfid_* + -rm -f testocsp_* + -rm -fr ca-test/ + -rm -f ca-?.log + -rm -f ca-3.*.log + -rm -f va-*.log + -rm -f sshd_x509.log + -rm -f ssh_askpass-p12 + + +distclean: clean + -rm -f Makefile + +# === + +check-certs: ca_files hostkeys identities selfidentities ocsp_certs crl_files ldap_files + @echo + $(SHELL) $(srcdir)/ssh_x509tests.sh + +# === +ca_files: ca-test/catest.config ca-test/catest-bundle.crt + +#user is responsible to recreate X.509 tests files !!! +#ca-test/catest.config: $(srcdir)/config +ca-test/catest.config: + @echo + $(SHELL) $(srcdir)/1-cre_cadb.sh + +ca-test/catest-bundle.crt: ca-test/catest.config + @echo + $(SHELL) $(srcdir)/2-cre_cakeys.sh + +# === +hostkeys: testhostkey_rsa.certstamp + +testhostkey_rsa: + @$(SHELL) $(srcdir)/2-cre_key.sh rsa server $@ + +testhostkey_rsa.certstamp: testhostkey_rsa ca-test/catest-bundle.crt + @$(SHELL) $(srcdir)/3-cre_certs.sh rsa server testhostkey_rsa + +@COMMENT_OUT_DSA@hostkeys: testhostkey_dsa.certstamp + +testhostkey_dsa: + @$(SHELL) $(srcdir)/2-cre_key.sh dsa server $@ + +testhostkey_dsa.certstamp: testhostkey_dsa ca-test/catest-bundle.crt + @$(SHELL) $(srcdir)/3-cre_certs.sh dsa server testhostkey_dsa + +@COMMENT_OUT_ECC256@hostkeys: testhostkey_eccnistp256.certstamp +@COMMENT_OUT_ECC384@hostkeys: testhostkey_eccnistp384.certstamp +@COMMENT_OUT_ECC521@hostkeys: testhostkey_eccnistp521.certstamp + +testhostkey_eccnistp256: + @$(SHELL) $(srcdir)/2-cre_key.sh ec256 server $@ + +testhostkey_eccnistp256.certstamp: testhostkey_eccnistp256 ca-test/catest-bundle.crt + @$(SHELL) $(srcdir)/3-cre_certs.sh ec256 server testhostkey_eccnistp256 + +testhostkey_eccnistp384: + @$(SHELL) $(srcdir)/2-cre_key.sh ec384 server $@ + +testhostkey_eccnistp384.certstamp: testhostkey_eccnistp384 ca-test/catest-bundle.crt + @$(SHELL) $(srcdir)/3-cre_certs.sh ec384 server testhostkey_eccnistp384 + +testhostkey_eccnistp521: + @$(SHELL) $(srcdir)/2-cre_key.sh ec521 server $@ + +testhostkey_eccnistp521.certstamp: testhostkey_eccnistp521 ca-test/catest-bundle.crt + @$(SHELL) $(srcdir)/3-cre_certs.sh ec521 server testhostkey_eccnistp521 + +@COMMENT_OUT_ED25519@hostkeys: testhostkey_ed25519.certstamp + +testhostkey_ed25519: + @$(SHELL) $(srcdir)/2-cre_key.sh ed25519 server $@ + +testhostkey_ed25519.certstamp: testhostkey_ed25519 ca-test/catest-bundle.crt + @$(SHELL) $(srcdir)/3-cre_certs.sh ed25519 server testhostkey_ed25519 + +# === +identities: testid_rsa.certstamp + +testid_rsa: + @$(SHELL) $(srcdir)/2-cre_key.sh rsa client $@ + +testid_rsa.certstamp: testid_rsa ca-test/catest-bundle.crt + @$(SHELL) $(srcdir)/3-cre_certs.sh rsa client testid_rsa + +@COMMENT_OUT_DSA@identities: testid_dsa.certstamp + +testid_dsa: + @$(SHELL) $(srcdir)/2-cre_key.sh dsa client $@ + +testid_dsa.certstamp: testid_dsa ca-test/catest-bundle.crt + @$(SHELL) $(srcdir)/3-cre_certs.sh dsa client testid_dsa + +@COMMENT_OUT_ECC256@identities: testid_eccnistp256.certstamp +@COMMENT_OUT_ECC384@identities: testid_eccnistp384.certstamp +@COMMENT_OUT_ECC521@identities: testid_eccnistp521.certstamp + +testid_eccnistp256: + @$(SHELL) $(srcdir)/2-cre_key.sh ec256 client $@ + +testid_eccnistp256.certstamp: testid_eccnistp256 ca-test/catest-bundle.crt + @$(SHELL) $(srcdir)/3-cre_certs.sh ec256 client testid_eccnistp256 + +testid_eccnistp384: + @$(SHELL) $(srcdir)/2-cre_key.sh ec384 client $@ + +testid_eccnistp384.certstamp: testid_eccnistp384 ca-test/catest-bundle.crt + @$(SHELL) $(srcdir)/3-cre_certs.sh ec384 client testid_eccnistp384 + +testid_eccnistp521: + @$(SHELL) $(srcdir)/2-cre_key.sh ec521 client $@ + +testid_eccnistp521.certstamp: testid_eccnistp521 ca-test/catest-bundle.crt + @$(SHELL) $(srcdir)/3-cre_certs.sh ec521 client testid_eccnistp521 + +@COMMENT_OUT_ED25519@identities: testid_ed25519.certstamp + +testid_ed25519: + @$(SHELL) $(srcdir)/2-cre_key.sh ed25519 client $@ + +testid_ed25519.certstamp: testid_ed25519 ca-test/catest-bundle.crt + @$(SHELL) $(srcdir)/3-cre_certs.sh ed25519 client testid_ed25519 + +# === +selfidentities: selfid_rsa.certstamp + +selfid_rsa.certstamp: selfid_rsa + @$(SHELL) $(srcdir)/3-cre_certs.sh rsa self selfid_rsa + +selfid_rsa: + @$(SHELL) $(srcdir)/2-cre_key.sh rsa self $@ + +@COMMENT_OUT_DSA@selfidentities: selfid_dsa.certstamp + +selfid_dsa.certstamp: selfid_dsa + @$(SHELL) $(srcdir)/3-cre_certs.sh dsa self selfid_dsa + +selfid_dsa: + @$(SHELL) $(srcdir)/2-cre_key.sh dsa self $@ + +@COMMENT_OUT_ECC256@selfidentities: selfid_eccnistp256.certstamp + +selfid_eccnistp256.certstamp: selfid_eccnistp256 + @$(SHELL) $(srcdir)/3-cre_certs.sh ec256 self selfid_eccnistp256 + +selfid_eccnistp256: + @$(SHELL) $(srcdir)/2-cre_key.sh ec256 self $@ + + +# === +@OCSP_OFF@ocsp_certs: +@OCSP_ON@ocsp_certs: testocsp_rsa.certstamp + +testocsp_rsa.certstamp: testocsp_rsa ca-test/catest-bundle.crt + @$(SHELL) $(srcdir)/3-cre_certs.sh rsa ocsp testocsp_rsa + +testocsp_rsa: + @$(SHELL) $(srcdir)/2-cre_key.sh rsa ocsp $@ + +@OCSP_ON@@COMMENT_OUT_DSA@ocsp_certs: testocsp_dsa.certstamp + +testocsp_dsa.certstamp: testocsp_dsa ca-test/catest-bundle.crt + @$(SHELL) $(srcdir)/3-cre_certs.sh dsa ocsp testocsp_dsa + +testocsp_dsa: + @$(SHELL) $(srcdir)/2-cre_key.sh dsa ocsp $@ + +@OCSP_ON@@COMMENT_OUT_ECC256@ocsp_certs: testocsp_eccnistp256.certstamp +@OCSP_ON@@COMMENT_OUT_ECC384@ocsp_certs: testocsp_eccnistp384.certstamp +@OCSP_ON@@COMMENT_OUT_ECC521@ocsp_certs: testocsp_eccnistp521.certstamp + +testocsp_eccnistp256.certstamp: testocsp_eccnistp256 ca-test/catest-bundle.crt + @$(SHELL) $(srcdir)/3-cre_certs.sh ec256 ocsp testocsp_eccnistp256 + +testocsp_eccnistp256: + @$(SHELL) $(srcdir)/2-cre_key.sh ec256 ocsp $@ + +testocsp_eccnistp384.certstamp: testocsp_eccnistp384 ca-test/catest-bundle.crt + @$(SHELL) $(srcdir)/3-cre_certs.sh ec384 ocsp testocsp_eccnistp384 + +testocsp_eccnistp384: + @$(SHELL) $(srcdir)/2-cre_key.sh ec384 ocsp $@ + +testocsp_eccnistp521.certstamp: testocsp_eccnistp521 ca-test/catest-bundle.crt + @$(SHELL) $(srcdir)/3-cre_certs.sh ec521 ocsp testocsp_eccnistp521 + +testocsp_eccnistp521: + @$(SHELL) $(srcdir)/2-cre_key.sh ec521 ocsp $@ + +@OCSP_ON@@COMMENT_OUT_ED25519@ocsp_certs: testocsp_ed25519.certstamp + +testocsp_ed25519.certstamp: testocsp_ed25519 ca-test/catest-bundle.crt + @$(SHELL) $(srcdir)/3-cre_certs.sh ed25519 ocsp testocsp_ed25519 + +testocsp_ed25519: + @$(SHELL) $(srcdir)/2-cre_key.sh ed25519 ocsp $@ + +# === +crl_files: ca-test/catest-bundle.crl + +ca-test/catest-bundle.crl: testid_rsa-rsa_sha1 testid_dsa-rsa_sha1 + @echo + $(SHELL) $(srcdir)/4-cre_crls.sh + +# === +@LDAP_OFF@ldap_files: +@LDAP_ON@ldap_files: ldap/base.ldif + +@LDAP_ON@ldap/base.ldif: +@LDAP_ON@ @echo +@LDAP_ON@ $(SHELL) $(srcdir)/5-cre_ldap.sh + +@LDAP_OFF@ldap_clean: +@LDAP_ON@ldap_clean: +@LDAP_ON@ -rm -f ldap_setup.log +@LDAP_ON@ -rm -fr ldap diff -ruN openssh-9.4p1/tests/CA/ssh_x509tests.sh openssh-9.4p1+x509-14.2.1/tests/CA/ssh_x509tests.sh --- openssh-9.4p1/tests/CA/ssh_x509tests.sh 1970-01-01 02:00:00.000000000 +0200 +++ openssh-9.4p1+x509-14.2.1/tests/CA/ssh_x509tests.sh 2023-08-20 10:07:00.000000000 +0300 @@ -0,0 +1,447 @@ +#! /bin/sh +# Copyright (c) 2002-2023 Roumen Petrov, Sofia, Bulgaria +# All rights reserved. +# +# Redistribution and use of this script, with or without modification, is +# permitted provided that the following conditions are met: +# +# 1. Redistributions of this script must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED +# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +# EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# DESCRIPTION: Test client and server with x509 certificates. +# + + +CWD=`pwd` +SCRIPTDIR=`echo $0 | sed 's/ssh_x509tests.sh//'` +. "${SCRIPTDIR}config" +. "${SCRIPTDIR}functions" + +test "x$TEST_SSH_SSH" = "x" && { echo "${warn}Please define ${attn}TEST_SSH_SSH${norm}" >&2 ; exit 1; } +test "x$TEST_SSH_SSHD" = "x" && { echo "${warn}Please define ${attn}TEST_SSH_SSHD${norm}" >&2 ; exit 1; } +test "x$TEST_SSH_SSHAGENT" = "x" && { echo "${warn}Please define ${attn}TEST_SSH_SSHAGENT${norm}" >&2 ; exit 1; } +test "x$TEST_SSH_SSHADD" = "x" && { echo "${warn}Please define ${attn}TEST_SSH_SSHADD${norm}" >&2 ; exit 1; } +test "x$TEST_SSH_SSHKEYGEN" = "x" && { echo "${warn}Please define ${attn}TEST_SSH_SSHKEYGEN${norm}" >&2 ; exit 1; } +#TEST_SSH_SSHKEYSCAN +#TEST_SSH_SFTP +#TEST_SSH_SFTPSERVER + +cat <&2 + continue + ;; + esac + SSH_EC_CURVES="$SSH_EC_CURVES $curve" + SSH_ALGS_PLAIN_EC="$SSH_ALGS_PLAIN_EC `echo $a | sed 's/x509v3-//'`" + SSH_ALGS_X509_EC="$SSH_ALGS_X509_EC $a" + ;; + x509v3-*-ed25519) + SSH_ALGS_X509_ED25519="$SSH_ALGS_X509_ED25519 $a" + ;; + esac +done + +# if exist X.509 algorithm must exist corresponding plain-key +if test -n "$SSH_ALGS_X509_RSA" ; then + TEST_SSH_CLIENTKEYS="$TEST_SSH_CLIENTKEYS testid_rsa" + TEST_OCSP_RESPKEYS="$TEST_OCSP_RESPKEYS testocsp_rsa" + SSH_ALGS_PLAIN_RSA=ssh-rsa +fi +if test -n "$SSH_ALGS_X509_DSA" ; then + TEST_SSH_CLIENTKEYS="$TEST_SSH_CLIENTKEYS testid_dsa" + TEST_OCSP_RESPKEYS="$TEST_OCSP_RESPKEYS testocsp_dsa" + SSH_ALGS_PLAIN_DSA=ssh-dss +fi +for curve in $SSH_EC_CURVES "" ; do + test -z "$curve" && break + TEST_SSH_CLIENTKEYS="$TEST_SSH_CLIENTKEYS testid_ecc$curve" + TEST_OCSP_RESPKEYS="$TEST_OCSP_RESPKEYS testocsp_ecc$curve" +done +if test -n "$SSH_ALGS_X509_ED25519" ; then + TEST_SSH_CLIENTKEYS="$TEST_SSH_CLIENTKEYS testid_ed25519" + SSH_ALGS_PLAIN_ED25519=ssh-ed25519 +fi + +# if SHA-256 is supported must exist RSA RFC8332 algorithms +if $HAVE_EVP_SHA256 ; then + SSH_ALGS_PLAIN_RSA="$SSH_ALGS_PLAIN_RSA rsa-sha2-256 rsa-sha2-512" +fi + +SSH_ALGS_PLAIN="\ + $SSH_ALGS_PLAIN_RSA \ + $SSH_ALGS_PLAIN_DSA \ + $SSH_ALGS_PLAIN_EC \ + $SSH_ALGS_PLAIN_ED25519 \ +" +SSH_ALGS_X509="\ + $SSH_ALGS_X509_RSA \ + $SSH_ALGS_X509_DSA \ + $SSH_ALGS_X509_EC \ + $SSH_ALGS_X509_ED25519 \ +" + +# OpenSSL OCSP limitation: only rsa keys for versions before 1.x +# OCSP tests are slow as OpenSSL OCSP sample responder does not reuse +# socked address. So each test has to wait timeout to expire ~ 60 sec. +# Lets use only rsa for now. +TEST_OCSP_RESPKEYS="testocsp_rsa" + +#TEST_SSHD_HOSTKEY="$CWD/testhostkey_rsa-rsa_sha1" +TEST_SSHD_HOSTKEY="$CWD/testhostkey_rsa" + + +USERDIR="${HOME}/.ssh" +if test ! -d "${USERDIR}"; then + mkdir "${USERDIR}" || exit 1 + chmod 700 "${USERDIR}" || exit 1 +fi + +AUTHORIZEDKEYSFILE="${USERDIR}/authorized_keys-certTests" +USERKNOWNHOSTSFILE="${USERDIR}/known_hosts-certTests" + + +# === +# remove unsupported tests + +if $SSH_LDAP_ENABLED ; then + echo "LDAP: enabled" +else + echo "LDAP: disabled" + SSH_X509TESTS=`echo "${SSH_X509TESTS}" | sed -e 's|by_ldap||g'` +fi +if $SSH_OCSP_ENABLED ; then + echo "OCSP: enabled" +else + echo "OCSP: disabled" + SSH_X509TESTS=`echo "${SSH_X509TESTS}" | sed -e 's|ocsp||g'` +fi +if $USE_OPENSSL_STORE2 ; then + echo "STORE: enabled" +else + echo "STORE: disabled" + SSH_X509TESTS=`echo "${SSH_X509TESTS}" | sed -e 's|store_file||g'` +fi +echo SSH_X509TESTS: $SSH_X509TESTS + + +# === +runSSHdaemon() { + echo "=======================================================================" >> "${SSHD_LOG}" + + if test -f "${SSHD_PID}"; then + echo "${warn}sshd pid file exist!${norm}" >&2 + fi + + #NOTES: + #- without -d option sshd run in daemon mode and this command always return 0 !!! + #- bug or ?: with option -e no log to stderr in daemon mode + $SUDO "$TEST_SSH_SSHD" -f "${SSHD_CFG}" \ + -o PidFile="${SSHD_PID}" \ + -o SyslogFacility="${SSHSERVER_SYSLOGFACILITY}" \ + -o LogLevel="${SSHSERVER_LOGLEVEL}" \ + >> "${SSHD_LOG}" 2>&1 + + sleep 3 + if test ! -f "${SSHD_PID}"; then + printf "${warn}cannot start sshd:${norm} " >&2 + error_file_not_readable "${SSHD_PID}" + return 33 + fi +} + + +# === +killSSHdaemon() { +( + $SUDO kill `$SUDO cat "$SSHD_PID" 2>/dev/null` > /dev/null 2>&1 + K=0 + while test $K -le 9; do + if test ! -f "${SSHD_PID}"; then + break + fi + sleep 1 + K=`expr $K + 1` + done + rm -f "${SSHD_CFG}" + if test -f "${SSHD_PID}"; then + $SUDO kill -9 `$SUDO cat "$SSHD_PID" 2>/dev/null` > /dev/null 2>&1 + sleep 1 + $SUDO rm -f "${SSHD_PID}" > /dev/null 2>&1 + fi + exit 0 +) +} + + +# === +testEND() { + ( echo + echo "*=- The END -=*" + ) >> "${SSHD_LOG}" + + rm -f "${SSH_ERRLOG}" + rm -f "${SSH_REPLY}" + rm -f "${AUTHORIZEDKEYSFILE}" + rm -f "${USERKNOWNHOSTSFILE}" + rm -f "${SSH_CFG}" +} + +testBREAK() { + ( echo + echo "*=- BREAK -=*" + ) >> "${SSHD_LOG}" + killSSHdaemon +} + +trap testBREAK HUP INT QUIT ABRT TERM || exit 1 +trap testEND EXIT || exit 1 + + +# === +creTestSSHDcfgFile() { + cat > "$SSHD_CFG" <> "$SSHD_CFG" + fi + cat >> "$SSHD_CFG" < "${SSH_CFG}" < "${SSH_ERRLOG}" > "${SSH_REPLY}"; retval=$? + + if test "x$must_fail" = "x1"; then + if test $retval -ne 0; then + retval=0 + else + retval=1 + fi + fi + + show_status $retval + if test $retval -ne 0; then + printf '%s' "${warn}" + cat "${SSH_ERRLOG}"; printf '%s' "${norm}" + else + if test "x$must_fail" = "x1"; then + if fgrep "$must_fail_err_txt" "$SSH_ERRLOG" > /dev/null; then + printf '%s' "${done}" + else + retval=33 + printf '%s' "${warn}" + fi + cat "${SSH_ERRLOG}"; printf '%s' "${norm}" + else + if fgrep "$msg" "${SSH_REPLY}" > /dev/null; then + : + else + retval=33 + printf '%s' "${warn}" + cat "${SSH_REPLY}"; printf '%s' "${norm}" + fi + fi + fi + + exit $retval +) +} + + +# === +do_all () { + create_empty_file "${AUTHORIZEDKEYSFILE}" && + chmod 644 "${AUTHORIZEDKEYSFILE}" || return $? + + create_empty_file "${SSHD_LOG}" || return $? + + if test ! -f "${TEST_SSHD_HOSTKEY}.pub"; then + echo "${warn}Public host file ${attn}$TEST_SSHD_HOSTKEY.pub${warn} not found !${norm}" >72 + return 3 + fi + ( printf '%s' "${SSHD_LISTENADDRESS} " + cat "${TEST_SSHD_HOSTKEY}.pub" + ) > "${USERKNOWNHOSTSFILE}" && + chmod 644 "${USERKNOWNHOSTSFILE}" || return $? + + # call the test scripts + for LTEST in ${SSH_X509TESTS}; do + ( + echo + echo "using: ${attn}${SCRIPTDIR}test-${LTEST}.sh.inc${norm}" + . ${SCRIPTDIR}test-${LTEST}.sh.inc && + do_test + ) || return $? + done + + printSeparator + return 0 +} + + +# === +echo +printSeparator +echo "${extd}Testing client and server with X.509 certificates:${norm}" +printSeparator + +do_all; retval=$? + +echo +printSeparator +echo "${extd}Testing client and server with X.509 certificates finished.${norm}" +show_status $retval " ${extd}status${norm}:" +printSeparator +echo + +exit $retval diff -ruN openssh-9.4p1/tests/CA/test-agent.sh.inc openssh-9.4p1+x509-14.2.1/tests/CA/test-agent.sh.inc --- openssh-9.4p1/tests/CA/test-agent.sh.inc 1970-01-01 02:00:00.000000000 +0200 +++ openssh-9.4p1+x509-14.2.1/tests/CA/test-agent.sh.inc 2023-08-20 10:07:00.000000000 +0300 @@ -0,0 +1,165 @@ +# +# Copyright (c) 2002-2020 Roumen Petrov, Sofia, Bulgaria +# All rights reserved. +# +# Redistribution and use of this script, with or without modification, is +# permitted provided that the following conditions are met: +# +# 1. Redistributions of this script must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED +# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +# EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# DESCRIPTION: Test client authentication: +# - add a key to agent; +# - list agent keys; +# - try to connect with key from agent; +# - remove the key from agent. +# + + +# === +#env. vars: +# SSH_CLIENTKEY +# type +testAgent () { + identity_file="${SSH_CLIENTKEY}-${type}" + if test ! -r "${identity_file}"; then + error_file_not_readable "${identity_file}"; return $? + fi + + ( + sshkeytype=`getSSHkeyType "$identity_file"` || exit $? + subject=`getSubject "$identity_file"` || exit $? + + echo "$sshkeytype Subject: $subject" + ) > "${AUTHORIZEDKEYSFILE}" || return $? + +( +killAgent () { + "${TEST_SSH_SSHAGENT}" -k > /dev/null + sleep 1 + exit $1 +} + +checkEmptyListResponse () { + case $1 in + 1) return 0;; + 0) killAgent 99;; + *) killAgent $1;; + esac + return 33 +} + +showAgentMsg() { + show_status $1 "$2" + if test $1 -ne 0; then + printf '%s' "${warn}" + cat "${SSH_ERRLOG}" + printf '%s' "${norm}" + if test $1 -ne 2; then + killAgent $1 + fi + exit $1 + fi + + if test "x$3" != "x"; then + printf '%s' "${done}" + cat "$3" + printf '%s' "${norm}" + fi + return 0 +} + + eval `"${TEST_SSH_SSHAGENT}"` > /dev/null + + "${TEST_SSH_SSHADD}" -L >/dev/null; checkEmptyListResponse $? + + "${TEST_SSH_SSHADD}" "${identity_file}" 2> "${SSH_ERRLOG}" > "${SSH_REPLY}"; \ + showAgentMsg $? " add identity ${extd}${SSH_CLIENTKEY}-${attn}${type}${norm} to agent ..." + + "${TEST_SSH_SSHADD}" -L 2> "${SSH_ERRLOG}" > "${SSH_REPLY}"; \ + retval=$? + if test $retval -ne 0; then + showAgentMsg ${retval} + else + printf " ${done}-${norm} " + cat "$SSH_REPLY" + fi + +# TODO +# Note the current script run ssh with -i option, +# but ssh check existence of file and when file +# don't exit it is excluded from list of identity +# files. When the list is empty ssh will use +# default file names. To avoid this we will +# use /dev/null, until method runTest run ssh +# with -i option +#!!! "use-only-key-from-agent" \ + runTest "${type}" \ + "/dev/null" \ + "key from agent ..." || + killAgent $? + + "${TEST_SSH_SSHADD}" -d "${identity_file}".pub \ + 2> "${SSH_ERRLOG}" > "${SSH_REPLY}"; \ + showAgentMsg $? " remove identity ${extd}${SSH_CLIENTKEY}-${attn}${type}${norm} from agent ..." + + "${TEST_SSH_SSHADD}" -L > /dev/null; checkEmptyListResponse $? + + "$TEST_SSH_SSHADD" "$identity_file" 2> "$SSH_ERRLOG" > "$SSH_REPLY"; \ + showAgentMsg $? " add identity ${extd}${SSH_CLIENTKEY}-${attn}${type}${norm} again to agent ..." + ( + echo "# some extra comments" + echo " # more comments" + echo " garbage data " + cat "$identity_file".pub + echo " more garbage data $identity_file " + ) | \ + "$TEST_SSH_SSHADD" -d - 2> "$SSH_ERRLOG" > "$SSH_REPLY"; \ + showAgentMsg $? " remove identity ${extd}${SSH_CLIENTKEY}-${attn}${type}${norm} (stdin) from agent ..." + "$TEST_SSH_SSHADD" -L > /dev/null; checkEmptyListResponse $? + + + killAgent 0 +) +} + + +# === + +do_test () { + retval=0 + echo "* ${extd}against ${attn}CACertificateFile${norm} and x509 identity from ${attn}agent${norm}:" + + creTestSSHDcfgFile + cat >> "$SSHD_CFG" <> "$SSHD_CFG" + case $fmt_srv in + *md5) + if test -n "$OPENSSL_FIPS"; then + if "$TEST_SSH_SSHD" -f "$SSHD_CFG" -t >> "$SSHD_LOG" 2>&1; then + echo " server in ${attn}FIPS${norm} mode - accept ${attn}$fmt_srv${norm} digest!" + return 99 + else + echo " server in ${attn}FIPS${norm} mode - skipping ..." + continue + fi + fi + ;; + esac + + + runSSHdaemon || return $? + ( + for SSH_CLIENTKEY in $TEST_SSH_CLIENTKEYS; do + case $SSH_CLIENTKEY in + *eccnistp*) continue;; + *ed25519) continue;; + *rsa) keytype="rsa";; + *dsa) keytype="dsa";; + *) echo "${warn}unknown client key type : $SSH_CLIENTKEY${norm}" + exit 1;; + esac + case $alg in + x509v3-*-rsa*) test "$keytype" = "rsa" || continue;; + x509v3-*-dss*) test "$keytype" = "dsa" || continue;; + *) + echo "${warn}unknown X.509 alg${norm}" >&2 + exit 1;; + esac + + for type in $SSH_SIGN_TYPES; do + identity_file="$SSH_CLIENTKEY-$type" + "$TEST_SSH_SSHKEYGEN" -f "$identity_file" -y 2>/dev/null > "$AUTHORIZEDKEYSFILE" || exit $? + + for fmt_cln in $fmt_list; do + TEST_CLIENT_CFG="\ +X509KeyAlgorithm $alg,$fmt_cln +" + if test $fmt_srv = $fmt_cln; then + must_fail=no + typemsg="$identity_file $fmt_cln" + else + must_fail=yes + typemsg="$identity_file $fmt_cln ${warn}!${norm}" + fi + must_fail_err_txt= + + if test -n "$OPENSSL_FIPS"; then + case $fmt_cln in + *md5) + typemsg="$identity_file $fmt_cln ${warn}FIPS mode!${norm}" + must_fail_err_txt='rsa-md5 in not enabled in FIPS mode' + ;; + esac + fi + + runTest "$typemsg" \ + "$identity_file" "" $must_fail $must_fail_err_txt || exit $? + done + done + done + ); retval=$? + killSSHdaemon + + test $retval -ne 0 && break + done + + return $retval +} + + +# === + +do_test () { + retval=0 + echo "* ${extd}against ${attn}CACertificateFile${norm} and different digest ${attn}algorithms${norm}:" + + for alg in \ + $SSH_ALGS_X509_RSA \ + $SSH_ALGS_X509_DSA \ + ; do + testAlgFmt; retval=$? + test $retval -ne 0 && break + done + return $retval +} diff -ruN openssh-9.4p1/tests/CA/test-alg.sh.inc openssh-9.4p1+x509-14.2.1/tests/CA/test-alg.sh.inc --- openssh-9.4p1/tests/CA/test-alg.sh.inc 1970-01-01 02:00:00.000000000 +0200 +++ openssh-9.4p1+x509-14.2.1/tests/CA/test-alg.sh.inc 2023-08-20 10:07:00.000000000 +0300 @@ -0,0 +1,275 @@ +# +# Copyright (c) 2004-2022 Roumen Petrov, Sofia, Bulgaria +# All rights reserved. +# +# Redistribution and use of this script, with or without modification, is +# permitted provided that the following conditions are met: +# +# 1. Redistributions of this script must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED +# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +# EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# DESCRIPTION: Test client authentication: +# - "IdentityFile" contain private key and optional x509 certificate; +# - "AuthorizedKeysFile" contain certificate BLOB. +# - 1) server accept different publickey algorithms. +# - 2) client use failback publickey algorithm. +# Note that "Host-Based Authentication" we can not test without to install. +# + + +# === +#args: +# $1 - identity file +fill_authorized () { + # fill with extra host-keys to simulate multiple key-types + cat testhostkey_*.pub > "$AUTHORIZEDKEYSFILE" + + "$TEST_SSH_SSHKEYGEN" -f "$1" -y 2>/dev/null >> "$AUTHORIZEDKEYSFILE" +} + + +# === +#env. vars: +# alg +testAlg1 () { + printSeparator + echo " - only ${attn}${alg}${norm} algorithm" + + creTestSSHDcfgFile + cat >> "$SSHD_CFG" </dev/null && withcert=yes + + # 'plain' key + must_fail=yes + if test -z "$withcert" ; then + case $SSH_CLIENTKEY in + *_rsa) case $alg in + rsa-sha2-*|ssh-rsa) must_fail=;; + esac;; + *_dsa) test $alg = ssh-dss && must_fail=;; + *_ecc*) curve=`echo $SSH_CLIENTKEY | sed 's/^.*_ecc//'` + test $alg = ecdsa-sha2-$curve && must_fail=;; + *_ed25519) test $alg = ssh-ed25519 && must_fail=;; + *) + echo "${warn}unknown 'plain' client key type${norm}" >&2 + exit 1;; + esac + fi + + identity_file="${SSH_CLIENTKEY}" + fill_authorized "$identity_file" || exit $? + + if test -n "$must_fail"; then + typemsg="${identity_file} ${warn}!${norm}" + else + typemsg="${identity_file}" + fi + runTest "${typemsg}" \ + "${identity_file}" "" "$must_fail" || exit $? + + # X.509 keys + for type in $SSH_SIGN_TYPES ; do + + must_fail=yes + if test -n "$withcert" ; then + case $SSH_CLIENTKEY in + *_rsa*) expr $alg : 'x509v3-.*-rsa' >/dev/null && must_fail=;; + *_dsa*) expr $alg : 'x509v3-.*-dss' >/dev/null && must_fail=;; + *_ecc*) curve=`echo $SSH_CLIENTKEY | sed 's/^.*_ecc//'` + test $alg = x509v3-ecdsa-sha2-$curve && must_fail=;; + *_ed25519) test $alg = x509v3-ssh-ed25519 && must_fail=;; + *) + echo "${warn}unknown 'x.509' client key type${norm}" >&2 + exit 1;; + esac + fi + + identity_file="${SSH_CLIENTKEY}-${type}" + fill_authorized "$identity_file" || exit $? + + if test -n "$must_fail"; then + typemsg="${identity_file} ${warn}!${norm}" + else + typemsg="${identity_file}" + fi + runTest "${typemsg}" \ + "${identity_file}" "" "$must_fail" || exit $? + done + done + ); retval=$? + killSSHdaemon + + return $retval +} + + +# === +#env. vars: +# alg - only public key based +testAlg2 () { + printSeparator + echo " - client failback to ${attn}${alg}${norm} algorithm" + + creTestSSHDcfgFile + cat >> "$SSHD_CFG" <&2 + exit 1;; + esac + + identity_file="$SSH_CLIENTKEY" + fill_authorized "$identity_file" || exit $? + + for type in $SSH_SIGN_TYPES; do + identity_file="$SSH_CLIENTKEY-$type" + + if test -n "$must_fail"; then + typemsg="$identity_file ${warn}!${norm}" + else + typemsg="$identity_file" + fi + + runTest "$typemsg" "$identity_file" "" "$must_fail" || exit $? + done + done + ); retval=$? + killSSHdaemon + + return $retval +} + + +# === +#env. vars: +# alg +testAlg3 () { + printSeparator + echo " - only ${attn}X.509${norm} algorithms" + + creTestSSHDcfgFile + cat >> "$SSHD_CFG" </dev/null > "$AUTHORIZEDKEYSFILE" || return $? + runTest "$type" "$identity_file"\ + "${extd}valid${norm}" || return $? + + blob=`cat "$AUTHORIZEDKEYSFILE"` + echo $blob | cut -c 1-50 > "$AUTHORIZEDKEYSFILE" + runTest "$type" "$identity_file"\ + "${warn}invalid${norm}" "Yes" || return $? +} + + +# === +#env. vars: +# SSH_CLIENTKEY +# type +testPUBKEYautorization () { + base_identity_file="$SSH_CLIENTKEY" + if test ! -r "$base_identity_file" ; then + error_file_not_readable "$base_identity_file"; return $? + fi + identity_file="$base_identity_file-$type" + if test ! -r "$identity_file" ; then + error_file_not_readable "$identity_file"; return $? + fi + + echo " using $base_identity_file to autorize X.509/$type" + + "$TEST_SSH_SSHKEYGEN" -f "$base_identity_file" -y 2>/dev/null > "$AUTHORIZEDKEYSFILE" || return $? + runTest "$type" "$identity_file"\ + "${extd}valid${norm}" || return $? + + blob=`cat "$AUTHORIZEDKEYSFILE"` + echo $blob | cut -c 1-50 > "$AUTHORIZEDKEYSFILE" + runTest "$type" "$identity_file"\ + "${warn}invalid${norm}" "Yes" || return $? +} + + +# === + +do_test () { + retval=0 + echo "* ${extd}with ${attn}CACertificateFile${norm} and" + echo "* ${extd}authorization${norm} by encoded ${attn}public identity${norm}:" + + creTestSSHDcfgFile + cat >> "$SSHD_CFG" < $LDAPD_CFG +} + + +# === +creTestLDAPDCAldifFile() { +( + for level in 0; do + N="$CAKEY_PREFIX"-root$level.crt + if test ! -f ldap/"$N".der; then + $OPENSSL x509 \ + -in "$SSH_CAROOT/crt/$N.pem" \ + -out ldap/"$N".der -outform DER + retval=$? + if test $retval -ne 0; then + rm -f ldap/"$N".der + exit $retval + fi + fi + done + + for type in $SSH_SIGN_TYPES; do + N="$CAKEY_PREFIX"-$type.crt + if test ! -f ldap/"$N".der; then + $OPENSSL x509 \ + -in "$SSH_CAROOT/crt/$N.pem" \ + -out ldap/"$N".der -outform DER + retval=$? + if test $retval -ne 0; then + rm -f ldap/"$N".der + exit $retval + fi + fi + + N="$CAKEY_PREFIX"-$type.crl + if test ! -f ldap/"$N".der; then + $OPENSSL crl \ + -in "$SSH_CAROOT/crl/$N.pem" \ + -out ldap/"$N".der -outform DER + retval=$? + if test $retval -ne 0; then + rm -f ldap/"$N".der + exit $retval + fi + fi + done +) || return $? + +( + for level in 0; do + cat < ldap/ca.ldif +} + + +# === +runLDAPdaemon() { + if test -f "${LDAPD_PID}"; then + echo "${warn}slapd pid file exist!${norm}" >&2 + fi + + printf ' %s' "starting ${extd}LDAP${norm} server on ${attn}${LDAPD_URL}${norm}" + #for errors check syslog files(LOCAL4 facility) + $SUDO "${LDAP_LIBEXECDIR}/slapd" \ + -f "${LDAPD_CFG}" \ + -h "${LDAPD_URL}" \ + > /dev/null 2>&1 + + sleep 2 + K=0 + while test $K -le 5; do + if test -f "${LDAPD_PID}"; then + break + fi + sleep 1 + K=`expr $K + 1` + done + + test -r "${LDAPD_PID}"; show_status $? + if test ! -r "${LDAPD_PID}"; then + printf "${warn}cannot start slapd:${norm} " >&2 + error_file_not_readable "${LDAPD_PID}" + return 33 + fi + return 0 +} + + +killLDAPdaemon() { +( + $SUDO kill `cat "${LDAPD_PID}" 2>/dev/null` > /dev/null 2>&1 + K=0 + while test $K -le 9; do + if test ! -f "${LDAPD_PID}"; then + break + fi + sleep 1 + K=`expr $K + 1` + done + if test -f "${LDAPD_PID}"; then + $SUDO kill -9 `cat "${LDAPD_PID}" 2>/dev/null` > /dev/null 2>&1 + sleep 1 + $SUDO rm -f "${LDAPD_PID}" > /dev/null 2>&1 + $SUDO rm -f "${LDAPD_ARGS}" > /dev/null 2>&1 + fi + rm -f "${LDAPD_CFG}" + exit 0 +) +} + + +initLDAPdb() { + create_empty_file "${LDAP_SETUP_LOG}" || return $? + + "${LDAPADD}" \ + -x -w secret -D "cn=Manager,${SSH_LDAP_DC}" \ + -H "${LDAPD_URL}" \ + -f "${CWD}/ldap/base.ldif" \ + >> "${LDAP_SETUP_LOG}" 2>&1 || return $? + + "${LDAPADD}" \ + -x -w secret -D "cn=Manager,${SSH_LDAP_DC}" \ + -H "${LDAPD_URL}" \ + -f "${CWD}/ldap/ca.ldif" \ + >> "${LDAP_SETUP_LOG}" 2>&1 || return $? + + return 0 +} + + +# === +# $1 - LDAP version +testLDAP() { + printSeparator + echo "Begin test with LDAP ${extd}version${norm} ${attn}$1${norm}" + + creTestLDAPDcfgFile + creTestLDAPDCAldifFile + creTestSSHDcfgFile + +#limitation of configuration parser +SSH_CONF_LDAP_DC=`echo ${SSH_LDAP_DC} | sed -e 's|=|%3D|g' -e 's|,|%2C|'` + cat >> "$SSHD_CFG" <> "$SSHD_CFG" <> "$SSHD_CFG" <> "$SSHD_CFG" <> "$SSHD_CFG" < /dev/null + cre_crl_hash_link "$SSH_CAROOT/crl/$CAKEY_PREFIX-$crltype.crl.pem" "$CRL_TEST_DIR" + retval=$? + #printf "${norm}" + show_status $retval || return $? + + ( + for type in ${SSH_SIGN_TYPES}; do + for SSH_CLIENTKEY in ${TEST_SSH_CLIENTKEYS}; do + identity_file="${SSH_CLIENTKEY}-${type}-revoked" + + creX509AuthorizedKeysFile "${identity_file}" || exit $? + + if test "${type}" = "${crltype}"; then + runTest "${SSH_CLIENTKEY}-${warn}${type}-revoked${norm}" \ + "${identity_file}" "" "Yes" + else + runTest "${identity_file}" \ + "${identity_file}" "" "" + fi || exit $? + done + done + exit 0 + ); retval=$? + + if test $retval -eq 0; then + rm "$hash_link"; retval=$? + else + rm -f "$hash_link" + fi + return $retval +} + + +# === +test_onlyonecrl () { + retval=0 + CRL_TEST_DIR="${SSH_CAROOT}/crl-test" + + printSeparator + echo "Check ${extd}revoked${norm} with only ${attn}one CRL${norm} in ${attn}CARevocationPath${norm} ..." + + mkdir -p "${CRL_TEST_DIR}" || return $? + + creTestSSHDcfgFile + cat >> "$SSHD_CFG" < /dev/null + if test ${retval} -eq 0; then + rmdir "${CRL_TEST_DIR}"; retval=$? + else + rmdir "${CRL_TEST_DIR}" + fi + return ${retval} +} + + +# === +test_crlpresence_yes () { + printSeparator + echo "Begin test with mandatory ${extd}CRL presence ${attn}with${norm} CRL ..." + + creTestSSHDcfgFile + cat >> "$SSHD_CFG" <> "$SSHD_CFG" < "${AUTHORIZEDKEYSFILE}" + runTest "${type} ${subtype}" "${identity_file}" "" || return $? + done + + subtype="subject" + subject=`getSubject "${identity_file}" -nameopt RFC2253 -nameopt -esc_msb` || return $? + echo "${sshkeytype} ${subtype} ${subject}" > "${AUTHORIZEDKEYSFILE}" + runTest "${type} ${subtype} in ${attn}RFC2253${norm} format" "${identity_file}" "" || return $? + + echo "${sshkeytype} ${subtype} ${subject}" | sed -e 's/,/\//'> "${AUTHORIZEDKEYSFILE}" + runTest "${type} ${subtype} and mixed item-separator symbol" "${identity_file}" "" || return $? + + for subtype in \ + "Invalid" \ + "Subject-" \ + ; do + echo "${sshkeytype} ${subtype} ${subject}" > "${AUTHORIZEDKEYSFILE}" + runTest "${type} ${warn}${subtype}${norm}" "${identity_file}" \ + "authorization type" "Yes" || return $? + done + + subtype="Subject" + printf "${sshkeytype} ${subtype}," > "${AUTHORIZEDKEYSFILE}" + runTest "${type} ${warn}empty${norm} ${subtype}" "${identity_file}" \ + "" "Yes" || return $? + + subtype="Subject" + ( printf "${sshkeytype} ${subtype}" + echo "${subject}" | cut -c -40 + ) > "${AUTHORIZEDKEYSFILE}" + runTest "${type} ${warn}invalid${norm} ${subtype}" "${identity_file}" \ + "" "Yes" || return $? + + return 0 +} + + +# === + +do_test () { + echo "* ${extd}against ${attn}CACertificateFile${norm} and authorization by X.509 ${attn}'Distinguished Name'${norm}:" + + creTestSSHDcfgFile + cat >> "$SSHD_CFG" <> "$SSHD_CFG" </dev/null + + for catype in ${SSH_SIGN_TYPES}; do + ( cd "$CRT_TEST_DIR" && + rm -f "$CRT_TEST_DIR"/* && + for level in 0; do + cre_hash_link "$SSH_CAROOT/crt/$CAKEY_PREFIX-root${level}.crt.pem" || exit $? + done + cre_hash_link "$SSH_CAROOT/crt/$CAKEY_PREFIX-$catype.crt.pem" + ) && + do_test_catype; retval=$? + rm -f "$CRT_TEST_DIR"/* + if test $retval -ne 0; then + break + fi + done + + rmdir "${CRT_TEST_DIR}" + if test $retval -ne 0; then + exit $retval + fi + done + + exit 0 + ); retval=$? + killSSHdaemon + return $retval +} diff -ruN openssh-9.4p1/tests/CA/test-hostalg.sh.inc openssh-9.4p1+x509-14.2.1/tests/CA/test-hostalg.sh.inc --- openssh-9.4p1/tests/CA/test-hostalg.sh.inc 1970-01-01 02:00:00.000000000 +0200 +++ openssh-9.4p1+x509-14.2.1/tests/CA/test-hostalg.sh.inc 2023-08-20 10:07:00.000000000 +0300 @@ -0,0 +1,179 @@ +# +# Copyright (c) 2012-2022 Roumen Petrov, Sofia, Bulgaria +# All rights reserved. +# +# Redistribution and use of this script, with or without modification, is +# permitted provided that the following conditions are met: +# +# 1. Redistributions of this script must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED +# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +# EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# DESCRIPTION: Test client authentication: +# - "IdentityFile" contain private key and optional X.509 certificate; +# - "AuthorizedKeysFile" contain encoded client public key; +# - user "KnownHostsFile" contain records for each host key; +# - client accept certain hostkey algorithm. +# + + +USERKNOWNHOSTSFILE="$USERDIR/known_hosts-HostsTests" +for RSA_DGST in $SSH_SIGN_TYPES; do + # get first key rsa.... + break +done + + +# === + +HOSTKEYtestBREAK() { + echo + rm -f $USERKNOWNHOSTSFILE + rm -f $SSHD_CFG.tmp + testBREAK +} + +trap HOSTKEYtestBREAK HUP INT QUIT ABRT TERM || exit 1 + + +# === + +do_test () { + echo "* with ${extd}different ${attn}hostkey${norm} algorithms:" + + creTestSSHDcfgFile + + cat >> "$SSHD_CFG" < $SSHD_CFG + rm $SSHD_CFG.tmp + +if test -n "$SSH_ALGS_X509_RSA" ; then +( + echo "# x509v3-*-rsa (legacy or RFC6187)" + echo "HostKey \"$CWD/testhostkey_rsa-$RSA_DGST\"" +) >> "$SSHD_CFG" +fi +if test -n "$SSH_ALGS_X509_DSA" ; then +( + echo "# x509v3-*-dss (legacy or RFC6187)" + echo "HostKey \"$CWD/testhostkey_dsa-dsa\"" +) >> "$SSHD_CFG" +fi +if test -n "$SSH_ALGS_X509_EC" ; then +( + echo "# x509v3-ecdsa-sha2-* (RFC6187)" + for alg in $SSH_ALGS_X509_EC ; do + case $alg in + x509v3-ecdsa-sha2-*) + curve=`echo $alg | sed 's/^.*ecdsa-sha2-//'` + hostkey=ecc$curve-$RSA_DGST + echo "HostKey \"$CWD/testhostkey_$hostkey\"" + ;; + esac + done +) >> "$SSHD_CFG" +fi +if test -n "$SSH_ALGS_X509_ED25519" ; then +( + echo "# x509v3-ssh-ed25519" + echo "HostKey \"$CWD/testhostkey_ed25519-$RSA_DGST\"" +) >> "$SSHD_CFG" +fi + + runSSHdaemon || return $? + ( + identity_file="testid_rsa-$RSA_DGST" + "$TEST_SSH_SSHKEYGEN" -f "$identity_file" -y 2>/dev/null > "$AUTHORIZEDKEYSFILE" || exit $? + + printSeparator + + for alg in \ + $SSH_ALGS_X509 \ + $SSH_ALGS_PLAIN \ + ; do + + plainkey=: + expr $alg : 'x509v3-' >/dev/null && plainkey=false + + case $alg in + x509v3-*-rsa|\ + rsa-sha2-*|\ + ssh-rsa) hostkey=rsa;; + *ecdsa-sha2-*) + curve=`echo $alg | sed 's/^.*ecdsa-sha2-//'` + hostkey=ecc$curve;; + x509v3-*-dss|\ + ssh-dss) hostkey=dsa;; + x509v3-*-ed25519|\ + ssh-ed25519) hostkey=ed25519;; + *) + echo "${warn}unsupported public key algorithm : $alg${norm}" >&2 + exit 1;; + esac + + TEST_CLIENT_CFG="\ +HostKeyAlgorithms $alg +" + + typemsg="$alg" + mustfail=no + errmsg= + + infomsg=".../testhostkey_$hostkey.pub ${extd}plain${norm}" + cat > $USERKNOWNHOSTSFILE < $USERKNOWNHOSTSFILE < $USERKNOWNHOSTSFILE <&2 + count=`expr ${count}` + while test ${count} -gt 0; do + printf 'O'; sleep 1 + count=`expr ${count} - 1` + done + printf '-'; sleep 1 + printf '/'; sleep 1 + printf '-'; sleep 1 + printf 'X'; sleep 1 + printf '\n' +) +} + + +# === +killResponders() { +( + if test -z "$SSH_OPENSSL_OCSP_TMOUT"; then + ( + has="" + for pidfile in va-*.pid; do + if test -r "${pidfile}"; then + kill `cat "${pidfile}"` > /dev/null 2>&1 + has="yes" + fi + done + if test -n "${has}"; then + openssl_ocsp_tmout + fi + ) + fi + ( + has="" + for pidfile in va-*.pid; do + if test -r "${pidfile}"; then + kill -9 `cat "${pidfile}"` > /dev/null 2>&1 + rm -f "${pidfile}" + has="yes" + fi + done + if test -n "${has}"; then + openssl_ocsp_tmout + fi + ) + : +) +} + + +# === +OCSPtestBREAK() { + echo + killResponders + testBREAK +} + +trap OCSPtestBREAK HUP INT QUIT ABRT TERM || exit 1 + + +# === +#args: +# $1 - port +#env. vars: +# OCSP_RESPKEY +# type +runResponder() { +( + port=$1 + + pidfile="va-${port}.pid" + test -r "${pidfile}" && exit 1 + + printf ' %s' "starting OCSP ${extd}responder${norm}(${attn}${type}${norm}) on ${attn}${SSHD_LISTENADDRESS}:${port}${norm}" + ( + ${OPENSSL} ocsp \ + -CA "$SSH_CAROOT/crt/${CAKEY_PREFIX}-${type}.crt.pem" \ + -rsigner "${OCSP_RESPKEY}-${type}.crt" \ + -rkey "${OCSP_RESPKEY}" \ + -index "${SSH_CAROOT}/index-${type}.txt" \ + -host ${SSHD_LISTENADDRESS} \ + -port ${port} > va-${type}.log 2>&1 & + pid=$! + echo ${pid} > "${pidfile}" + wait ${pid} + rm -f "${pidfile}" + ) 2> /dev/null & + + sleep 1 + test -r "${pidfile}"; show_status $? +) +} + + +# === +test_ocsp_cert () { +( + printSeparator + echo "Begin test ${extd}against${norm} OCSP provider from ${attn}certificate${norm} ..." + + retval=1 + for OCSP_RESPKEY in ${TEST_OCSP_RESPKEYS}; do + printSeparator + echo " responder key base ${attn}$OCSP_RESPKEY${norm} ..." + + creTestSSHDcfgFile + cat >> "$SSHD_CFG" <> "$SSHD_CFG" < "$AUTHORIZEDKEYSFILE" && + runTest "$type" "$identity_file" "$blob_msg" $encoded_fail \ + || return $? + + if test yes = $encoded_fail; then + blob_msg="encoded ${warn}X.509${norm} certificate" + else + blob_msg="encoded ${extd}X.509${norm} certificate" + fi + # X.509 certificate + cat "$identity_file.pub" > "$AUTHORIZEDKEYSFILE" && + runTest "$type" "$identity_file" "$blob_msg" $encoded_fail \ + || return $? + + sshkeytype=`getSSHkeyType "$identity_file"` || return $? + subject=`getSubject "$identity_file"` || return $? + # X.509 certificate distinguished name + echo "$sshkeytype Subject: $subject" > "$AUTHORIZEDKEYSFILE" && + runTest "$type" "$identity_file" "$dn_msg" "$2" \ + || return $? + done +} + +# === + +test_store () { + retval=0 + echo " - ${attn}with${norm} self-issued trusted by ${extd}x509store${norm}:" + printSeparator + + cat selfid_*.crt > $CWD/selfid-bundle + + creTestSSHDcfgFile + cat >> "$SSHD_CFG" <> "$SSHD_CFG" < /dev/null ; then + echo "${warn}skipped due to openssl verification bug${norm}" >&2 + echo "(see email thread ${attn}1.0.2beta2 and X.509 certificate verification${norm})" >&2 + return 0 + fi + echo "... ${extd}none found!${norm}" + + printSeparator + + creTestSSHDcfgFile + cat >> "$SSHD_CFG" <> "$SSHD_CFG" <= 1.1.1(Store2 API). +# + + +SSH_ASKPASS=`pwd`/ssh_askpass-p12 + +# === +#env. vars: +# SSH_CLIENTKEY +# type +testX509autorization () { + identity_file="$SSH_CLIENTKEY-$type" + if test ! -r "$identity_file" ; then + error_file_not_readable "$identity_file"; return $? + fi + + "$TEST_SSH_SSHKEYGEN" -f "$identity_file" -y 2>/dev/null > "$AUTHORIZEDKEYSFILE" || return $? + runTest "${norm}store:${extd}$SSH_CLIENTKEY${norm}..." \ + store:"$identity_file".p12 "$type" || return $? +} + + +# === + +do_test () { + retval=0 + if $USE_OPENSSL_STORE2 ; then : + else + echo "* ${extd}STORE${norm} is ${attn}not supported${norm}" + return 1 + fi + echo "* ${extd}with ${attn}CACertificateFile${norm} using ${attn}\"store\"${norm}" + + creTestSSHDcfgFile + cat >> "$SSHD_CFG" < ssh_askpass-p12 </dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; + esac +fi + + +# which compatible shell function +which() +{ + case "$1" in + */*) + case "$1" in + /*) which_PATH0="${1%/*}" + which_PATH="$which_PATH0" + ;; + .*/*) which_PATH0="${1%/*}" + which_PATH="`if cd $which_PATH0 2>/dev/null; then pwd ; fi`" + ;; + *) which_PATH0="./${1%/*}" + which_PATH="`pwd`/${1%/*}" + ;; + esac + which_NAME=${1##*/} + ;; + *) which_PATH0="$PATH" + which_PATH="$which_PATH0" + which_NAME="$1" + ;; + esac + which_IFS="$IFS" + IFS=":" + for D in $which_PATH "" ; do + test -z "$D" && continue + test -x "$D/$which_NAME" || continue + + IFS="$which_IFS" + echo "$D/$which_NAME" + return 0 + done + IFS="$which_IFS" + echo "which: no $which_NAME in ($which_PATH0)" >&2 + return 1 +} diff -ruN openssh-9.4p1/tests/env.in openssh-9.4p1+x509-14.2.1/tests/env.in --- openssh-9.4p1/tests/env.in 1970-01-01 02:00:00.000000000 +0200 +++ openssh-9.4p1+x509-14.2.1/tests/env.in 2023-08-20 10:07:00.000000000 +0300 @@ -0,0 +1,26 @@ +TEST_SHELL=${TEST_SHELL-@TEST_SHELL@} +EGREP="@EGREP@" +AWK="@AWK@" + +# pass configuration to regression tests +sysconfdir=@sysconfdir@ +EXEEXT=@EXEEXT@ +TEST_SSH_IPV6=@TEST_SSH_IPV6@ +TEST_SSH_UTF8=@TEST_SSH_UTF8@ +USE_OPENSSL_STORE2=@USE_OPENSSL_STORE2@ + +# OCSP enabled +@OCSP_ON@SSH_OCSP_ENABLED=: +@OCSP_OFF@SSH_OCSP_ENABLED=false + +# LDAP environment: +@LDAP_ON@SSH_LDAP_ENABLED=: +@LDAP_OFF@SSH_LDAP_ENABLED=false + +@LDAP_ON@LDAP_SYSCONFDIR="@LDAP_SYSCONFDIR@" +@LDAP_ON@LDAP_LIBEXECDIR="@LDAP_LIBEXECDIR@" +@LDAP_ON@LDAP_BINDIR="@LDAP_BINDIR@" +@LDAP_ON@LDAPADD="@LDAPADD@" + +# FIPS capable openssl +OPENSSL_FIPS_MODE=@OPENSSL_FIPS_MODE@ diff -ruN openssh-9.4p1/TODO openssh-9.4p1+x509-14.2.1/TODO --- openssh-9.4p1/TODO 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/TODO 2023-08-20 10:07:00.000000000 +0300 @@ -30,12 +30,10 @@ - More platforms for for setproctitle() emulation (testing needed) -- Improve PAM ChallengeResponseAuthentication +- Improve PAM KbdInteractiveAuthentication - Informational messages - Use different PAM service name for kbdint vs regular auth (suggest from Solar Designer) - - Ability to select which ChallengeResponseAuthentications may be used - and order to try them in e.g. "ChallengeResponseAuthentication pam" - Complete Tru64 SIA support - It looks like we could merge it into the password auth code to cut down diff -ruN openssh-9.4p1/ttymodes.c openssh-9.4p1+x509-14.2.1/ttymodes.c --- openssh-9.4p1/ttymodes.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/ttymodes.c 2023-08-20 10:07:01.000000000 +0300 @@ -56,7 +56,6 @@ #include "log.h" #include "compat.h" #include "sshbuf.h" -#include "ssherr.h" #define TTY_OP_END 0 /* @@ -291,7 +290,7 @@ goto end; } if (tcgetattr(fd, &tio) == -1) { - logit("tcgetattr: %.100s", strerror(errno)); + debug_f("tcgetattr: %.100s", strerror(errno)); goto end; } } else @@ -316,7 +315,8 @@ #define SSH_TTYMODE_IUTF8 42 /* for SSH_BUG_UTF8TTYMODE */ #define TTYMODE(NAME, FIELD, OP) \ - if (OP == SSH_TTYMODE_IUTF8 && (ssh->compat & SSH_BUG_UTF8TTYMODE)) { \ + if (OP == SSH_TTYMODE_IUTF8 && \ + ssh_compat_fellows(ssh, SSH_BUG_UTF8TTYMODE)) { \ debug3_f("SSH_BUG_UTF8TTYMODE"); \ } else if ((r = sshbuf_put_u8(buf, OP)) != 0 || \ (r = sshbuf_put_u32(buf, ((tio.FIELD & NAME) != 0))) != 0) \ @@ -365,7 +365,7 @@ * modes, they will initially have reasonable values. */ if (tcgetattr(fd, &tio) == -1) { - logit("tcgetattr: %.100s", strerror(errno)); + debug("tcgetattr: %.100s", strerror(errno)); failure = -1; } @@ -428,7 +428,7 @@ fatal_fr(r, "parse arg"); break; } else { - logit_f("unknown opcode %d", opcode); + error_f("unknown opcode %d", opcode); goto set; } } @@ -438,7 +438,7 @@ len = sshbuf_len(buf); sshbuf_free(buf); if (len > 0) { - logit_f("%zu bytes left", len); + error_f("%zu bytes left", len); return; /* Don't process bytes passed */ } if (failure == -1) diff -ruN openssh-9.4p1/uidswap.c openssh-9.4p1+x509-14.2.1/uidswap.c --- openssh-9.4p1/uidswap.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/uidswap.c 2023-08-20 10:07:01.000000000 +0300 @@ -64,7 +64,7 @@ #ifdef SAVED_IDS_WORK_WITH_SETEUID saved_euid = geteuid(); saved_egid = getegid(); - debug("temporarily_use_uid: %u/%u (e=%u/%u)", + debug_f("%u/%u (e=%u/%u)", (u_int)pw->pw_uid, (u_int)pw->pw_gid, (u_int)saved_euid, (u_int)saved_egid); #ifndef HAVE_CYGWIN @@ -143,14 +143,14 @@ { /* it's a no-op unless privileged */ if (!privileged) { - debug("restore_uid: (unprivileged)"); + debug_f("(unprivileged)"); return; } if (!temporarily_use_uid_effective) - fatal("restore_uid: temporarily_use_uid not effective"); + fatal_f("temporarily_use_uid not effective"); #ifdef SAVED_IDS_WORK_WITH_SETEUID - debug("restore_uid: %u/%u", (u_int)saved_euid, (u_int)saved_egid); + debug_f("%u/%u", (u_int)saved_euid, (u_int)saved_egid); /* Set the effective uid back to the saved privileged uid. */ if (seteuid(saved_euid) == -1) fatal("seteuid %u: %.100s", (u_int)saved_euid, strerror(errno)); @@ -163,9 +163,9 @@ * as well. */ if (setuid(getuid()) == -1) - fatal("%s: setuid failed: %s", __func__, strerror(errno)); + fatal_f("setuid failed: %s", strerror(errno)); if (setgid(getgid()) == -1) - fatal("%s: setgid failed: %s", __func__, strerror(errno)); + fatal_f("setgid failed: %s", strerror(errno)); #endif /* SAVED_IDS_WORK_WITH_SETEUID */ if (setgroups(saved_egroupslen, saved_egroups) == -1) @@ -186,10 +186,10 @@ #endif if (pw == NULL) - fatal("permanently_set_uid: no user given"); + fatal_f("no user given"); if (temporarily_use_uid_effective) - fatal("permanently_set_uid: temporarily_use_uid effective"); - debug("permanently_set_uid: %u/%u", (u_int)pw->pw_uid, + fatal_f("temporarily_use_uid effective"); + debug_f("%u/%u", (u_int)pw->pw_uid, (u_int)pw->pw_gid); if (setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) == -1) @@ -212,27 +212,25 @@ /* Try restoration of GID if changed (test clearing of saved gid) */ if (old_gid != pw->pw_gid && pw->pw_uid != 0 && (setgid(old_gid) != -1 || setegid(old_gid) != -1)) - fatal("%s: was able to restore old [e]gid", __func__); + fatal_f("was able to restore old [e]gid"); #endif /* Verify GID drop was successful */ if (getgid() != pw->pw_gid || getegid() != pw->pw_gid) { - fatal("%s: egid incorrect gid:%u egid:%u (should be %u)", - __func__, (u_int)getgid(), (u_int)getegid(), - (u_int)pw->pw_gid); + fatal_f("egid incorrect gid:%u egid:%u (should be %u)", + (u_int)getgid(), (u_int)getegid(), (u_int)pw->pw_gid); } #ifndef NO_UID_RESTORATION_TEST /* Try restoration of UID if changed (test clearing of saved uid) */ if (old_uid != pw->pw_uid && (setuid(old_uid) != -1 || seteuid(old_uid) != -1)) - fatal("%s: was able to restore old [e]uid", __func__); + fatal_f("was able to restore old [e]uid"); #endif /* Verify UID drop was successful */ if (getuid() != pw->pw_uid || geteuid() != pw->pw_uid) { - fatal("%s: euid incorrect uid:%u euid:%u (should be %u)", - __func__, (u_int)getuid(), (u_int)geteuid(), - (u_int)pw->pw_uid); + fatal_f("euid incorrect uid:%u euid:%u (should be %u)", + (u_int)getuid(), (u_int)geteuid(), (u_int)pw->pw_uid); } } diff -ruN openssh-9.4p1/umac.c openssh-9.4p1+x509-14.2.1/umac.c --- openssh-9.4p1/umac.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/umac.c 2023-08-20 10:07:01.000000000 +0300 @@ -154,18 +154,31 @@ /* UMAC uses AES with 16 byte block and key lengths */ #define AES_BLOCK_LEN 16 -/* OpenSSL's AES */ -#ifdef WITH_OPENSSL -#include "openbsd-compat/openssl-compat.h" -#ifndef USE_BUILTIN_RIJNDAEL -# include +#if defined(WITH_OPENSSL) && defined(HAVE_AES_ENCRYPT) +/* Note low level AES API is deprecated in OpenSSL 3.0. + * We will not use it for builds with OpenSSL < 3.0 + * unless build-in rijndael is requested globaly. + */ +# if !defined(USE_BUILTIN_RIJNDAEL) && \ + defined(HAVE_ERR_GET_ERROR_ALL) /* new is OpenSSL 3.0 */ +# define USE_BUILTIN_RIJNDAEL /* force build-in rijndael */ +# endif +#else +# ifndef USE_BUILTIN_RIJNDAEL +# define USE_BUILTIN_RIJNDAEL +# endif #endif + +#ifndef USE_BUILTIN_RIJNDAEL +/* OpenSSL's AES */ +#include typedef AES_KEY aes_int_key[1]; #define aes_encryption(in,out,int_key) \ AES_encrypt((u_char *)(in),(u_char *)(out),(AES_KEY *)int_key) #define aes_key_setup(key,int_key) \ AES_set_encrypt_key((const u_char *)(key),UMAC_KEY_LEN*8,int_key) #else +/* build-in rijndael */ #include "rijndael.h" #define AES_ROUNDS ((UMAC_KEY_LEN / 4) + 6) typedef UINT8 aes_int_key[AES_ROUNDS+1][4][4]; /* AES internal */ diff -ruN openssh-9.4p1/utf8.c openssh-9.4p1+x509-14.2.1/utf8.c --- openssh-9.4p1/utf8.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/utf8.c 2023-08-20 10:07:01.000000000 +0300 @@ -1,6 +1,7 @@ /* $OpenBSD: utf8.c,v 1.11 2020/05/01 06:28:52 djm Exp $ */ /* * Copyright (c) 2016 Ingo Schwarze + * Copyright (c) 2019 Roumen Petrov. All rights reserved. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -39,6 +40,10 @@ # include #endif +#ifndef HAVE_NL_LANGINFO +# define nl_langinfo(x) "" +#endif + #include "utf8.h" static int dangerous_locale(void); @@ -52,21 +57,28 @@ * For state-dependent encodings, recovery is impossible. * For arbitrary encodings, replacement of non-printable * characters would be non-trivial and too fragile. + * As exception is used 8-bit codeset ISO8859-1 as on some operating + * system it is default for "C"("POSIX") locale. * The comments indicate what nl_langinfo(CODESET) - * returns for US-ASCII on various operating systems. + * returns for "C" locale on various operating systems. */ static int dangerous_locale(void) { +#ifdef __ANDROID__ + /* nl_langinfo is not supported properly */ + return 0; +#else char *loc; loc = nl_langinfo(CODESET); return strcmp(loc, "UTF-8") != 0 && - strcmp(loc, "US-ASCII") != 0 && /* OpenBSD */ strcmp(loc, "ANSI_X3.4-1968") != 0 && /* Linux */ - strcmp(loc, "ISO8859-1") != 0 && /* AIX */ strcmp(loc, "646") != 0 && /* Solaris, NetBSD */ + strcmp(loc, "US-ASCII") != 0 && /* OpenBSD */ + strcmp(loc, "ISO8859-1") != 0 && /* AIX */ strcmp(loc, "") != 0; /* Solaris 6 */ +#endif } static int @@ -255,7 +267,7 @@ } int -asmprintf(char **outp, size_t sz, int *wp, const char *fmt, ...) +asnmprintf(char **outp, size_t sz, int *wp, const char *fmt, ...) { va_list ap; int ret; @@ -345,6 +357,7 @@ if ((strcasestr(cp, "UTF-8") != NULL || strcasestr(cp, "UTF8") != NULL) && (setlocale(LC_CTYPE, "C.UTF-8") != NULL || + setlocale(LC_CTYPE, "en_US.UTF-8") != NULL || setlocale(LC_CTYPE, "POSIX.UTF-8") != NULL)) return; setlocale(LC_CTYPE, "C"); @@ -353,3 +366,46 @@ /* We can handle this locale */ setlocale(LC_CTYPE, ""); } + +#include "evp-compat.h" +/* mbtowc implementation based on OpenSSL function UTF8_getc */ + +#ifndef HAVE_MBTOWC +int +mbtowc(wchar_t *pwc, const char *s, size_t n) { + int r, len; + unsigned long val; + + if (s == NULL) return 0; + if (*s == '\0') return 0; + +#ifdef __ANDROID__ +/* NOTE: function is called will MB_CUR_MAX, but before API 21 + * locale is not supported. For consistency we ignore argument + * and we will use 6 as this is maximum for UTF8_getc(). + */ + UNUSED(n); + len = 6; +#else + len = (int)n; + if (n != (size_t)len) { + errno = EINVAL; + return -1; + } +#endif + + r = UTF8_getc(s, len, &val); + if (r < 0) return -1; + if ((r > 0) && (pwc != NULL)) + *pwc = val; + + return r; +} +#endif /*ndef HAVE_MBTOWC*/ + +#ifndef HAVE_MBLEN +int +mblen(const char *s, size_t n) { + return mbtowc(NULL, s, n); +} +#endif diff -ruN openssh-9.4p1/utf8.h openssh-9.4p1+x509-14.2.1/utf8.h --- openssh-9.4p1/utf8.h 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/utf8.h 2023-08-20 10:07:00.000000000 +0300 @@ -23,6 +23,6 @@ int vfmprintf(FILE *, const char *, va_list); int snmprintf(char *, size_t, int *, const char *, ...) __attribute__((format(printf, 4, 5))); -int asmprintf(char **, size_t, int *, const char *, ...) +int asnmprintf(char **, size_t, int *, const char *, ...) __attribute__((format(printf, 4, 5))); void msetlocale(void); diff -ruN openssh-9.4p1/version.h openssh-9.4p1+x509-14.2.1/version.h --- openssh-9.4p1/version.h 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/version.h 2023-08-20 10:07:00.000000000 +0300 @@ -2,5 +2,4 @@ #define SSH_VERSION "OpenSSH_9.4" -#define SSH_PORTABLE "p1" -#define SSH_RELEASE SSH_VERSION SSH_PORTABLE +#define SSH_RELEASE PACKAGE_STRING ", " SSH_VERSION "p1" diff -ruN openssh-9.4p1/version.m4 openssh-9.4p1+x509-14.2.1/version.m4 --- openssh-9.4p1/version.m4 1970-01-01 02:00:00.000000000 +0200 +++ openssh-9.4p1+x509-14.2.1/version.m4 2023-08-20 10:07:00.000000000 +0300 @@ -0,0 +1,7 @@ +# update version number here and if necessary +# in version.h and in contrib/*/pkixssh.spec + +m4_define([SSH_PACKAGE], [PKIX-SSH]) +m4_define([SSH_VERSION], [14.2.1]) +m4_define([SSH_BUGREPORT], [ssh_x509@roumenpetrov.info]) +m4_define([SSH_URL], [https://roumenpetrov.info/secsh]) diff -ruN openssh-9.4p1/version.sh openssh-9.4p1+x509-14.2.1/version.sh --- openssh-9.4p1/version.sh 1970-01-01 02:00:00.000000000 +0200 +++ openssh-9.4p1+x509-14.2.1/version.sh 2023-08-20 10:07:00.000000000 +0300 @@ -0,0 +1,28 @@ +#! /bin/sh + + +VERSION_PACKAGE=$1 +if test -z "$VERSION_PACKAGE" ; then + echo "usage: $0 [VERSION] " >&1 + exit 1 +fi + +upd_file() { + if cmp $1.tmp $1 > /dev/null; then + rm -f $1.tmp + else + mv -v $1.tmp $1 + fi +} + + +F=version.m4 +sed \ + -e "s|SSH_VERSION\],.*|SSH_VERSION], [$VERSION_PACKAGE])|g" \ + $F > $F.tmp +upd_file $F + +for F in contrib/*/pkixssh.spec ; do + sed -e "s|^Version:.*|Version: $VERSION_PACKAGE|g" $F > $F.tmp + upd_file $F +done diff -ruN openssh-9.4p1/x509_by_ldap.c openssh-9.4p1+x509-14.2.1/x509_by_ldap.c --- openssh-9.4p1/x509_by_ldap.c 1970-01-01 02:00:00.000000000 +0200 +++ openssh-9.4p1+x509-14.2.1/x509_by_ldap.c 2023-08-20 10:07:01.000000000 +0300 @@ -0,0 +1,513 @@ +/* + * Copyright (c) 2004-2021 Roumen Petrov. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "x509_by_ldap.h" +#include "ssh_ldap.h" + +#ifndef USE_OPENSSL_STORE2 +/* custom X.509 look-up */ + +#include "x509store.h" +#include + +#include + + +/* ================================================================== */ +/* backport OpenSSL 1.1 functions */ +#ifndef HAVE_X509_STORE_GET0_OBJECTS +static inline STACK_OF(X509_OBJECT)* +X509_STORE_get0_objects(X509_STORE *store) { + return store->objs; +} +#endif /*ndef HAVE_X509_STORE_GET0_OBJECTS*/ + + +#ifndef HAVE_X509_STORE_LOCK +static inline int +X509_STORE_lock(X509_STORE *s) { + UNUSED(s); +#ifdef CRYPTO_LOCK_X509_STORE + CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE); +#endif + return 1; +} + +static inline int +X509_STORE_unlock(X509_STORE *s) { + UNUSED(s); +#ifdef CRYPTO_LOCK_X509_STORE + CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE); +#endif + return 1; +} +#endif /*def HAVE_X509_STORE_LOCK*/ + + +/* ================================================================== */ +/* ERRORS */ + +/* Function codes. */ +#define X509byLDAP_F_LOOKUPCRTL 100 +#define X509byLDAP_F_GET_BY_SUBJECT 104 + +/* Reason codes. */ +#define X509byLDAP_R_INVALID_CRTLCMD 100 +#define X509byLDAP_R_WRONG_LOOKUP_TYPE 107 +#define X509byLDAP_R_UNABLE_TO_GET_FILTER 108 +#define X509byLDAP_R_UNABLE_TO_BIND 109 +#define X509byLDAP_R_SEARCH_FAIL 110 + +#ifndef OPENSSL_NO_ERR + +static ERR_STRING_DATA X509byLDAP_str_functs[] = { + { ERR_PACK(0, X509byLDAP_F_LOOKUPCRTL, 0) , "LOOKUPCRTL" }, + { ERR_PACK(0, X509byLDAP_F_GET_BY_SUBJECT, 0) , "GET_BY_SUBJECT" }, + { 0, NULL } +}; + + +static ERR_STRING_DATA X509byLDAP_str_reasons[] = { + { ERR_PACK(0, 0, X509byLDAP_R_INVALID_CRTLCMD) , "invalid control command" }, + { ERR_PACK(0, 0, X509byLDAP_R_WRONG_LOOKUP_TYPE) , "wrong lookup type" }, + { ERR_PACK(0, 0, X509byLDAP_R_UNABLE_TO_GET_FILTER) , "unable to get ldap filter" }, + { ERR_PACK(0, 0, X509byLDAP_R_UNABLE_TO_BIND) , "unable to bind to ldap server" }, + { ERR_PACK(0, 0, X509byLDAP_R_SEARCH_FAIL) , "search failure" }, + { 0, NULL } +}; + +static ERR_STRING_DATA X509byLDAP_lib_name[] = { + { 0, "X509byLDAP" }, + { 0, NULL } +}; + +#endif /*ndef OPENSSL_NO_ERR*/ + + +static int ERR_LIB_X509byLDAP = 0; + +static inline void +X509byLDAP_PUT_error(int function, int reason, const char *file, int line, const char *funcname) { + if (ERR_LIB_X509byLDAP == 0) + ERR_LIB_X509byLDAP = ERR_get_next_error_library(); + +#ifdef OPENSSL_NO_FILENAMES /* OpenSSL 1.1+ */ + file = NULL; + line = 0; +#endif +#ifdef ERR_raise_data + UNUSED(function); + ERR_new(); + ERR_set_debug(file, line, funcname); + ERR_set_error(ERR_LIB_X509byLDAP, reason, NULL); +#else +# ifdef OPENSSL_NO_ERR + /* If ERR_PUT_error macro ignores file and line */ + UNUSED(file); + UNUSED(line); +# endif + UNUSED(funcname); + ERR_PUT_error(ERR_LIB_X509byLDAP, function, reason, file, line); +#endif /*ndef ERR_raise_data*/ +} + +#define X509byLDAPerr(f,r) X509byLDAP_PUT_error((f),(r),__FILE__,__LINE__, __func__) + + +extern void ERR_load_X509byLDAP_strings(void); +void +ERR_load_X509byLDAP_strings(void) { +#ifndef OPENSSL_NO_ERR +{ static int loaded = 0; + if (loaded) return; + loaded = 1; +} + if (ERR_LIB_X509byLDAP == 0) + ERR_LIB_X509byLDAP = ERR_get_next_error_library(); + + ERR_load_strings(ERR_LIB_X509byLDAP, X509byLDAP_str_functs); + ERR_load_strings(ERR_LIB_X509byLDAP, X509byLDAP_str_reasons); + + X509byLDAP_lib_name[0].error = ERR_PACK(ERR_LIB_X509byLDAP, 0, 0); + ERR_load_strings(0, X509byLDAP_lib_name); +#endif /*ndef OPENSSL_NO_ERR*/ +} + + +/* ================================================================== */ +/* LOOKUP by LDAP */ + +static int ldaplookup_ctrl(X509_LOOKUP *ctx, int cmd, const char *argp, long argl, char **ret); +static int ldaplookup_new(X509_LOOKUP *ctx); +static void ldaplookup_free(X509_LOOKUP *ctx); +static int ldaplookup_init(X509_LOOKUP *ctx); +static int ldaplookup_shutdown(X509_LOOKUP *ctx); +static int ldaplookup_by_subject(X509_LOOKUP *ctx, int type, X509_NAME *name, X509_OBJECT *ret); + + +typedef struct lookup_item_s lookup_item; + +struct lookup_item_s { + ldaphost *lh; + lookup_item *next; +}; + +static inline void +lookup_item_free(lookup_item *p) { + if (p == NULL) return; + + ldaphost_free(p->lh); + OPENSSL_free(p); +} + +static inline lookup_item* +lookup_item_new(const char *url) { + lookup_item *ret; + + ret = OPENSSL_malloc(sizeof(lookup_item)); + if (ret == NULL) return NULL; + + ret->lh = ldaphost_new(url); + if (ret->lh == NULL) { + OPENSSL_free(ret); + return NULL; + } + + ret->next = NULL; + return ret; +} + + +X509_LOOKUP_METHOD x509_ldap_lookup = { + "Load certs and crls from LDAP server", + ldaplookup_new, /* new */ + ldaplookup_free, /* free */ + ldaplookup_init, /* init */ + ldaplookup_shutdown, /* shutdown */ + ldaplookup_ctrl, /* ctrl */ + ldaplookup_by_subject, /* get_by_subject */ + NULL, /* get_by_issuer_serial */ + NULL, /* get_by_fingerprint */ + NULL, /* get_by_alias */ +}; + + +X509_LOOKUP_METHOD* +X509_LOOKUP_ldap(void) { + return &x509_ldap_lookup; +} + + +static int +ldaplookup_new(X509_LOOKUP *ctx) { +TRACE_BY_LDAP(__func__, "ctx=%p", ctx); + if (ctx == NULL) return 0; + + ctx->method_data = NULL; + return 1; +} + + +static void +ldaplookup_free(X509_LOOKUP *ctx) { + lookup_item *p; +TRACE_BY_LDAP(__func__, "ctx=%p", ctx); + + if (ctx == NULL) return; + + p = (lookup_item*)(void*) ctx->method_data; + while (p != NULL) { + lookup_item *q = p; + p = p->next; + lookup_item_free(q); + } +} + + +static int +ldaplookup_init(X509_LOOKUP *ctx) { +TRACE_BY_LDAP(__func__, "ctx=%p", ctx); + UNUSED(ctx); + return 1; +} + + +static int +ldaplookup_shutdown(X509_LOOKUP *ctx) { +TRACE_BY_LDAP(__func__, "ctx=%p", ctx); + UNUSED(ctx); + return 1; +} + + +static int/*bool*/ +ldaplookup_add_search(X509_LOOKUP *ctx, const char *url) { + lookup_item *p, *q; + + if (ctx == NULL) return 0; + if (url == NULL) return 0; + + q = lookup_item_new(url); + if (q == NULL) return 0; + + p = (lookup_item*)(void*) ctx->method_data; + if (p == NULL) { + ctx->method_data = (void*) q; + return 1; + } + + for(; p->next != NULL; p = p->next) { + /*find list end*/ + } + p->next = q; + + return 1; +} + + +static int +ldaplookup_ctrl(X509_LOOKUP *ctx, int cmd, const char *argc, long argl, char **retp) { + int ret = 0; + + UNUSED(argl); + UNUSED(retp); +TRACE_BY_LDAP(__func__, "ctx=%p, cmd: %d, argc: '%s'", ctx, cmd, argc); + switch (cmd) { + case X509_L_LDAP_HOST: + ret = ldaplookup_add_search(ctx, argc); + break; + default: + X509byLDAPerr(X509byLDAP_F_LOOKUPCRTL, X509byLDAP_R_INVALID_CRTLCMD); + break; + } + return ret; +} + + +/* + * We will put into store X509 object from passed data in buffer only + * when object name match passed. To compare both names we use our + * method "ssh_X509_NAME_cmp"(it is more general). + */ +static int/*bool*/ +ldaplookup_data2store( + int type, + X509_NAME* name, + void* buf, + int len, + X509_STORE* store +) { + int ok = 0; + BIO *mbio; + + if (name == NULL) return 0; + if (buf == NULL) return 0; + if (len <= 0) return 0; + if (store == NULL) return 0; + + mbio = BIO_new_mem_buf(buf, len); + if (mbio == NULL) return 0; + + switch (type) { + case X509_LU_X509: { + X509 *x509 = d2i_X509_bio(mbio, NULL); + if(x509 == NULL) goto exit; + + /*This is correct since lookup method is by subject*/ + if (ssh_X509_NAME_cmp(name, X509_get_subject_name(x509)) != 0) goto exit; + + ok = X509_STORE_add_cert(store, x509); + /* X509_STORE_add...() increase "object" reference, + * so here object must be released unconditionally. + */ + X509_free(x509); + } break; + case X509_LU_CRL: { + X509_CRL *crl = d2i_X509_CRL_bio(mbio, NULL); + if(crl == NULL) goto exit; + + if (ssh_X509_NAME_cmp(name, X509_CRL_get_issuer(crl)) != 0) goto exit; + + ok = X509_STORE_add_crl(store, crl); + X509_CRL_free(crl); + } break; + } + +exit: + BIO_free_all(mbio); +TRACE_BY_LDAP(__func__, "ok: %d", ok); + return ok; +} + + +/* + * Clasic(direct) search "by subject" + */ +static int +ldaplookup_by_subject( + X509_LOOKUP *ctx, + int type, + X509_NAME *name, + X509_OBJECT *ret +) { + int count = 0; + lookup_item *p; + const char *attrs[2]; + static const char *ATTR_CACERT = "cACertificate"; + static const char *ATTR_CACRL = "certificateRevocationList"; + char *filter = NULL; + +TRACE_BY_LDAP(__func__, "ctx=%p, type: %d", ctx, type); + if (ctx == NULL) return 0; + if (name == NULL) return 0; + + p = (lookup_item*)(void*) ctx->method_data; + if (p == NULL) return 0; + + switch(type) { + case X509_LU_X509: { + attrs[0] = ATTR_CACERT; + } break; + case X509_LU_CRL: { + attrs[0] = ATTR_CACRL; + } break; + default: { + X509byLDAPerr(X509byLDAP_F_GET_BY_SUBJECT, X509byLDAP_R_WRONG_LOOKUP_TYPE); + goto done; + } + } + attrs[1] = NULL; + + filter = X509_NAME_ldapfilter(name, attrs[0]); + if (filter == NULL) { + X509byLDAPerr(X509byLDAP_F_GET_BY_SUBJECT, X509byLDAP_R_UNABLE_TO_GET_FILTER); + goto done; + } +TRACE_BY_LDAP(__func__, "filter: '%s'", filter); + + for (; p != NULL; p = p->next) { + ldaphost *lh = p->lh; + LDAPMessage *res = NULL; + int result; + +#ifdef TRACE_BY_LDAP_ENABLED +{ +int version = -1; + +ldap_get_option(lh->ld, LDAP_OPT_PROTOCOL_VERSION, &version); +TRACE_BY_LDAP(__func__, "bind to '%s://%s:%d' using protocol v%d" +, lh->ldapurl->lud_scheme, lh->ldapurl->lud_host, lh->ldapurl->lud_port +, version +); +} +#endif /*def TRACE_BY_LDAP_ENABLED*/ + + result = ssh_ldap_bind_s(lh->ld); + if (result != LDAP_SUCCESS) { + X509byLDAPerr(X509byLDAP_F_GET_BY_SUBJECT, X509byLDAP_R_UNABLE_TO_BIND); + { + char buf[1024]; + snprintf(buf, sizeof(buf), + " url=\"%s://%s:%d\"" + " ldaperror=0x%x(%.256s)" + , lh->ldapurl->lud_scheme, lh->ldapurl->lud_host, lh->ldapurl->lud_port + , result, ldap_err2string(result) + ); + ERR_add_error_data(1, buf); + } + continue; + } + + result = ssh_ldap_search_s(lh->ld, lh->ldapurl->lud_dn, + LDAP_SCOPE_SUBTREE, filter, (char**)attrs, 0, &res); + if (result != LDAP_SUCCESS) { + X509byLDAPerr(X509byLDAP_F_GET_BY_SUBJECT, X509byLDAP_R_SEARCH_FAIL); + ldap_msgfree(res); + continue; + } + { X509_STORE *store = ctx->store_ctx; + ldapsearch_result *it = ldapsearch_iterator(lh->ld, res); + + while (ldapsearch_advance(it)) { + { const char *q; + + switch (type) { + case X509_LU_X509: q = ATTR_CACERT; break; + case X509_LU_CRL : q = ATTR_CACRL ; break; + default: /* warnings */ + continue; + } + if (strncmp(it->attr, q, strlen(q)) != 0) + continue; + } + + { struct berval *q = *it->p; + count += ldaplookup_data2store(type, name, + q->bv_val, q->bv_len, store) + ? 1 : 0; + } + } + + OPENSSL_free(it); + } + + ldap_msgfree(res); + + /* NOTE: do not call ldap_unbind... here! + * Function ldaphost_free() unbind LDAP structure. + */ + } + +TRACE_BY_LDAP(__func__, "count: %d", count); + if (count > 0) { + X509_STORE *store = ctx->store_ctx; + X509_OBJECT *tmp; + + X509_STORE_lock(store); + { STACK_OF(X509_OBJECT) *objs; + objs = X509_STORE_get0_objects(store); + tmp = X509_OBJECT_retrieve_by_subject(objs, type, name); + } + X509_STORE_unlock(store); +TRACE_BY_LDAP(__func__, "tmp=%p", (void*)tmp); + + if (tmp == NULL) { + count = 0; + goto done; + } + + ret->type = tmp->type; + memcpy(&ret->data, &tmp->data, sizeof(ret->data)); + } + +done: + OPENSSL_free(filter); + return count > 0; +} +#else /*ndef USE_OPENSSL_STORE2*/ + +/* use OpenSSL 3.0+ X.509 look-up "by_store" */ +typedef int x509_by_ldap_empty_translation_unit; + +#endif diff -ruN openssh-9.4p1/x509_by_ldap.h openssh-9.4p1+x509-14.2.1/x509_by_ldap.h --- openssh-9.4p1/x509_by_ldap.h 1970-01-01 02:00:00.000000000 +0200 +++ openssh-9.4p1+x509-14.2.1/x509_by_ldap.h 2023-08-20 10:07:00.000000000 +0300 @@ -0,0 +1,51 @@ +#ifndef X509_BY_LDAP_H +#define X509_BY_LDAP_H +/* + * Copyright (c) 2004-2021 Roumen Petrov. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "includes.h" +#ifndef LDAP_ENABLED +# include "error: LDAP is disabled" +#endif +#ifndef USE_X509_LOOKUP_STORE + +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +X509_LOOKUP_METHOD* X509_LOOKUP_ldap(void); + +#define X509_L_LDAP_HOST 1 +#define X509_LOOKUP_add_ldap(x,value) \ + X509_LOOKUP_ctrl((x),X509_L_LDAP_HOST,(value),(long)(0),NULL) + + +#ifdef __cplusplus +} +#endif +#endif /*ndef USE_X509_LOOKUP_STORE*/ +#endif /*ndef X509_BY_LDAP_H*/ diff -ruN openssh-9.4p1/x509_by_store.c openssh-9.4p1+x509-14.2.1/x509_by_store.c --- openssh-9.4p1/x509_by_store.c 1970-01-01 02:00:00.000000000 +0200 +++ openssh-9.4p1+x509-14.2.1/x509_by_store.c 2023-08-20 10:07:01.000000000 +0300 @@ -0,0 +1,336 @@ +/* + * Copyright (c) 2016-2021 Roumen Petrov. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "x509store.h" + +#ifdef USE_X509_LOOKUP_MYSTORE + +#include +#include + + +typedef struct mystore_s mystore; +struct mystore_s { + char *url; + OSSL_STORE_CTX *ctx; +}; + +static void +mystore_free(mystore *p) { + if (p == NULL) return; + + OPENSSL_free(p->url); + if (p->ctx != NULL) { + OSSL_STORE_close(p->ctx); + p->ctx = NULL; + } + OPENSSL_free(p); +} + +static mystore* +mystore_new(const char *url) { + mystore *p; + + p = OPENSSL_malloc(sizeof(mystore)); + if (p == NULL) return NULL; + + p->url = OPENSSL_malloc(strlen(url) + 1); + if (p->url == NULL) goto error; + strcpy(p->url, url); + + p->ctx = NULL; + + return p; + +error: + mystore_free(p); + return NULL; +} + + +typedef struct lookup_item_s lookup_item; +struct lookup_item_s { + mystore *db; + lookup_item *next; +}; + +static lookup_item* +lookup_item_new(const char *url) { + lookup_item *ret; + + ret = OPENSSL_malloc(sizeof(lookup_item)); + if (ret == NULL) return NULL; + + ret->db = mystore_new(url); + if (ret->db == NULL) { + OPENSSL_free(ret); + return NULL; + } + + ret->next = NULL; + return ret; +} + +static void +lookup_item_free(lookup_item *p) { + if (p == NULL) return; + + mystore_free(p->db); + OPENSSL_free(p); +} + + +static int mystorelookup_new(X509_LOOKUP *ctx); +static void mystorelookup_free(X509_LOOKUP *ctx); +static int mystorelookup_init(X509_LOOKUP *ctx); +static int mystorelookup_shutdown(X509_LOOKUP *ctx); +static int mystorelookup_ctrl(X509_LOOKUP *ctx, int cmd, const char *argp, long argl, char **ret); +static int mystorelookup_by_subject(X509_LOOKUP *ctx, int type, X509_NAME *name, X509_OBJECT *ret); + +X509_LOOKUP_METHOD* +X509_LOOKUP_mystore(void) { +static X509_LOOKUP_METHOD + x509_mystore_lookup = { + "Load certs and crls from Store", + mystorelookup_new, + mystorelookup_free, + mystorelookup_init, + mystorelookup_shutdown, + mystorelookup_ctrl, + mystorelookup_by_subject, + NULL/*get_by_issuer_serial*/, + NULL/*get_by_fingerprint*/, + NULL/*get_by_alias */ + }; + return &x509_mystore_lookup; +} + + +static int +mystorelookup_new(X509_LOOKUP *ctx) { + if (ctx == NULL) return 0; + + ctx->method_data = NULL; + return 1; +} + + +static void +mystorelookup_free(X509_LOOKUP *ctx) { + lookup_item *p; + + if (ctx == NULL) return; + + p = (lookup_item*)(void*) ctx->method_data; + while (p != NULL) { + lookup_item *q = p; + p = p->next; + lookup_item_free(q); + } +} + + +static int +mystorelookup_init(X509_LOOKUP *ctx) { + UNUSED(ctx); + return 1; +} + + +static int +mystorelookup_shutdown(X509_LOOKUP *ctx) { + UNUSED(ctx); + return 1; +} + + +static int/*bool*/ +mystorelookup_add_search(X509_LOOKUP *ctx, const char *uri) { + lookup_item *p, *q; + + if (ctx == NULL) return 0; + if (uri == NULL) return 0; + + q = lookup_item_new(uri); + if (q == NULL) return 0; + + p = (lookup_item*)(void*) ctx->method_data; + if (p == NULL) { + ctx->method_data = (void*) q; + return 1; + } + + for(; p->next != NULL; p = p->next) { + /*find list end*/ + } + p->next = q; + + return 1; +} +static int +mystorelookup_ctrl(X509_LOOKUP *ctx, int cmd, const char *argc, long argl, char **retp) { + int ret = 0; + + UNUSED(argl); + UNUSED(retp); + switch (cmd) { + case X509_L_MYSTORE_URI: + ret = mystorelookup_add_search(ctx, argc); + break; + default: + break; + } + return ret; +} + + +/* + * We will put into store X509 object from passed data in buffer only + * when object name match passed. To compare both names we use our + * method "ssh_X509_NAME_cmp"(it is more general). + */ +static int/*bool*/ +mystorelookup_data2store( + int type, X509_NAME *name, + OSSL_STORE_INFO *info, + X509_STORE *store +) { + int ok = 0; + + if (name == NULL) return 0; + if (info == NULL) return 0; + if (store == NULL) return 0; + + switch (type) { + case X509_LU_X509: { + X509 *x509 = OSSL_STORE_INFO_get0_CERT(info); + if(x509 == NULL) goto exit; + + /*This is correct since lookup method is by subject*/ + if (ssh_X509_NAME_cmp(name, X509_get_subject_name(x509)) != 0) goto exit; + + ok = X509_STORE_add_cert(store, x509); + } break; + case X509_LU_CRL: { + X509_CRL *crl = OSSL_STORE_INFO_get0_CRL(info); + if(crl == NULL) goto exit; + + if (ssh_X509_NAME_cmp(name, X509_CRL_get_issuer(crl)) != 0) goto exit; + + ok = X509_STORE_add_crl(store, crl); + } break; + default: + return 0; + } +exit: + return ok; +} + + +/* + * Search "by subject" based on "Store2 API" + */ +static int +mystorelookup_by_subject( + X509_LOOKUP *ctx, + int type, + X509_NAME *name, + X509_OBJECT *ret +) { + int count = 0; + lookup_item *p; + + if (ctx == NULL) return 0; + if (name == NULL) return 0; + + p = (lookup_item*)(void*) ctx->method_data; + if (p == NULL) return 0; + + for (; p != NULL; p = p->next) { + mystore *ls = p->db; + X509_STORE *store = ctx->store_ctx; + OSSL_STORE_SEARCH *search; + + if (ls->ctx == NULL) + ls->ctx = OSSL_STORE_open(ls->url, NULL, NULL, NULL, NULL); + if (ls->ctx == NULL) continue; + + { int expected; + switch(type) { + case X509_LU_X509: expected = OSSL_STORE_INFO_CERT; break; + case X509_LU_CRL: expected = OSSL_STORE_INFO_CRL; break; + default: expected = -1; /*suppress warning*/ + } + (void)OSSL_STORE_expect(ls->ctx, expected); + } + + search = OSSL_STORE_SEARCH_by_name(name); + OSSL_STORE_find(ls->ctx, search); + + while (!OSSL_STORE_eof(ls->ctx)) { + OSSL_STORE_INFO *store_info; + + store_info = OSSL_STORE_load(ls->ctx); + if (store_info == NULL) break; + + count += mystorelookup_data2store(type, name, + store_info, store) + ? 1 : 0; + + OSSL_STORE_INFO_free(store_info); + } + + OSSL_STORE_SEARCH_free(search); + OSSL_STORE_close(ls->ctx); + ls->ctx = NULL; + } + + if (count > 0) { + X509_STORE *store = ctx->store_ctx; + X509_OBJECT *tmp; + + X509_STORE_lock(store); + { STACK_OF(X509_OBJECT) *objs; + objs = X509_STORE_get0_objects(store); + tmp = X509_OBJECT_retrieve_by_subject(objs, type, name); + } + X509_STORE_unlock(store); + + if (tmp == NULL) { + count = 0; + goto done; + } + + ret->type = tmp->type; + memcpy(&ret->data, &tmp->data, sizeof(ret->data)); + } + +done: + return count > 0; +} +#else /*def USE_X509_LOOKUP_MYSTORE */ + +typedef int x509_by_sock_empty_translation_unit; + +#endif diff -ruN openssh-9.4p1/x509_nm_cmp.c openssh-9.4p1+x509-14.2.1/x509_nm_cmp.c --- openssh-9.4p1/x509_nm_cmp.c 1970-01-01 02:00:00.000000000 +0200 +++ openssh-9.4p1+x509-14.2.1/x509_nm_cmp.c 2023-08-20 10:07:01.000000000 +0300 @@ -0,0 +1,576 @@ +/* + * Copyright (c) 2005-2018 Roumen Petrov. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* initial code is moved from ssh-x509.c */ +#include "includes.h" + +#include +#include + +#include "x509store.h" +#include "log.h" +#include "xmalloc.h" + +/* NOTE: OpenSSL ASN1_STRING methods surprisingly require non-const + * ASN1_STRING arguments! With replace from macros to methods we + * also change our definitions to non-const ASN1_STRING. + */ + + +#if 1 +# define COMPARE_X509_NAME_ENTRY_OBJECT +#endif + +#ifdef COMPARE_X509_NAME_ENTRY_OBJECT +static int +ssh_ASN1_OBJECT_cmp(ASN1_OBJECT *a, ASN1_OBJECT *b) { + int a_length; + int b_length; + int ret; + + a_length = i2d_ASN1_OBJECT(a, NULL); + b_length = i2d_ASN1_OBJECT(b, NULL); + +{ + unsigned char *a_data = malloc(a_length); + unsigned char *b_data = malloc(b_length); + int lmin = MIN(a_length, b_length); + + if (a_data == NULL) return(1); + if (b_data == NULL) return(-1); + +{ unsigned char *p = a_data; + (void)i2d_ASN1_OBJECT(a, &p); +} +{ unsigned char *p = b_data; + (void)i2d_ASN1_OBJECT(a, &p); +} + + ret = memcmp(a_data, b_data, lmin); + + free(a_data); + free(b_data); +} + + return((ret == 0) + ? (b_length - a_length) + : ret); +} +#endif /*def COMPARE_X509_NAME_ENTRY_OBJECT*/ + + +/* NOTE: used only for encoded as IA5String [PKCS9] emailAddress, + * i.e. irrelevant to application locale. + */ +static inline int +ssh_ASN1_STRING_casecmp(ASN1_STRING *a, ASN1_STRING *b) { + const u_char *sa, *sb; + int la, lb; + + ssh_ASN1_STRING_get0_data(a, &sa, &la); + ssh_ASN1_STRING_get0_data(b, &sb, &lb); + + return((strncasecmp(sa, sb, MIN(la, lb)) != 0) ? (lb - la) : 0); +} + + +/* - from RFC3280 (obsoletes: 2459) + * (d) attribute values in PrintableString are compared after + * removing leading and trailing white space and converting internal + * substrings of one or more consecutive white space characters to a + * single space. + * - from RFC5280 (obsoletes: 3280, 4325, 4630) + * Before comparing names using the caseIgnoreMatch matching rule, + * conforming implementations MUST perform the six-step string + * preparation algorithm described in [RFC4518] for each attribute of + * type DirectoryString, with the following clarifications: + * * In step 2, Map, the mapping shall include case folding as + * specified in Appendix B.2 of [RFC3454]. + * * In step 6, Insignificant Character Removal, perform white space + * compression as specified in Section 2.6.1, Insignificant Space + * Handling, of [RFC4518]. + * NOTE: In "Section 2.6.1, Insignificant Space Handling, of RFC4518" + * space is defined to be the "SPACE (U+0020) code point followed by + * no combining marks". + */ +static int +ssh_printable_casecmp(const u_char *pa, int la, const u_char *pb, int lb) +{ +/* NOTE: This method is used only if one of compared attributes is + * PrintableString. By definition string type PrintableString + * supports very basic Latin letters: [a-zA-Z =()+,-./:?] + * (for instance see RFC5280). + * This mean that application locale is practically irrelevant to + * case insensitive compare in this method. + */ + /* skip leading spaces */ + for (; la > 0 && isspace((int)*pa); la--, pa++) + /*nop*/; + for (; lb > 0 && isspace((int)*pb); lb--, pb++) + /*nop*/; + + /* skip trailing spaces */ + { + const u_char *p; + for (p = pa + la - 1; la > 0 && isspace((int)*p); la--, p--); + for (p = pb + lb - 1; lb > 0 && isspace((int)*p); lb--, p--); + } + + while (la > 0 && lb > 0) + { + int chA = tolower((int)*pa); + int chB = tolower((int)*pb); + + if (chA != chB) + return(chB - chA); + + pa++; pb++; + la--; lb--; + if (isspace(chA)) { + /* skip inner spaces */ + for (; la > 0 && isspace((int)*pa); la--, pa++); + for (; lb > 0 && isspace((int)*pb); lb--, pb++); + } + } + return(lb - la); +} + + +static int +ssh_ASN1_STRING_to_UTF8(unsigned char **out, ASN1_STRING *in) { +/* + * Note before OpenSSL versions 0.9.7e method ASN1_STRING_to_UTF8 + * fail when ASN1_STRING is utf8String ! + */ + int tag; + const u_char *s; + int l; + + if (!in) return(-1); + + tag = ASN1_STRING_type(in); + if (tag != V_ASN1_UTF8STRING) { + return(ASN1_STRING_to_UTF8(out, in)); + } + + ssh_ASN1_STRING_get0_data(in, &s, &l); + if (out) { + u_char *p; + + if (*out) { + error_f("*out is not NULL"); + return(-1); + } + /* we MUST allocate memory with OPENSSL method! */ + p = OPENSSL_malloc(l + 1); + if (p == NULL) { + fatal_f("out of memory (allocating %d bytes)", (l + 1)); + } + memcpy(p, s, l); + p[l] = 0; + *out = p; + } + return(l); +} + + +static int +ssh_ASN1_PRINTABLESTRING_cmp(ASN1_STRING *a, ASN1_STRING *b) { + int n = -1; + int tagA, tagB; + int la, lb; + const u_char *pa, *pb; + u_char *ua = NULL, *ub = NULL; + + tagA = ASN1_STRING_type(a); + tagB = ASN1_STRING_type(b); + if (tagA != V_ASN1_PRINTABLESTRING) { + debug3_f("a->type=%d(%.30s) is not PrintableString", tagA, ASN1_tag2str(tagA)); + /* just in case - see caling methods */ + if (tagB != V_ASN1_PRINTABLESTRING) { + error_f("b is not PrintableString too"); + return(-1); + } + } + if (tagB != V_ASN1_PRINTABLESTRING) { + debug3_f("b->type=%d(%.30s) is not PrintableString", tagB, ASN1_tag2str(tagB)); + /* just in case - see caling methods */ + if (tagA != V_ASN1_PRINTABLESTRING) { + error_f("a is not PrintableString too"); + return(1); + } + } + + if (tagA == tagB) { + /*both are PrintableString*/ + ssh_ASN1_STRING_get0_data(a, &pa, &la); + ssh_ASN1_STRING_get0_data(b, &pb, &lb); + } else { + /*convert strings to utf8*/ + la = ssh_ASN1_STRING_to_UTF8(&ua, a); + if (la <= 0) { + /*first string is lower in case of error or zero length*/ + n = -1; + goto done; + } + lb = ssh_ASN1_STRING_to_UTF8(&ub, b); + if (lb <= 0) { + /*second string is greater in case of error or zero length*/ + n = 1; + goto done; + } + pa = ua; + pb = ub; + } + + n = ssh_printable_casecmp(pa, la, pb, lb); + +done: + if(ua) OPENSSL_free(ua); + if(ub) OPENSSL_free(ub); +#ifdef SSHX509TEST_DBGCMP +fprintf(stderr, "%s: return %d\n", __func__, n); +#endif + return(n); +} + + +/* + * ===================================================================== + * from RFC3280 and oldest 2459: + * DirectoryString ::= CHOICE { + * teletexString TeletexString (SIZE (1..MAX)), + * printableString PrintableString (SIZE (1..MAX)), + * universalString UniversalString (SIZE (1..MAX)), + * utf8String UTF8String (SIZE (1..MAX)), + * bmpString BMPString (SIZE (1..MAX)) } + *..... + * The DirectoryString type is defined as a choice of PrintableString, + * TeletexString, BMPString, UTF8String, and UniversalString. The + * UTF8String encoding is the preferred encoding, and all certificates + * issued after December 31, 2003 MUST use the UTF8String encoding of + * DirectoryString (except as noted below). Until that date, conforming + * CAs MUST choose from the following options when creating a + * distinguished name, including their own: + * (a) if the character set is sufficient, the string MAY be + * represented as a PrintableString; + * (b) failing (a), if the BMPString character set is sufficient the + * string MAY be represented as a BMPString; and + * (c) failing (a) and (b), the string MUST be represented as a + * UTF8String. If (a) or (b) is satisfied, the CA MAY still choose + * to represent the string as a UTF8String. + *..... + * later in RFCs: + * (a) attribute values encoded in different types (e.g., + * PrintableString and BMPString) may be assumed to represent + * different strings; + * (b) attribute values in types other than PrintableString are case + * sensitive (this permits matching of attribute values as binary + * objects); + * (c) attribute values in PrintableString are not case sensitive + * (e.g., "Marianne Swanson" is the same as "MARIANNE SWANSON"); and + * (d) attribute values in PrintableString are compared after + * removing leading and trailing white space and converting internal + * substrings of one or more consecutive white space characters to a + * single space. + * ===================================================================== + * + * PKIX-SSH implementation: + * - assume that all DirectoryStrings represent same strings regardless + * of type. When strings are from different types they will be converted + * to utf8 before comparison. + * - when one of the strings is PrintableString they will be compared + * with method that ignore cases and spaces and convert to utf8 + * if necessary. + * + * Note calling method should ensure that both strings are + * DirectoryString !!! + */ +static int +ssh_ASN1_DIRECTORYSTRING_cmp(ASN1_STRING *a, ASN1_STRING *b) { +/* NOTE: + * - RFC3280 required only binary comparison of attribute values encoded in + * UTF8String. + * - RFC5280 conforming implementations for DirectoryString type MUST support + * name comparisons using caseIgnoreMatch - see Appendix B.2 of RFC3454. + */ + int n = -1; + int tagA, tagB; + int la, lb; + const u_char *pa, *pb; + u_char *ua = NULL, *ub = NULL; + + tagA = ASN1_STRING_type(a); + tagB = ASN1_STRING_type(b); + + /* just in case of PrintableString - see calling method ;-) */ + if ((tagA == V_ASN1_PRINTABLESTRING) || + (tagB == V_ASN1_PRINTABLESTRING) ) { + /* + * one is PrintableString and we will compare + * according rules for PrintableString. + */ + return(ssh_ASN1_PRINTABLESTRING_cmp(a, b)); + } +/*....*/ + /* TODO always convert to utf8 for RFC5280 conformance */ + if (tagA == tagB) { + ssh_ASN1_STRING_get0_data(a, &pa, &la); + ssh_ASN1_STRING_get0_data(b, &pb, &lb); + } else { + /*convert both string to utf8*/ + la = ssh_ASN1_STRING_to_UTF8(&ua, a); + if (la <= 0) { + /*first string is lower in case of error or zero length*/ + n = -1; + goto done; + } + lb = ssh_ASN1_STRING_to_UTF8(&ub, b); + if (lb <= 0) { + /*second string is greater in case of error or zero length*/ + debug_f("lb=%d", lb); + n = 1; + goto done; + } +#ifdef SSHX509TEST_DBGCMP +fprintf(stderr, "%s: ua='%s'\n", __func__, ua); +fprintf(stderr, "%s: ub='%s'\n", __func__, ub); +#endif + pa = (const char *)ua; + pb = (const char *)ub; + } + + /* TODO RFC5280 conforming, requires internal or external + * source that perform UNICODE normalization according + * rules from appendix B.2 of RFC3454. + */ + n = memcmp(pa, pb, (size_t)MIN(la, lb)); +#ifdef SSHX509TEST_DBGCMP +fprintf(stderr, "%s: n=%d, la=%d, lb=%d\n", __func__, n, la, lb); +#endif + if (n == 0) n = (lb - la); + +done: + if(ua) OPENSSL_free(ua); + if(ub) OPENSSL_free(ub); +#ifdef SSHX509TEST_DBGCMP +fprintf(stderr, "%: return %d\n", __func__, n); +#endif + return(n); +} + + +static int/*bool*/ +ssh_is_DirectoryString(ASN1_STRING* s) { + int tag = ASN1_STRING_type(s); + + switch(tag) { + case V_ASN1_T61STRING: /*==V_ASN1_TELETEXSTRING*/ + case V_ASN1_PRINTABLESTRING: + case V_ASN1_UNIVERSALSTRING: + case V_ASN1_UTF8STRING: + case V_ASN1_BMPSTRING: + return(1); + default: + return(0); + } +} + + +/* + * 1.) + * Since version 0.9.7.beta4 and 0.9.6h OpenSSL function X509_NAME_cmp + * is more restrictive but more correct (!). + * Problem is that some x509 implementation set X509_NAME entry + * incorrectly to "Printable String" :-[ . + * Work around: when one entry is "Printable String" method compare + * to corresponding entry as "Printable String". + * 2.) + * OpenSSL functions X509_NAME_cmp check nids order in X509_NAME. + * i.e. X509_NAME{"/C=XX/O=YY"} is not equal to X509_NAME{"/O=YY/C=XX"} + */ +int +ssh_X509_NAME_cmp(X509_NAME *_a, X509_NAME *_b) { + int k, n; + X509_NAME *b; + +#if 1 + /*XXX: to call fatal when _a or _b is NULL or to use next*/ + if (_a == NULL) { + return((_b == NULL) ? 0 : 1); + } else { + if (_b == NULL) return(-1); + } +#else + if (_a == NULL) { + fatal_f("first name is NULL"); + } + if (_b == NULL) { + fatal_f("second name is NULL"); + } +#endif + + k = X509_NAME_entry_count(_a); + n = X509_NAME_entry_count(_b); + + if (k != n) + return(n - k); + + b = X509_NAME_dup(_b); + n = 0; + for (--k; k >= 0; k--) { + X509_NAME_ENTRY *neA; + ASN1_STRING *nvA; + ASN1_OBJECT *noA; + int nid; + X509_NAME_ENTRY *neB; + ASN1_STRING *nvB; + #ifdef COMPARE_X509_NAME_ENTRY_OBJECT + ASN1_OBJECT *noB; + #endif + int loc; + + neA = X509_NAME_get_entry(_a, k); + nvA = X509_NAME_ENTRY_get_data(neA); + noA = X509_NAME_ENTRY_get_object(neA); + nid = OBJ_obj2nid(noA); + loc = X509_NAME_get_index_by_NID(b, nid, -1); + if (loc < 0) { + char *buf1, *buf2; + + buf1 = ssh_X509_NAME_oneline(_a); /*fatal on error*/ + buf2 = ssh_X509_NAME_oneline(_b); /*fatal on error*/ + debug3_f("insufficient entries with nid=%d(%.40s) in second name." + " na=%s, nb=%s", + nid, OBJ_nid2ln(nid), + buf1, buf2); + free(buf1); + free(buf2); + n = -1; + break; + } +trynextentry: + neB = X509_NAME_get_entry(b, loc); + nvB = X509_NAME_ENTRY_get_data(neB); +#ifdef SSHX509TEST_DBGCMP +{ + int l, tag; + + l = ASN1_STRING_length(nvA); + tag = ASN1_STRING_type (nvA); + fprintf(stderr, "nvA(%.40s:%d)='", ASN1_tag2str(tag), l); + ASN1_STRING_print_ex_fp(stderr, nvA, /*flags*/0); + fputs("'\n", stderr); + + l = ASN1_STRING_length(nvB); + tag = ASN1_STRING_type (nvB); + fprintf(stderr, "nvA(%.40s:%d)='", ASN1_tag2str(tag), l); + ASN1_STRING_print_ex_fp(stderr, nvB, /*flags*/0); + fputs("'\n", stderr); +} +#endif + + if (nid == NID_pkcs9_emailAddress) { + int tag; + + tag = ASN1_STRING_type(nvA); + if (tag != V_ASN1_IA5STRING) { + /* to be strict and return nonzero or ... ? XXX + n = -1; + break; + */ + error_f("incorrect type for emailAddress(a) %d(%.30s)", tag, ASN1_tag2str(tag)); + } + + tag = ASN1_STRING_type(nvB); + if (tag != V_ASN1_IA5STRING) { + /* to be strict and return nonzero or ... ? XXX + n = 1; + break; + */ + error_f("incorrect type for emailAddress(b) %d(%.30s)", tag, ASN1_tag2str(tag)); + } + + /* NOTE: [PKCS9] emailAddress attribute must be encoded as + * IA5String, which is limited to the set of ASCII characters. + * This mean that application locale is practically irrelevant + * to case insensitive compare below. + */ + n = ssh_ASN1_STRING_casecmp(nvA, nvB); + if (n == 0) goto entryisok; + + goto getnextentry; + } + if ((ASN1_STRING_type(nvA) == V_ASN1_PRINTABLESTRING) || + (ASN1_STRING_type(nvB) == V_ASN1_PRINTABLESTRING) ) { + n = ssh_ASN1_PRINTABLESTRING_cmp(nvA, nvB); + if (n == 0) goto entryisok; + + goto getnextentry; + } + if (ssh_is_DirectoryString(nvA) && + ssh_is_DirectoryString(nvB)) { + n = ssh_ASN1_DIRECTORYSTRING_cmp(nvA, nvB); + if (n == 0) goto entryisok; + + goto getnextentry; + } + + n = ASN1_STRING_length(nvA) - ASN1_STRING_length(nvB); + if (n != 0) goto getnextentry; + + n = ASN1_STRING_length(nvA); + n = memcmp(nvA->data, nvB->data, n); + if (n != 0) goto getnextentry; + +#ifdef COMPARE_X509_NAME_ENTRY_OBJECT +/* NAME_ENTRY object is field name. We could omit object compare + * as we peek from second name entry with same nid as current + */ + /* openssl check object too */ + noB = X509_NAME_ENTRY_get_object(neB); + n = ssh_ASN1_OBJECT_cmp(noA, noB); + if (n != 0) goto getnextentry; +#endif + +entryisok: + { + X509_NAME_ENTRY *ne = X509_NAME_delete_entry(b, loc); + X509_NAME_ENTRY_free(ne); + } + continue; +getnextentry: + loc = X509_NAME_get_index_by_NID(b, nid, loc); + if (loc < 0) { + break; + } + goto trynextentry; + } + + X509_NAME_free(b); +#ifdef SSHX509TEST_DBGCMP +fprintf(stderr, "%s: return %d\n", __func__, n); +#endif + return(n); +} diff -ruN openssh-9.4p1/x509store.c openssh-9.4p1+x509-14.2.1/x509store.c --- openssh-9.4p1/x509store.c 1970-01-01 02:00:00.000000000 +0200 +++ openssh-9.4p1+x509-14.2.1/x509store.c 2023-08-20 10:07:01.000000000 +0300 @@ -0,0 +1,1451 @@ +/* + * Copyright (c) 2002-2022 Roumen Petrov. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "x509store.h" +#ifdef LDAP_ENABLED +# include "ssh_ldap.h" +#endif +#include +#include +#include + +#include + +#ifdef LDAP_ENABLED +# include "x509_by_ldap.h" +#endif +#include "log.h" +#include "xmalloc.h" +#include "pathnames.h" +#include "misc.h" + +#if 0 /* enable if check below is not suitable for you build environment */ +/* work-around if attribute X509_VERIFY_PARAM.check_time is not accessible */ +# define USE_X509_STORE_CTX_INDEX 1 +#endif +#ifndef USE_X509_STORE_CTX_INDEX +# if defined(HAVE_X509_STORE_CTX_GET0_PARAM) && !defined(HAVE_X509_VERIFY_PARAM_GET_TIME) +/* Note structure X509_VERIFY_PARAM is defined in OpenSSL 0.9.8+ together + * with function X509_STORE_CTX_get0_param() + */ +# if defined(HAVE_OPENSSL_INIT_CRYPTO) +/* Temporary work-around for opaque structure X509_VERIFY_PARAM. + * In OpenSSL 1.1.0* branch X509_VERIFY_PARAM_get_time() is available since 1.1.0d. + * As result for versions from 1.1.0 to 1.1.0c we has to provide work-around. + * In LibreSSL 3.5 structure X509_VERIFY_PARAM is opaque but library + * fail to provide get_time() function! + */ +# define USE_X509_STORE_CTX_INDEX 1 +# else +/* Use wrapper function X509_VERIFY_PARAM_get_time() */ +# endif +# endif +#endif +#ifdef USE_X509_STORE_CTX_INDEX +/* do not define local get function if structure X509_VERIFY_PARAM is opaque */ +# define HAVE_X509_VERIFY_PARAM_GET_TIME +#endif +#ifndef HAVE_X509_STORE_CTX_GET0_PARAM +/* do not define local get function as X509_VERIFY_PARAM is not available */ +# define HAVE_X509_VERIFY_PARAM_GET_TIME +#endif + + +#ifndef HAVE_X509_STORE_SET_VERIFY_CB /* OpenSSL < 1.0.0 */ +static inline void +X509_STORE_set_verify_cb(X509_STORE *ctx, int (*verify_cb) (int, X509_STORE_CTX *)) { + ctx->verify_cb = verify_cb; +} +#endif /*ndef HAVE_X509_STORE_SET_VERIFY_CB*/ + + +SSH_X509Flags +ssh_x509flags = { + 0, /* is_server */ + -1, /* allowedcertpurpose */ + -1, /* key_allow_selfissued */ + -1, /* mandatory_crl */ + -1 /* validate_first */ +}; + + +static X509_STORE *x509store = NULL; +static X509_STORE *x509revoked = NULL; + +static int ssh_x509revoked_cb(int ok, X509_STORE_CTX *ctx); + + +#ifdef USE_X509_STORE_CTX_INDEX +static int ssh_X509_STORE_CTX_index = -1; + +struct ssh_X509_STORE_CTX_data_st { + time_t check_time; +}; + +typedef struct ssh_X509_STORE_CTX_data_st SSH_X509_STORE_CTX_DATA; + + +static inline SSH_X509_STORE_CTX_DATA* +SSH_X509_STORE_CTX_DATA_new(void) { + SSH_X509_STORE_CTX_DATA *p; + + p = malloc(sizeof(SSH_X509_STORE_CTX_DATA)); + if (p != NULL) { + p->check_time = 0; + } + return p; +} + +static inline void +SSH_X509_STORE_CTX_DATA_free(SSH_X509_STORE_CTX_DATA* p) { + free(p); +} +#endif /*def USE_X509_STORE_CTX_INDEX*/ + + +#ifndef HAVE_X509_CRL_GET0_LASTUPDATE /* OpenSSL < 1.1 */ +static inline const ASN1_TIME* +X509_CRL_get0_lastUpdate(const X509_CRL *crl) { + return X509_CRL_get_lastUpdate(crl); +} + +static inline const ASN1_TIME* +X509_CRL_get0_nextUpdate(const X509_CRL *crl) { + return X509_CRL_get_nextUpdate(crl); +} +#endif /* ndef HAVE_X509_CRL_GET0_LASTUPDATE OpenSSL < 1.1 */ + + +#ifndef HAVE_X509_OBJECT_NEW /* OpenSSL < 1.1 */ +/* backport specific OpenSSL X509_OBJECT functions */ +static inline X509_OBJECT* +X509_OBJECT_new(void) { + X509_OBJECT *xobj; + + xobj = OPENSSL_malloc(sizeof (X509_OBJECT)); + if (xobj != NULL) { + memset(xobj, '\0', sizeof(*xobj)); + xobj->type = X509_LU_FAIL; + } + return xobj; +} + +static inline void +X509_OBJECT_free(X509_OBJECT *xobj) { + if (xobj == NULL) return; + + X509_OBJECT_free_contents(xobj); + OPENSSL_free(xobj); +} +#endif /*ndef HAVE_X509_OBJECT_NEW*/ + +#ifndef HAVE_X509_STORE_CTX_GET_BY_SUBJECT /* OpenSSL < 1.1 */ +static inline int +X509_STORE_CTX_get_by_subject( + X509_STORE_CTX *vs, /*X509_LOOKUP_TYPE*/int type, + X509_NAME *name, X509_OBJECT *ret +) { + return X509_STORE_get_by_subject(vs, type, name, ret); +} +#endif /*ndef HAVE_X509_STORE_CTX_GET_BY_SUBJECT*/ + +#ifndef HAVE_X509_OBJECT_GET0_X509 /* OpenSSL < 1.1 */ +/* backport specific OpenSSL X509_OBJECT functions */ +static inline X509* +X509_OBJECT_get0_X509(const X509_OBJECT *xobj) { + if (xobj == NULL) return NULL; + if (xobj->type != X509_LU_X509) return NULL; + + return xobj->data.x509; +} + +static inline X509_CRL* +X509_OBJECT_get0_X509_CRL(const X509_OBJECT *xobj) { + if (xobj == NULL) return NULL; + if (xobj->type != X509_LU_CRL) return NULL; + + return xobj->data.crl; +} +#endif /*ndef HAVE_X509_OBJECT_GET0_X509*/ + +#ifndef HAVE_X509_VERIFY_PARAM_GET_TIME /* OpenSSL < 1.1.0d, actually < 1.1.0 */ +static inline time_t +X509_VERIFY_PARAM_get_time(const X509_VERIFY_PARAM *param) { + return param->check_time; +} +#endif /*ndef HAVE_X509_VERIFY_PARAM_GET_TIME*/ + +#ifndef HAVE_X509_GET_EXTENSION_FLAGS +static inline uint32_t +X509_get_extension_flags(X509 *x) { + X509_check_purpose(x, -1, -1); /* set flags */ + return x->ex_flags; +} +#endif /*ndef HAVE_X509_GET_EXTENSION_FLAGS*/ + + +static char * +ssh_ASN1_INTEGER_2_string(ASN1_INTEGER *_asni) { + BIO *bio; + int k; + char *p; + + if (_asni == NULL) { + error_f("_asni is NULL"); + return NULL; + } + + bio = BIO_new(BIO_s_mem()); + if (bio == NULL) { + fatal_f("out of memory"); + return NULL; /* ;-) */ + } + + i2a_ASN1_INTEGER(bio, _asni); + k = BIO_pending(bio); + p = xmalloc(k + 1); /*fatal on error*/ + k = BIO_read(bio, p, k); + p[k] = '\0'; + BIO_free_all(bio); + + return p; +} + + +#ifdef USE_OPENSSL_STORE2 +static void +load_ldap_engine(void) { +#ifdef USE_LDAP_STORE +{ static int load_ldap = 1; + if (load_ldap) { + load_ldap = 0; + ENGINE_load_ldap(); + } +} +#endif +} +#endif /*def USE_OPENSSL_STORE2*/ + + +#ifdef LDAP_ENABLED +static int ldap_version = -1; + +static int +parse_ldap_version(const char *ver) { + long n; + + if (ver == NULL) return -1; + +{ char *endptr = NULL; + n = strtol(ver, &endptr, 10); + if (*endptr != '\0') return -1; +} + if ((n < LDAP_VERSION_MIN) || (n > LDAP_VERSION_MAX)) return -1; + + return (int) n; +} + +static int/*bool*/ +set_ldap_version(const char *ver) { + if (ver != NULL) { + int n = parse_ldap_version(ver); + if (n < 0) return 0; + ldap_version = n; + } + + return 1; +} + +int +ssh_ldap_version() { + return ldap_version; +} +#endif /*def LDAP_ENABLED*/ + + +static int +ssh_x509store_lookup(X509_STORE *store, int type, X509_NAME *name, X509_OBJECT *xobj) { + X509_STORE_CTX *csc; + int ret = -1; + + csc = X509_STORE_CTX_new(); + if (csc == NULL) { + error_crypto("X509_STORE_CTX_new"); + return -1; + } + if (X509_STORE_CTX_init(csc, store, NULL, NULL) <= 0) { + /*memory allocation error*/ + error_f("cannot initialize x509store context"); + goto done; + } + + ret = X509_STORE_CTX_get_by_subject(csc, type, name, xobj); + +done: + X509_STORE_CTX_free(csc); + return ret; +} + + +X509* +ssh_x509store_get_cert_by_subject(X509_STORE *store, X509_NAME *name) { + X509 *ret = NULL; + +{ /* opaque use of X509_OBJECT */ + X509_OBJECT *xobj; + + xobj = X509_OBJECT_new(); + if (xobj == NULL) { + error_f("cannot allocate X509_OBJECT"); + return NULL; + } + + if (ssh_x509store_lookup(store, X509_LU_X509, name, xobj) > 0) + ret = X509_OBJECT_get0_X509(xobj); + + X509_OBJECT_free(xobj); +} + + return ret; +} + + +X509_CRL* +ssh_x509store_get_crl_by_subject(X509_STORE *store, X509_NAME *name) { + X509_CRL *ret = NULL; + +{ /* opaque use of X509_OBJECT */ + X509_OBJECT *xobj; + + xobj = X509_OBJECT_new(); + if (xobj == NULL) { + error_f("cannot allocate X509_OBJECT"); + return NULL; + } + + if (ssh_x509store_lookup(store, X509_LU_CRL, name, xobj) > 0) + ret = X509_OBJECT_get0_X509_CRL(xobj); + + X509_OBJECT_free(xobj); +} + + return ret; +} + + +static int +ssh_x509store_cb(int ok, X509_STORE_CTX *ctx) { + int ctx_error = X509_STORE_CTX_get_error(ctx); + X509 *ctx_cert = X509_STORE_CTX_get_current_cert(ctx); + int self_signed = 0; + + if ((!ok) && + (ctx_error == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT) + ) { + if (ssh_x509flags.key_allow_selfissued) { + ok = ssh_X509_is_selfissued(ctx_cert); + if (ok) + self_signed = 1; + } + } + if (!ok) { + char *buf; + buf = ssh_X509_NAME_oneline(X509_get_subject_name(ctx_cert)); /*fatal on error*/ + error_f("subject='%s', error %d at %d depth lookup:%.200s", + buf, + ctx_error, + X509_STORE_CTX_get_error_depth(ctx), + X509_verify_cert_error_string(ctx_error)); + free(buf); + } + if (ok && !self_signed) { + ok = ssh_x509revoked_cb(ok, ctx); + } + return ok; +} + + +typedef struct { + const char * const *synonyms; +} CertPurposes; + + +static const char * const __purpose_any[] = { + "any", "any purpose", "any_purpose", "anypurpose", NULL +}; + + +static const char * const __purpose_sslclient[] = { + "sslclient", "ssl client", "ssl_client", "client", NULL +}; + + +static const char * const __purpose_sslserver[] = { + "sslserver", "ssl server", "ssl_server", "server", NULL +}; + + +static CertPurposes +sslclient_purposes[] = { + { __purpose_sslclient }, + { __purpose_any }, + { NULL } +}; + + +static CertPurposes +sslserver_purposes [] = { + { __purpose_sslserver }, + { __purpose_any }, + { NULL } +}; + + +static const char* +get_cert_purpose(const char* _purpose_synonym, CertPurposes *_purposes) { + int i; + + for (i = 0; _purposes[i].synonyms; i++) { + const char *q = _purposes[i].synonyms[0]; + if (strcasecmp(_purpose_synonym, q) == 0) { + return q; + } else { + const char * const *p; + for (p = (_purposes[i].synonyms) + 1; *p; p++) { + if (strcasecmp(_purpose_synonym, *p) == 0 ) { + return q; + } + } + } + } + return NULL; +} + + +void +ssh_x509flags_initialize(SSH_X509Flags *flags, int is_server) { + flags->is_server = is_server; + flags->allowedcertpurpose = -1; + flags->key_allow_selfissued = -1; + flags->mandatory_crl = -1; + flags->validate_first = -1; +} + + +void +ssh_x509flags_defaults(SSH_X509Flags *flags) { + if (flags->allowedcertpurpose == -1) { + int is_server = flags->is_server; + const char* purpose_synonym = is_server ? __purpose_sslclient[0] : __purpose_sslserver[0]; + + flags->allowedcertpurpose = ssh_get_x509purpose_s(is_server, purpose_synonym); + } + if (flags->key_allow_selfissued == -1) { + flags->key_allow_selfissued = 0; + } + if (flags->mandatory_crl == -1) { + flags->mandatory_crl = 0; + } + if (flags->validate_first == -1) { + flags->validate_first = 0; + } +} + + +int +ssh_get_x509purpose_s(int _is_server, const char* _purpose_synonym) { + const char * sslpurpose; + + sslpurpose = get_cert_purpose(_purpose_synonym, + (_is_server ? sslclient_purposes : sslserver_purposes)); + if (sslpurpose != NULL) { + int purpose_index = X509_PURPOSE_get_by_sname((char*)sslpurpose); + if (purpose_index < 0) + fatal_f("%s X509_PURPOSE_get_by_sname fail for argument '%.30s(%.40s)'", + (_is_server ? "server" : "client"), + sslpurpose, _purpose_synonym); + return purpose_index; + } + return -1; +} + + +char* +format_x509_purpose(int purpose_index) { + X509_PURPOSE *xp; + + xp = X509_PURPOSE_get0(purpose_index); + if (xp == NULL) { + fatal_f("cannot get purpose from index"); + return "skip"; /* ;-) */ + } + return X509_PURPOSE_get0_sname(xp); +} + + +int/*bool*/ +ssh_X509_is_selfissued(X509 *_cert) { +#if 0 +/* If issuer distinguished name match certificate + * distinguished name it is self-issued. + * OpenSSL uses flag to indicate this but flag is changed + * between releases. + * a) Flag EXFLAG_SS is historic, i.e. used initially. + * b) Version 0.9.8i change it to EXFLAG_SI but for compatibility + * keep EXFLAG_SS defined with the same value. + * Note that "i" is patch release! + * c) OpenSSL release 1.0.2 breaks compatibility and + * now EXFLAG_SS means that SKID matches AKID, is self-signed. + * + * As result we will do compare instead to rely on OpenSSL flag. + */ +# define USE_EXFLAG_SI +# ifndef EXFLAG_SI +# define EXFLAG_SI EXFLAG_SS /*OpenSSL < 0.9.8i*/ +# endif +#endif +#ifdef USE_EXFLAG_SI + uint32_t flags = X509_get_extension_flags(_cert); + return (flags & EXFLAG_SI) != 0; +#else + X509_NAME *issuer, *subject; + + issuer = X509_get_issuer_name(_cert); + subject = X509_get_subject_name(_cert); + + if (get_log_level() >= SYSLOG_LEVEL_DEBUG3) { + char *buf; + + buf = ssh_X509_NAME_oneline(issuer); /*fatal on error*/ + debug3_f("issuer='%s'", buf); + free(buf); + + buf = ssh_X509_NAME_oneline(subject); /*fatal on error*/ + debug3_f("subject='%s'", buf); + free(buf); + } + + return ssh_X509_NAME_cmp(issuer, subject) == 0; +#endif +} + + +void +X509StoreOptions_init(X509StoreOptions *options) { + options->certificate_file = NULL; + options->certificate_path = NULL; + options->revocation_file = NULL; + options->revocation_path = NULL; +} + + +void +X509StoreOptions_cleanup(X509StoreOptions *options) { + free((char*)options->certificate_file); options->certificate_file = NULL; + free((char*)options->certificate_path); options->certificate_path = NULL; + free((char*)options->revocation_file); options->revocation_file = NULL; + free((char*)options->revocation_path); options->revocation_path = NULL; +} + + +void +X509StoreOptions_system_defaults(X509StoreOptions *options) { + if (options->certificate_file == NULL) + options->certificate_file = xstrdup(_PATH_CA_CERTIFICATE_FILE); + if (options->certificate_path == NULL) + options->certificate_path = xstrdup(_PATH_CA_CERTIFICATE_PATH); + if (options->revocation_file == NULL) + options->revocation_file = xstrdup(_PATH_CA_REVOCATION_FILE); + if (options->revocation_path == NULL) + options->revocation_path = xstrdup(_PATH_CA_REVOCATION_PATH); +#ifdef LDAP_ENABLED + /*nothing to do ;-)*/ +#endif +} + + +static void +tilde_expand_filename2(const char **_fn, const char* _default, uid_t uid) { + if (*_fn == NULL) { + *_fn = tilde_expand_filename(_default, uid); + } else { + const char *p = *_fn; + *_fn = tilde_expand_filename(p, uid); + free((void*)p); + } +} + + +void +X509StoreOptions_user_defaults(X509StoreOptions *options, uid_t uid) { + tilde_expand_filename2(&options->certificate_file, _PATH_USERCA_CERTIFICATE_FILE, uid); + tilde_expand_filename2(&options->certificate_path, _PATH_USERCA_CERTIFICATE_PATH, uid); + tilde_expand_filename2(&options->revocation_file , _PATH_USERCA_REVOCATION_FILE , uid); + tilde_expand_filename2(&options->revocation_path , _PATH_USERCA_REVOCATION_PATH , uid); +#ifdef LDAP_ENABLED + /*nothing to do ;-)*/ +#endif +} + + +static void +ssh_x509store_initcontext(void) { +#ifdef USE_X509_STORE_CTX_INDEX + if (ssh_X509_STORE_CTX_index < 0) + ssh_X509_STORE_CTX_index = X509_STORE_CTX_get_ex_new_index(0, NULL, NULL, NULL, NULL); +#endif + if (x509store == NULL) { + x509store = X509_STORE_new(); + if (x509store == NULL) { + fatal("cannot create x509store context"); + } + X509_STORE_set_verify_cb(x509store, ssh_x509store_cb); + } + if (x509revoked == NULL) { + x509revoked = X509_STORE_new(); + if (x509revoked == NULL) { + fatal("cannot create x509revoked context"); + } + } +} + + +void +ssh_x509store_cleanup(void) { + if (x509store != NULL) { + X509_STORE_free(x509store); + x509store = NULL; + } + if (x509revoked != NULL) { + X509_STORE_free(x509revoked); + x509revoked = NULL; + } +} + + +static int/*bool*/ +ssh_x509store_add_hash_dir(X509_STORE* store, const char *name, const char *path) { + int ret = 0; + X509_LOOKUP *lookup; + + if (path == NULL) return 0; + if (*path == '\0') return 0; + + lookup = X509_STORE_add_lookup(store, X509_LOOKUP_hash_dir()); + if (lookup == NULL) { + fatal_f("cannot add 'hash dir lookup' to '%s'", name); + return 0; /* ;-) */ + } + + if (X509_LOOKUP_add_dir(lookup, path, X509_FILETYPE_PEM)) { + debug2("'hash dir lookup' '%.400s' added to '%s'", path, name); + ret = 1; + } + + /* NOTE: After X509_LOOKUP_{add_dir|load_file} calls we must call + * ERR_clear_error() otherwise if first call of control function + * fail then second call fail too! + */ + ERR_clear_error(); + return ret; +} + +int/*bool*/ +ssh_x509store_addlocations(const X509StoreOptions *_locations) { + int flag; + + if (_locations == NULL) { + error_f("_locations is NULL"); + return 0; + } + if ((_locations->certificate_path == NULL) && + (_locations->certificate_file == NULL)) { + error_f("certificate path and file are NULLs"); + return 0; + } + if ((_locations->revocation_path == NULL) && + (_locations->revocation_file == NULL)) { + error_f("revocation path and file are NULLs"); + return 0; + } + ssh_x509store_initcontext(); + + flag = ssh_x509store_add_hash_dir(x509store, "X.509 store", _locations->certificate_path); + if (_locations->certificate_file != NULL) { + X509_LOOKUP *lookup = X509_STORE_add_lookup(x509store, X509_LOOKUP_file()); + if (lookup == NULL) { + fatal_f("cannot add file lookup"); + return 0; /* ;-) */ + } + if (X509_LOOKUP_load_file(lookup, _locations->certificate_file, X509_FILETYPE_PEM)) { + debug2("file '%.400s' added to x509 store", _locations->certificate_file); + flag = 1; + } + ERR_clear_error(); + } + /*at least one lookup should succeed*/ + if (flag == 0) return 0; + + flag = ssh_x509store_add_hash_dir(x509revoked, "X.509 revocation store", _locations->revocation_path); + if (_locations->revocation_file != NULL) { + X509_LOOKUP *lookup = X509_STORE_add_lookup(x509revoked, X509_LOOKUP_file()); + if (lookup == NULL) { + fatal_f("cannot add file revocation lookup"); + return 0; /* ;-) */ + } + if (X509_LOOKUP_load_file(lookup, _locations->revocation_file, X509_FILETYPE_PEM)) { + debug2("file '%.400s' added to x509 revocation store", _locations->revocation_file); + flag = 1; + } + ERR_clear_error(); + } + /*at least one revocation lookup should succeed*/ + if (flag == 0) return 0; + + return 1; +} + + +#ifdef LDAP_ENABLED +int/*bool*/ +ssh_x509store_addldapurl(const char *ldap_url, const char *ldap_ver) { + /* could be set only in client and daemon program */ + if (ldap_url != NULL) { + X509_LOOKUP_METHOD* lookup_method; + X509_LOOKUP *lookup; + +#ifdef USE_X509_LOOKUP_STORE + #define SSH_X509_LOOKUP_ADD X509_LOOKUP_add_store + lookup_method = X509_LOOKUP_store(); + load_ldap_engine(); +#elif defined(USE_X509_LOOKUP_MYSTORE) + #define SSH_X509_LOOKUP_ADD X509_LOOKUP_add_mystore + lookup_method = X509_LOOKUP_mystore(); + load_ldap_engine(); +#else + #define SSH_X509_LOOKUP_ADD X509_LOOKUP_add_ldap + lookup_method = X509_LOOKUP_ldap(); +#endif + + lookup = X509_STORE_add_lookup(x509store, lookup_method); + if (lookup == NULL) { + fatal_f("cannot add ldap lookup"); + return 0; /* ;-) */ + } + if (SSH_X509_LOOKUP_ADD(lookup, ldap_url)) { + debug2("ldap url '%.400s' added to x509 store", ldap_url); + } + /*ERR_clear_error();*/ + + + lookup = X509_STORE_add_lookup(x509revoked, lookup_method); + if (lookup == NULL) { + fatal_f("cannot add ldap lookup(revoked)"); + return 0; /* ;-) */ + } + if (SSH_X509_LOOKUP_ADD(lookup, ldap_url)) { + debug2("ldap url '%.400s' added to x509 store(revoked)", ldap_url); + } + /*ERR_clear_error();*/ + + /* NOTE: All LDAP-connections will use one and the same protocol version */ + if (!set_ldap_version(ldap_ver)) { + fatal_f("cannot set ldap version"); + return 0; /* ;-) */ + } + } +#undef SSH_X509_LOOKUP_ADD + return 1; +} +#endif /*def LDAP_ENABLED*/ + + +#ifdef USE_OPENSSL_STORE2 +int/*bool*/ +ssh_x509store_adduri(const char **store_uri, u_int num_store_uri) { + u_int k; + X509_LOOKUP_METHOD* lookup_method; + +#ifdef USE_X509_LOOKUP_STORE + #define SSH_X509_LOOKUP_ADD X509_LOOKUP_add_store + lookup_method = X509_LOOKUP_store(); +#else + #define SSH_X509_LOOKUP_ADD X509_LOOKUP_add_mystore + lookup_method = X509_LOOKUP_mystore(); +#endif + + debug2("number of store URI: %u", num_store_uri); + if (num_store_uri > 0) { + /* store uri may use ldap scheme */ + load_ldap_engine(); + } + + for (k = 0; k < num_store_uri; k++) { + const char *uri = store_uri[k]; + X509_LOOKUP *lookup; + + lookup = X509_STORE_add_lookup(x509store, lookup_method); + if (lookup == NULL) { + fatal_f("cannot add store lookup[%d]", k); + return 0; /* ;-) */ + } + if (SSH_X509_LOOKUP_ADD(lookup, uri)) + debug2("store URI '%.400s' added to x509 store", uri); + else + error("cannot add store URI '%.400s' to x509 store", uri); + /*ERR_clear_error();*/ + + lookup = X509_STORE_add_lookup(x509revoked, lookup_method); + if (lookup == NULL) { + fatal_f("cannot add store lookup[%d](revoked)", k); + return 0; /* ;-) */ + } + if (SSH_X509_LOOKUP_ADD(lookup, uri)) + debug2("store URI '%.400s' added to x509 store(revoked)", uri); + else + error("cannot add store URI '%.400s' to x509 store(revoked)", uri); + /*ERR_clear_error();*/ + } +#undef SSH_X509_LOOKUP_ADD + return 1; +} +#endif /*def USE_OPENSSL_STORE2*/ + + +static int +ssh_verify_cert(X509_STORE_CTX *_csc) { + int flag; + + if (ssh_x509flags.allowedcertpurpose >= 0) { + int def_purpose = ( ssh_x509flags.is_server + ? X509_PURPOSE_SSL_CLIENT + : X509_PURPOSE_SSL_SERVER + ); + X509_PURPOSE *xptmp = X509_PURPOSE_get0(ssh_x509flags.allowedcertpurpose); + int purpose; + if (xptmp == NULL) { + fatal_f("cannot get purpose from index"); + return -1; /* ;-) */ + } + purpose = X509_PURPOSE_get_id(xptmp); + flag = X509_STORE_CTX_purpose_inherit(_csc, def_purpose, purpose, 0); + if (flag <= 0) { + /* + * By default openssl applications don't check return code from + * X509_STORE_CTX_set_purpose or X509_STORE_CTX_purpose_inherit. + * + * Both methods return 0 (zero) and don't change purpose in context when: + * -X509_STORE_CTX_set_purpose(...) + * purpose is X509_PURPOSE_ANY + * -X509_STORE_CTX_purpose_inherit(...) + * purpose is X509_PURPOSE_ANY and default purpose is zero (!) + * + * Take note when purpose is "any" check method in current + * OpenSSL code just return 1. This openssl behavior is same + * as ssh option "AllowedCertPurpose=skip". + */ + int ecode = X509_STORE_CTX_get_error(_csc); + error_f("context purpose error, code=%d, msg='%.200s'" + , ecode + , X509_verify_cert_error_string(ecode)); + error_crypto("X509_STORE_CTX_purpose_inherit"); + return -1; + } + } + +{ /* lets use same time in all time checks */ + time_t check_time; + + time(&check_time); + X509_STORE_CTX_set_time(_csc, 0, check_time); +#ifdef USE_X509_STORE_CTX_INDEX +{ SSH_X509_STORE_CTX_DATA* data = NULL; + + if (ssh_X509_STORE_CTX_index >= 0) + data = SSH_X509_STORE_CTX_DATA_new(); + + if (data != NULL) { + data->check_time = check_time; + X509_STORE_CTX_set_ex_data(_csc, ssh_X509_STORE_CTX_index, data); + } +} +#endif /*def USE_X509_STORE_CTX_INDEX*/ +} + + flag = X509_verify_cert(_csc); + +#ifdef USE_X509_STORE_CTX_INDEX +{ SSH_X509_STORE_CTX_DATA* data = NULL; + + if (ssh_X509_STORE_CTX_index >= 0) + data = X509_STORE_CTX_get_ex_data(_csc, ssh_X509_STORE_CTX_index); + + if (data != NULL) { + X509_STORE_CTX_set_ex_data(_csc, ssh_X509_STORE_CTX_index, NULL); + SSH_X509_STORE_CTX_DATA_free(data); + } +} +#endif /*def USE_X509_STORE_CTX_INDEX*/ + + if (flag < 0) { + /* NOTE: negative result is returned only if certificate to check + * is not set in context. This function is called if _cert is non + * NULL, i.e. certificate has to be set in context! + * Lets log (possible in future) cases with negative value. + */ + logit("X509_verify_cert return unexpected negative value: '%d'", flag); + return -1; + } + if (flag == 0) { + int ecode = X509_STORE_CTX_get_error(_csc); + error_f("verify error, code=%d, msg='%.200s'" + , ecode + , X509_verify_cert_error_string(ecode)); + return -1; + } + + return 1; +} + + +int +ssh_x509store_verify_cert(X509 *cert, STACK_OF(X509) *untrusted) { + int ret = 1; + + if (cert == NULL) { + /*already checked but ...*/ + error_f("cert is NULL"); + ret = -1; + goto done; + } + /* untrusted chain could be NULL */ + if (x509store == NULL) { + error_f("context is NULL"); + ret = -1; + goto done; + } + + if (get_log_level() >= SYSLOG_LEVEL_DEBUG3) { + char *buf; + buf = ssh_X509_NAME_oneline(X509_get_subject_name(cert)); /*fatal on error*/ + debug3_f("for '%s'", buf); + free(buf); + } + +{ X509_STORE_CTX *csc = X509_STORE_CTX_new(); + if (csc == NULL) { + error_crypto("X509_STORE_CTX_new"); + ret = -1; + goto done; + } + if (X509_STORE_CTX_init(csc, x509store, cert, untrusted) <= 0) { + /*memory allocation error*/ + error_f("cannot initialize x509store context"); + ret = -1; + goto donecsc; + } + + ret = ssh_verify_cert(csc); + +donecsc: + X509_STORE_CTX_free(csc); +} +#ifdef SSH_OCSP_ENABLED + if (ret > 0) { +/* + * PKIX-SSH implementation first verify and validate certificate by + * "X.509 store" with certs and crls from file system. It is fast + * check. After this when certificate chain is correct and + * certificate is not revoked we send a status request to an OCSP + * responder if configured. + * + * RFC2560(OCSP): + * ... + * 2.7 CA Key Compromise + * If an OCSP responder knows that a particular CA's private key + * has been compromised, it MAY return the revoked state for all + * certificates issued by that CA. + * ... + * 5. Security Considerations + * For this service to be effective, certificate using systems must + * connect to the certificate status service provider. In the event + * such a connection cannot be obtained, certificate-using systems + * could implement CRL processing logic as a fall-back position. + * ... + * RFC2560(OCSP)^ + * + * About PKIX-SSH implementation: + * 1.) We prefer to delegate validation of issuer certificates to + * 'OCSP Provider'. It is easy and simple to configure an OCSP + * responder to return revoked state for all certificates issued + * by a CA. Usually 'OCSP Provider' admins shall be first informed + * for certificates with changed state. In each case this simplify + * 'OCSP client'. + * 2.) To conform to RFC2560 we should use OCSP to check status of + * all certificates in the chain. Since this is network request it + * is good to implement a cache and to save status with lifetime. + * Might is good to have an OCSP cache server ;-). + * + * To minimize network latency and keeping in mind 1.) we send + * 'OCSP request' only for the last certificate in the chain, i.e. + * sended client or server certificate. + * + * Therefore instead to send OCSP request in ssh_x509revoked_cb() + * we do this here. + */ + ret = ssh_ocsp_validate(cert, x509store); + } +#endif /*def SSH_OCSP_ENABLED*/ + +done: +{ + const char *msg_ok = "trusted"; + const char *msg; + msg = (ret > 0) ? msg_ok : (ret < 0 ? "error" : "rejected"); + debug3_f("return %d(%s)", ret, msg); +} + return ret; +} + + +static int +ssh_build_certchain_cb(int ok, X509_STORE_CTX *ctx) { + + if (get_log_level() >= SYSLOG_LEVEL_DEBUG3) { + X509 *ctx_cert = X509_STORE_CTX_get_current_cert(ctx); + char *buf; + + buf = ssh_X509_NAME_oneline(X509_get_subject_name(ctx_cert)); /*fatal on error*/ + debug3_f("subject='%s'", buf); + free(buf); + } + + return ok; +} + + +STACK_OF(X509)* +ssh_x509store_build_certchain(X509 *cert, STACK_OF(X509) *untrusted) { + STACK_OF(X509) *ret = NULL; + X509_STORE_CTX *csc; + + if (cert == NULL) { + /*already checked but ...*/ + error_f("cert is NULL"); + return NULL; + } + /* _chain could be NULL */ + if (x509store == NULL) { + error_f("X.509 store in not initialized"); + return NULL; + } + + csc = X509_STORE_CTX_new(); + if (csc == NULL) { + error_crypto("X509_STORE_CTX_new"); + return NULL; + } + + if (X509_STORE_CTX_init(csc, x509store, cert, untrusted) <= 0) { + /*memory allocation error*/ + error_f("cannot initialize X.509 store context"); + goto donecsc; + } + + X509_STORE_CTX_set_verify_cb(csc, ssh_build_certchain_cb); + + if (X509_verify_cert(csc) > 0) { + X509 *x; + ret = X509_STORE_CTX_get1_chain(csc); + /*pop certificate - it must be first in chain*/ + x = sk_X509_delete(ret, 0); + X509_free(x); + } else { + int ecode = X509_STORE_CTX_get_error(csc); + verbose("cannot build certificate chain, code=%d, msg='%.200s'" + , ecode + , X509_verify_cert_error_string(ecode)); + } + +donecsc: + X509_STORE_CTX_free(csc); + return ret; +} + + +static void +ssh_get_namestr_and_hash( + X509_NAME *name, + char **buf, + u_long *hash +) { + if (name == NULL) { + debug_f("name is NULL"); + if (buf ) *buf = NULL; + if (hash) *hash = 0; /* not correct but :-( */ + return; + } + + if (buf ) *buf = ssh_X509_NAME_oneline(name); /*fatal on error*/ + if (hash) *hash = X509_NAME_hash(name); +} + + +static inline uint32_t +ssh_X509_get_key_usage(X509 *x) { +#ifdef HAVE_X509_GET_KEY_USAGE + /* defined in openssl 1.1+ */ + return X509_get_key_usage(x); +#else + uint32_t flags = X509_get_extension_flags(x); + return (flags & EXFLAG_KUSAGE) ? x->ex_kusage : UINT32_MAX; +#endif +} + + +static inline unsigned long +ssh_X509_STORE_CTX_get_verify_flags(X509_STORE_CTX *ctx) { +#ifdef HAVE_X509_STORE_CTX_GET0_PARAM + X509_VERIFY_PARAM *param = X509_STORE_CTX_get0_param(ctx); + return X509_VERIFY_PARAM_get_flags(param); +#else + return ctx->flags; +#endif +} + + +static inline time_t +X509_STORE_CTX_get_verify_check_time(X509_STORE_CTX *ctx) { +#ifndef USE_X509_STORE_CTX_INDEX +#ifdef HAVE_X509_STORE_CTX_GET0_PARAM + X509_VERIFY_PARAM *param = X509_STORE_CTX_get0_param(ctx); + return X509_VERIFY_PARAM_get_time(param); +#else + return ctx->check_time; +#endif +#else /*def USE_X509_STORE_CTX_INDEX*/ + SSH_X509_STORE_CTX_DATA* data = NULL; + + if (ssh_X509_STORE_CTX_index >= 0) + data = X509_STORE_CTX_get_ex_data(ctx, ssh_X509_STORE_CTX_index); + + if (data != NULL) + return data->check_time; + +{ /*failback to current time*/ + time_t check_time; + time(&check_time); + return check_time; +} +#endif +} + + +static inline int +ssh_X509_cmp_time(const ASN1_TIME *s, time_t *t) { + /* work-arround for OpenSSL <= 0.9.8: non-const argument */ + return X509_cmp_time((ASN1_TIME*)s, t); +} + +static inline int +ssh_ASN1_UTCTIME_print(BIO *bio, const ASN1_UTCTIME *a) { + /* work-arround for OpenSSL <= 0.9.8: non-const argument */ + return ASN1_UTCTIME_print(bio, (ASN1_UTCTIME*)a); +} + +static int/*bool*/ +ssh_check_crl(X509_STORE_CTX *_ctx, X509* _issuer, X509_CRL *_crl) { + time_t check_time; + time_t *pcheck_time; + int k; + u_long hash; + + if (_issuer == NULL) { + error_f("issuer is NULL"); + return 0; + } + if (_crl == NULL) { + debug_f("crl is NULL"); + return 1; + } + + if (get_log_level() >= SYSLOG_LEVEL_DEBUG3) { + BIO *bio; + char *p; + + bio = BIO_new(BIO_s_mem()); + if (bio == NULL) { + fatal_f("out of memory"); + return 0; /* ;-) */ + } + + ssh_X509_NAME_print(bio, X509_CRL_get_issuer(_crl)); + + BIO_printf(bio, "; Last Update: "); + ssh_ASN1_UTCTIME_print(bio, X509_CRL_get0_lastUpdate(_crl)); + + BIO_printf(bio, "; Next Update: "); + ssh_ASN1_UTCTIME_print(bio, X509_CRL_get0_nextUpdate(_crl)); + + k = BIO_pending(bio); + p = xmalloc(k + 1); /*fatal on error*/ + k = BIO_read(bio, p, k); + p[k] = '\0'; + + debug3_f("issuer: %s", p); + + free(p); + BIO_free(bio); + } + +/* RFC 3280: + * The cRLSign bit is asserted when the subject public key is used + * for verifying a signature on certificate revocation list (e.g., a + * CRL, delta CRL, or an ARL). This bit MUST be asserted in + * certificates that are used to verify signatures on CRLs. + */ + if (!(ssh_X509_get_key_usage(_issuer) & KU_CRL_SIGN)) { + char *buf; + #ifdef X509_V_ERR_KEYUSAGE_NO_CRL_SIGN + /*first defined in OpenSSL 0.9.7d*/ + X509_STORE_CTX_set_error(_ctx, X509_V_ERR_KEYUSAGE_NO_CRL_SIGN); + #endif + ssh_get_namestr_and_hash(X509_get_subject_name(_issuer), &buf, &hash); + error_f("to verify crl signature key usage 'cRLSign'" + " must present in issuer certificate '%s' with hash=0x%08lx" + , buf, hash + ); + free(buf); + return 0; + } + + { + EVP_PKEY *pkey = X509_get_pubkey(_issuer); + if (pkey == NULL) { + error_f("unable to decode issuer public key"); + X509_STORE_CTX_set_error(_ctx, X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY); + return 0; + } + + if (X509_CRL_verify(_crl, pkey) <= 0) { + char *buf; + + ssh_get_namestr_and_hash(X509_CRL_get_issuer(_crl), &buf, &hash); + error_f("CRL has invalid signature: issuer='%s', hash=0x%08lx", buf, hash); + X509_STORE_CTX_set_error(_ctx, X509_V_ERR_CRL_SIGNATURE_FAILURE); + free(buf); + EVP_PKEY_free(pkey); + return 0; + } + EVP_PKEY_free(pkey); + } + + + if (ssh_X509_STORE_CTX_get_verify_flags(_ctx) & X509_V_FLAG_USE_CHECK_TIME) { + check_time = X509_STORE_CTX_get_verify_check_time(_ctx); + pcheck_time = &check_time; + } else + pcheck_time = NULL; + + k = ssh_X509_cmp_time(X509_CRL_get0_lastUpdate(_crl), pcheck_time); + if (k == 0) { + char *buf; + + ssh_get_namestr_and_hash(X509_CRL_get_issuer(_crl), &buf, &hash); + error_f("CRL has invalid lastUpdate field: issuer='%s', hash=0x%08lx", buf, hash); + X509_STORE_CTX_set_error(_ctx, X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD); + free(buf); + return 0; + } + if (k > 0) { + char *buf; + + ssh_get_namestr_and_hash(X509_CRL_get_issuer(_crl), &buf, &hash); + error_f("CRL is not yet valid: issuer='%s', hash=0x%08lx", buf, hash); + X509_STORE_CTX_set_error(_ctx, X509_V_ERR_CRL_NOT_YET_VALID); + free(buf); + return 0; + } + + k = ssh_X509_cmp_time(X509_CRL_get0_nextUpdate(_crl), pcheck_time); + if (k == 0) { + char *buf; + + ssh_get_namestr_and_hash(X509_CRL_get_issuer(_crl), &buf, &hash); + error_f("CRL has invalid nextUpdate field: issuer='%s', hash=0x%08lx", buf, hash); + X509_STORE_CTX_set_error(_ctx, X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD); + free(buf); + return 0; + } +#if 0 + /*test "extend time limit"*/ + if (k < 0) { + time_t tm; + if (pcheck_time == NULL) { + tm = time(NULL); + pcheck_time = &tm; + } + *pcheck_time -= convtime("1w"); + k = X509_cmp_time(X509_CRL_get_nextUpdate(_crl), pcheck_time); + } +#endif + if (k < 0) { + char *buf; + + ssh_get_namestr_and_hash(X509_CRL_get_issuer(_crl), &buf, &hash); + error_f("CRL is expired: issuer='%s', hash=0x%08lx", buf, hash); + X509_STORE_CTX_set_error(_ctx, X509_V_ERR_CRL_HAS_EXPIRED); + free(buf); + return 0; + } + + return 1; +} + + +static int/*bool*/ +ssh_is_cert_revoked(X509_STORE_CTX *_ctx, X509_CRL *_crl, X509 *_cert) { + X509_REVOKED *revoked; + ASN1_INTEGER *serial; + int ret = 1; + int k; + + if (_crl == NULL) return 1; + + revoked = X509_REVOKED_new(); + if (revoked == NULL) { + error_crypto("X509_REVOKED_new"); + return 1; + } + + serial = X509_get_serialNumber(_cert); + X509_REVOKED_set_serialNumber(revoked, serial); + k = sk_X509_REVOKED_find(X509_CRL_get_REVOKED(_crl), revoked); + if (k < 0) { + ret = 0; + goto done; + } + + X509_STORE_CTX_set_error(_ctx, X509_V_ERR_CERT_REVOKED); + /* yes, revoked. print log and ...*/ +{ + char *dn, *ser, *in; + + dn = ssh_X509_NAME_oneline(X509_get_subject_name(_cert)); /*fatal on error*/ + ser = ssh_ASN1_INTEGER_2_string(serial); + in = ssh_X509_NAME_oneline(X509_CRL_get_issuer (_crl )); /*fatal on error*/ + + logit("Certificate '%s' with serial '%.40s' revoked from issuer '%s'", dn, ser, in); + free(dn); + free(ser); + free(in); +} +done: + if (revoked) X509_REVOKED_free(revoked); + return ret; +} + + +static int +ssh_x509revoked_cb(int ok, X509_STORE_CTX *ctx) { + X509 *cert; + X509_CRL *crl; + + if (!ok) return 0; + if (x509revoked == NULL) + return ok; /* XXX:hmm */ + + cert = X509_STORE_CTX_get_current_cert(ctx); + if (cert == NULL) { + error_f("missing current certificate in x509store context"); + return 0; + } + + if (get_log_level() >= SYSLOG_LEVEL_DEBUG3) { + char *buf; + + buf = ssh_X509_NAME_oneline(X509_get_issuer_name(cert)); /*fatal on error*/ + debug3_f("issuer: %s", buf); + free(buf); + + buf = ssh_X509_NAME_oneline(X509_get_subject_name(cert)); /*fatal on error*/ + debug3_f("subject: %s", buf); + free(buf); + } + +/* TODO: + * NID_crl_distribution_points may contain one or more + * CRLissuer != cert issuer + */ + crl = ssh_x509store_get_crl_by_subject( + x509revoked, + X509_get_subject_name(cert) + ); + if (crl != NULL) { +/* + * In callback we cannot check CRL signature at this point when we use + * X509_get_issuer_name(), because we don't know issuer public key! + * Of course we can get the public key from X509_STORE defined by + * static variable "x509store". + * Of course we can check revocation outside callback, but we should + * try to find public key in X509_STORE[s]. + * + * At this point we can get easy public key of "current certificate"! + * + * Method: "look forward" + * At this call we check CLR (signature and other) issued with "current + * certificate" ("CertA"). If all is OK with "CertA" by next call of + * callback method "current certificate" is signed from "CertA" and the + * CRL issued from "CertA", if any is already verified - cool ;-). + * + * Note that when a certificate is revoked all signed from that + * certificate are revoked automatically too. With method "look forward" + * we already know that all issuers of "current certificate" aren't + * revoked. + */ + ok = ssh_check_crl(ctx, cert, crl); + } else { + if (ssh_x509flags.mandatory_crl == 1) { + int loc; + loc = X509_get_ext_by_NID(cert, NID_crl_distribution_points, -1); + ok = (loc < 0); + if (!ok) { + error_f("unable to get issued CRL"); + X509_STORE_CTX_set_error(ctx, X509_V_ERR_UNABLE_TO_GET_CRL); + } + } + } + if (!ok) return 0; + + crl = ssh_x509store_get_crl_by_subject( + x509revoked, + X509_get_issuer_name(cert) + ); + if (crl != NULL) { + ok = !ssh_is_cert_revoked(ctx, crl, cert); + } + if (!ok) return 0; + + return ok; +} diff -ruN openssh-9.4p1/x509store.h openssh-9.4p1+x509-14.2.1/x509store.h --- openssh-9.4p1/x509store.h 1970-01-01 02:00:00.000000000 +0200 +++ openssh-9.4p1+x509-14.2.1/x509store.h 2023-08-20 10:07:00.000000000 +0300 @@ -0,0 +1,200 @@ +#ifndef X509STORE_H +#define X509STORE_H +/* + * Copyright (c) 2002-2021 Roumen Petrov. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "includes.h" +#include + + +int ssh_X509_NAME_print(BIO* bio, X509_NAME *xn); +char* ssh_X509_NAME_oneline(X509_NAME *xn); + +#ifndef HAVE_ASN1_STRING_GET0_DATA /* OpenSSL < 1.1 */ +static inline const unsigned char * +ASN1_STRING_get0_data(const ASN1_STRING *x) { + return(x->data); +} +#endif /*ndef HAVE_ASN1_STRING_GET0_DATA OpenSSL < 1.1 */ + +static inline void +ssh_ASN1_STRING_get0_data(const ASN1_STRING *a, + const unsigned char **p, int *len +) { + if (p != NULL) + *p = ASN1_STRING_get0_data(a); + if (len != NULL) + *len = ASN1_STRING_length( + (ASN1_STRING_LENGTH_CONST ASN1_STRING*) a); +} + + +int ssh_x509store_verify_cert(X509 *cert, STACK_OF(X509) *untrusted); + +STACK_OF(X509)* ssh_x509store_build_certchain(X509 *cert, STACK_OF(X509) *untrusted); + + +typedef struct { + int is_server; + /* allowed client/server certificate purpose */ + int allowedcertpurpose; /* note field contain purpose index */ + int key_allow_selfissued; /* make sense only when x509store is enabled */ + int mandatory_crl; + + /* boolean: if true first key is validated that authorized + * otherwise first is authorized then validated. + */ + int validate_first; +} SSH_X509Flags; + +extern SSH_X509Flags ssh_x509flags; + +void ssh_x509flags_initialize(SSH_X509Flags *flags, int is_server); +void ssh_x509flags_defaults(SSH_X509Flags *flags); + +/* return purpose index, not purpose id (!) */ +int ssh_get_x509purpose_s(int _is_server, const char* _purpose_synonym); + +char* format_x509_purpose(int purpose_index); + + +int ssh_X509_NAME_cmp(X509_NAME *_a, X509_NAME *_b); +int/*bool*/ ssh_X509_is_selfissued(X509 *_cert); + +typedef struct { + /* ssh PKI(X509) store */ + const char *certificate_file; + const char *certificate_path; + const char *revocation_file; + const char *revocation_path; +} X509StoreOptions; + +void X509StoreOptions_init(X509StoreOptions *options); +void X509StoreOptions_cleanup(X509StoreOptions *options); +void X509StoreOptions_system_defaults(X509StoreOptions *options); +void X509StoreOptions_user_defaults(X509StoreOptions *options, uid_t uid); + +void ssh_x509store_cleanup(void); + +int/*bool*/ ssh_x509store_addlocations(const X509StoreOptions *locations); +#ifdef LDAP_ENABLED +int/*bool*/ ssh_x509store_addldapurl(const char *ldap_url, const char *ldap_ver); +#endif +#ifdef USE_OPENSSL_STORE2 +int/*bool*/ ssh_x509store_adduri(const char **store_uri, u_int num_store_uri); +#endif + +typedef char SSHXSTOREPATH; +#if !HAVE_DECL_DEFINE_STACK_OF +DECLARE_STACK_OF(SSHXSTOREPATH) +# define sk_SSHXSTOREPATH_new_null() SKM_sk_new_null(SSHXSTOREPATH) +# define sk_SSHXSTOREPATH_num(st) SKM_sk_num(SSHXSTOREPATH, (st)) +# define sk_SSHXSTOREPATH_value(st, i) SKM_sk_value(SSHXSTOREPATH, (st), (i)) +# define sk_SSHXSTOREPATH_push(st, val) SKM_sk_push(SSHXSTOREPATH, (st), (val)) +#else +DEFINE_STACK_OF(SSHXSTOREPATH) +#endif + +X509* +ssh_x509store_get_cert_by_subject(X509_STORE *store, X509_NAME *name); + +X509_CRL* +ssh_x509store_get_crl_by_subject(X509_STORE *store, X509_NAME *name); + + +#ifdef USE_X509_LOOKUP_MYSTORE +X509_LOOKUP_METHOD* X509_LOOKUP_mystore(void); + +#define X509_L_MYSTORE_URI 1 +#define X509_LOOKUP_add_mystore(x,value) \ + X509_LOOKUP_ctrl((x),X509_L_MYSTORE_URI,(value),(long)(0),NULL) +#endif + + +#ifdef SSH_OCSP_ENABLED + +enum va_type { + SSHVA_NONE, + SSHVA_OCSP_CERT, + SSHVA_OCSP_SPEC +}; + + +typedef struct { + int type; /*allowed values from enum va_type*/ + + /* file with additional trusted certificates */ + const char *certificate_file; + + /* ssh OCSP Provider(Respoder) URL */ + const char *responder_url; +} VAOptions; + +int ssh_get_default_vatype(void); +int ssh_get_vatype_s(const char* type); +const char* +ssh_get_vatype_i(int id); + +void ssh_set_validator(const VAOptions *_va); /*fatal on error*/ + +int ssh_ocsp_validate(X509 *cert, X509_STORE *x509store); + +#endif /*def SSH_OCSP_ENABLED*/ + + +#ifndef HAVE_STRUCT_X509_LOOKUP_METHOD_ST +/* temporary for some OpenSSL 1.1 "alpha" versions */ +struct x509_lookup_method_st { + const char *name; + int (*new_item) (X509_LOOKUP *ctx); + void (*free) (X509_LOOKUP *ctx); + int (*init) (X509_LOOKUP *ctx); + int (*shutdown) (X509_LOOKUP *ctx); + int (*ctrl) (X509_LOOKUP *ctx, int cmd, const char *argc, long argl, char **ret); + int (*get_by_subject) (X509_LOOKUP *ctx, int type, X509_NAME *name, X509_OBJECT *ret); + int (*get_by_issuer_serial) (X509_LOOKUP *ctx, int type, X509_NAME *name, ASN1_INTEGER *serial, X509_OBJECT *ret); + int (*get_by_fingerprint) (X509_LOOKUP *ctx, int type, unsigned char *bytes, int len, X509_OBJECT *ret); + int (*get_by_alias) (X509_LOOKUP *ctx, int type, char *str, int len, X509_OBJECT *ret); +}; + +struct x509_lookup_st { + int init; /* have we been started */ + int skip; /* don't use us. */ + X509_LOOKUP_METHOD *method; /* the functions */ + char *method_data; /* method data */ + X509_STORE *store_ctx; /* who owns us */ +}; + +struct x509_object_st { + X509_LOOKUP_TYPE type; + union { + char *ptr; + X509 *x509; + X509_CRL *crl; + EVP_PKEY *pkey; + } data; +}; +#endif /*ndef HAVE_STRUCT_X509_LOOKUP_METHOD_ST*/ + +#endif /* X509STORE_H */ diff -ruN openssh-9.4p1/xmalloc.c openssh-9.4p1+x509-14.2.1/xmalloc.c --- openssh-9.4p1/xmalloc.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/xmalloc.c 2023-08-20 10:07:01.000000000 +0300 @@ -30,16 +30,22 @@ char *malloc_options = "S"; #endif /* __OpenBSD__ */ +void +ssh_malloc_init(void) +{ + /*NOTE reserved for future use*/ +} + void * xmalloc(size_t size) { void *ptr; if (size == 0) - fatal("xmalloc: zero size"); + fatal_f("zero size"); ptr = malloc(size); if (ptr == NULL) - fatal("xmalloc: out of memory (allocating %zu bytes)", size); + fatal_f("out of memory (allocating %zu bytes)", size); return ptr; } @@ -49,12 +55,12 @@ void *ptr; if (size == 0 || nmemb == 0) - fatal("xcalloc: zero size"); + fatal_f("zero size"); if (SIZE_MAX / nmemb < size) - fatal("xcalloc: nmemb * size > SIZE_MAX"); + fatal_f("nmemb * size > SIZE_MAX"); ptr = calloc(nmemb, size); if (ptr == NULL) - fatal("xcalloc: out of memory (allocating %zu bytes)", + fatal_f("out of memory (allocating %zu bytes)", size * nmemb); return ptr; } @@ -66,7 +72,7 @@ new_ptr = reallocarray(ptr, nmemb, size); if (new_ptr == NULL) - fatal("xreallocarray: out of memory (%zu elements of %zu bytes)", + fatal_f("out of memory (%zu elements of %zu bytes)", nmemb, size); return new_ptr; } @@ -78,7 +84,7 @@ new_ptr = recallocarray(ptr, onmemb, nmemb, size); if (new_ptr == NULL) - fatal("xrecallocarray: out of memory (%zu elements of %zu bytes)", + fatal_f("out of memory (%zu elements of %zu bytes)", nmemb, size); return new_ptr; } @@ -101,7 +107,7 @@ i = vasprintf(ret, fmt, ap); if (i < 0 || *ret == NULL) - fatal("xvasprintf: could not allocate memory"); + fatal_f("could not allocate memory"); return i; } diff -ruN openssh-9.4p1/xmalloc.h openssh-9.4p1+x509-14.2.1/xmalloc.h --- openssh-9.4p1/xmalloc.h 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/xmalloc.h 2023-08-20 10:07:00.000000000 +0300 @@ -1,5 +1,4 @@ /* $OpenBSD: xmalloc.h,v 1.20 2021/04/03 06:18:41 djm Exp $ */ - /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -16,6 +15,9 @@ * called by a name other than "ssh" or "Secure Shell". */ +#include /*for va_list*/ + +void ssh_malloc_init(void); void *xmalloc(size_t); void *xcalloc(size_t, size_t); void *xreallocarray(void *, size_t, size_t); diff -ruN openssh-9.4p1/xmss_commons.c openssh-9.4p1+x509-14.2.1/xmss_commons.c --- openssh-9.4p1/xmss_commons.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/xmss_commons.c 2023-08-20 10:07:01.000000000 +0300 @@ -3,7 +3,7 @@ xmss_commons.c 20160722 Andreas Hülsing Joost Rijneveld -Public domain. +CC0 1.0 Universal Public Domain Dedication. */ #include "includes.h" diff -ruN openssh-9.4p1/xmss_commons.h openssh-9.4p1+x509-14.2.1/xmss_commons.h --- openssh-9.4p1/xmss_commons.h 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/xmss_commons.h 2023-08-20 10:07:00.000000000 +0300 @@ -4,14 +4,14 @@ xmss_commons.h 20160722 Andreas Hülsing Joost Rijneveld -Public domain. +CC0 1.0 Universal Public Domain Dedication. */ #ifndef XMSS_COMMONS_H #define XMSS_COMMONS_H #include #ifdef HAVE_STDINT_H -#include +# include #endif #endif void to_byte(unsigned char *output, unsigned long long in, uint32_t bytes); diff -ruN openssh-9.4p1/xmss_fast.c openssh-9.4p1+x509-14.2.1/xmss_fast.c --- openssh-9.4p1/xmss_fast.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/xmss_fast.c 2023-08-20 10:07:01.000000000 +0300 @@ -3,7 +3,7 @@ xmss_fast.c version 20160722 Andreas Hülsing Joost Rijneveld -Public domain. +CC0 1.0 Universal Public Domain Dedication. */ #include "includes.h" diff -ruN openssh-9.4p1/xmss_fast.h openssh-9.4p1+x509-14.2.1/xmss_fast.h --- openssh-9.4p1/xmss_fast.h 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/xmss_fast.h 2023-08-20 10:07:00.000000000 +0300 @@ -4,7 +4,7 @@ xmss_fast.h version 20160722 Andreas Hülsing Joost Rijneveld -Public domain. +CC0 1.0 Universal Public Domain Dedication. */ #include "xmss_wots.h" diff -ruN openssh-9.4p1/xmss_hash_address.c openssh-9.4p1+x509-14.2.1/xmss_hash_address.c --- openssh-9.4p1/xmss_hash_address.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/xmss_hash_address.c 2023-08-20 10:07:01.000000000 +0300 @@ -3,7 +3,7 @@ hash_address.c version 20160722 Andreas Hülsing Joost Rijneveld -Public domain. +CC0 1.0 Universal Public Domain Dedication. */ #include "includes.h" #ifdef WITH_XMSS diff -ruN openssh-9.4p1/xmss_hash_address.h openssh-9.4p1+x509-14.2.1/xmss_hash_address.h --- openssh-9.4p1/xmss_hash_address.h 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/xmss_hash_address.h 2023-08-20 10:07:00.000000000 +0300 @@ -4,11 +4,11 @@ hash_address.h version 20160722 Andreas Hülsing Joost Rijneveld -Public domain. +CC0 1.0 Universal Public Domain Dedication. */ #ifdef HAVE_STDINT_H -#include +# include #endif void setLayerADRS(uint32_t adrs[8], uint32_t layer); diff -ruN openssh-9.4p1/xmss_hash.c openssh-9.4p1+x509-14.2.1/xmss_hash.c --- openssh-9.4p1/xmss_hash.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/xmss_hash.c 2023-08-20 10:07:01.000000000 +0300 @@ -3,7 +3,7 @@ hash.c version 20160722 Andreas Hülsing Joost Rijneveld -Public domain. +CC0 1.0 Universal Public Domain Dedication. */ #include "includes.h" @@ -19,6 +19,7 @@ #endif #include #include +#include int core_hash_SHA2(unsigned char *, const unsigned int, const unsigned char *, unsigned int, const unsigned char *, unsigned long long, unsigned int); diff -ruN openssh-9.4p1/xmss_hash.h openssh-9.4p1+x509-14.2.1/xmss_hash.h --- openssh-9.4p1/xmss_hash.h 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/xmss_hash.h 2023-08-20 10:07:00.000000000 +0300 @@ -4,7 +4,7 @@ hash.h version 20160722 Andreas Hülsing Joost Rijneveld -Public domain. +CC0 1.0 Universal Public Domain Dedication. */ #ifndef HASH_H diff -ruN openssh-9.4p1/xmss_wots.c openssh-9.4p1+x509-14.2.1/xmss_wots.c --- openssh-9.4p1/xmss_wots.c 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/xmss_wots.c 2023-08-20 10:07:01.000000000 +0300 @@ -3,7 +3,7 @@ wots.c version 20160722 Andreas Hülsing Joost Rijneveld -Public domain. +CC0 1.0 Universal Public Domain Dedication. */ #include "includes.h" diff -ruN openssh-9.4p1/xmss_wots.h openssh-9.4p1+x509-14.2.1/xmss_wots.h --- openssh-9.4p1/xmss_wots.h 2023-08-10 04:10:22.000000000 +0300 +++ openssh-9.4p1+x509-14.2.1/xmss_wots.h 2023-08-20 10:07:00.000000000 +0300 @@ -4,14 +4,14 @@ wots.h version 20160722 Andreas Hülsing Joost Rijneveld -Public domain. +CC0 1.0 Universal Public Domain Dedication. */ #ifndef WOTS_H #define WOTS_H #ifdef HAVE_STDINT_H -#include "stdint.h" +# include "stdint.h" #endif /**