diff --git a/openssh/openssh-6.6.1p1-selinux-contexts.patch b/openssh/openssh-6.6.1p1-selinux-contexts.patch index fa9d591..eab724a 100644 --- a/openssh/openssh-6.6.1p1-selinux-contexts.patch +++ b/openssh/openssh-6.6.1p1-selinux-contexts.patch @@ -93,19 +93,17 @@ index 8f32464..18a2ca4 100644 #endif diff --git a/openbsd-compat/port-linux.c b/openbsd-compat/port-linux.c -index 22ea8ef..1fc963d 100644 ---- a/openbsd-compat/port-linux.c -+++ b/openbsd-compat/port-linux.c -@@ -179,7 +179,7 @@ ssh_selinux_change_context(const char *newname) - strlcpy(newctx + len, newname, newlen - len); - if ((cx = index(cx + 1, ':'))) - strlcat(newctx, cx, newlen); -- debug3("%s: setting context from '%s' to '%s'", __func__, -+ debug_f("setting context from '%s' to '%s'", - oldctx, newctx); +--- a/openbsd-compat/port-linux.c (revision 8241b9c0529228b4b86d88b1a6076fb9f97e4a99) ++++ b/openbsd-compat/port-linux.c (date 1703108053912) +@@ -207,7 +207,7 @@ + xasprintf(&newctx, "%.*s%s%s", (int)(cx - oldctx + 1), oldctx, + newname, cx2 == NULL ? "" : cx2); + +- debug3_f("setting context from '%s' to '%s'", oldctx, newctx); ++ debug_f("setting context from '%s' to '%s'", oldctx, newctx); if (setcon(newctx) < 0) - do_log2(log_level, "%s: setcon %s from %s failed with %s", - __func__, newctx, oldctx, strerror(errno)); + do_log2_f(log_level, "setcon %s from %s failed with %s", + newctx, oldctx, strerror(errno)); diff --git a/openbsd-compat/port-linux.h b/openbsd-compat/port-linux.h index cb51f99..8b7cda2 100644 --- a/openbsd-compat/port-linux.h diff --git a/openssh/openssh-6.7p1-coverity.patch b/openssh/openssh-6.7p1-coverity.patch index 494f4c6..01a061b 100644 --- a/openssh/openssh-6.7p1-coverity.patch +++ b/openssh/openssh-6.7p1-coverity.patch @@ -17,17 +17,6 @@ diff -up openssh-8.5p1/auth-krb5.c.coverity openssh-8.5p1/auth-krb5.c return oerrno; } /* make sure the KRB5CCNAME is set for non-standard location */ -diff -up openssh-8.5p1/auth-options.c.coverity openssh-8.5p1/auth-options.c ---- openssh-8.5p1/auth-options.c.coverity 2021-03-02 11:31:47.000000000 +0100 -+++ openssh-8.5p1/auth-options.c 2021-03-24 12:03:33.782968159 +0100 -@@ -706,6 +708,7 @@ serialise_array(struct sshbuf *m, char * - return r; - } - /* success */ -+ sshbuf_free(b); - return 0; - } - diff -up openssh-8.5p1/gss-genr.c.coverity openssh-8.5p1/gss-genr.c --- openssh-8.5p1/gss-genr.c.coverity 2021-03-26 11:52:46.613942552 +0100 +++ openssh-8.5p1/gss-genr.c 2021-03-26 11:54:37.881726318 +0100 @@ -42,32 +31,9 @@ diff -up openssh-8.5p1/gss-genr.c.coverity openssh-8.5p1/gss-genr.c for ((p = strsep(&cp, ",")); p && *p != '\0'; (p = strsep(&cp, ","))) { if (sshbuf_len(buf) != 0 && -diff -up openssh-8.5p1/kexgssc.c.coverity openssh-8.5p1/kexgssc.c ---- openssh-8.5p1/kexgssc.c.coverity 2021-03-24 12:03:33.711967665 +0100 -+++ openssh-8.5p1/kexgssc.c 2021-03-24 12:03:33.783968166 +0100 -@@ -98,8 +98,10 @@ kexgss_client(struct ssh *ssh) - default: - fatal_f("Unexpected KEX type %d", kex->kex_type); - } -- if (r != 0) -+ if (r != 0) { -+ ssh_gssapi_delete_ctx(&ctxt); - return r; -+ } - - token_ptr = GSS_C_NO_BUFFER; - diff -up openssh-8.5p1/krl.c.coverity openssh-8.5p1/krl.c --- openssh-8.5p1/krl.c.coverity 2021-03-02 11:31:47.000000000 +0100 +++ openssh-8.5p1/krl.c 2021-03-24 12:03:33.783968166 +0100 -@@ -1209,6 +1209,7 @@ ssh_krl_from_blob(struct sshbuf *buf, st - sshkey_free(key); - sshbuf_free(copy); - sshbuf_free(sect); -+ /* coverity[leaked_storage : FALSE] */ - return r; - } - @@ -1261,6 +1262,7 @@ is_key_revoked(struct ssh_krl *krl, cons return r; erb = RB_FIND(revoked_blob_tree, &krl->revoked_sha1s, &rb); @@ -164,23 +130,6 @@ diff -up openssh-7.4p1/monitor.c.coverity openssh-7.4p1/monitor.c return (0); error: -diff -up openssh-7.4p1/monitor_wrap.c.coverity openssh-7.4p1/monitor_wrap.c ---- openssh-7.4p1/monitor_wrap.c.coverity 2016-12-23 16:40:26.892788689 +0100 -+++ openssh-7.4p1/monitor_wrap.c 2016-12-23 16:40:26.900788691 +0100 -@@ -525,10 +525,10 @@ mm_pty_allocate(int *ptyfd, int *ttyfd, - if ((tmp1 = dup(pmonitor->m_recvfd)) == -1 || - (tmp2 = dup(pmonitor->m_recvfd)) == -1) { - error_f("cannot allocate fds for pty"); -- if (tmp1 > 0) -+ if (tmp1 >= 0) - close(tmp1); -- if (tmp2 > 0) -- close(tmp2); -+ /*DEAD CODE if (tmp2 >= 0) -+ close(tmp2);*/ - return 0; - } - close(tmp1); diff -up openssh-7.4p1/openbsd-compat/bindresvport.c.coverity openssh-7.4p1/openbsd-compat/bindresvport.c --- openssh-7.4p1/openbsd-compat/bindresvport.c.coverity 2016-12-19 05:59:41.000000000 +0100 +++ openssh-7.4p1/openbsd-compat/bindresvport.c 2016-12-23 16:40:26.901788691 +0100 @@ -234,23 +183,6 @@ diff -up openssh-8.5p1/readconf.c.coverity openssh-8.5p1/readconf.c goto out; } free(arg2); -diff -up openssh-8.7p1/scp.c.coverity openssh-8.7p1/scp.c ---- openssh-8.7p1/scp.c.coverity 2021-08-30 16:23:35.389741329 +0200 -+++ openssh-8.7p1/scp.c 2021-08-30 16:27:04.854555296 +0200 -@@ -186,11 +186,11 @@ killchild(int signo) - { - if (do_cmd_pid > 1) { - kill(do_cmd_pid, signo ? signo : SIGTERM); -- waitpid(do_cmd_pid, NULL, 0); -+ (void) waitpid(do_cmd_pid, NULL, 0); - } - if (do_cmd_pid2 > 1) { - kill(do_cmd_pid2, signo ? signo : SIGTERM); -- waitpid(do_cmd_pid2, NULL, 0); -+ (void) waitpid(do_cmd_pid2, NULL, 0); - } - - if (signo) diff -up openssh-7.4p1/servconf.c.coverity openssh-7.4p1/servconf.c --- openssh-7.4p1/servconf.c.coverity 2016-12-23 16:40:26.896788690 +0100 +++ openssh-7.4p1/servconf.c 2016-12-23 16:40:26.901788691 +0100 @@ -278,18 +210,6 @@ diff -up openssh-8.7p1/serverloop.c.coverity openssh-8.7p1/serverloop.c if (tun != SSH_TUNID_ANY && auth_opts->force_tun_device != (int)tun) goto done; -diff -up openssh-7.4p1/sftp.c.coverity openssh-7.4p1/sftp.c ---- openssh-7.4p1/sftp.c.coverity 2016-12-19 05:59:41.000000000 +0100 -+++ openssh-7.4p1/sftp.c 2016-12-23 16:40:26.903788691 +0100 -@@ -224,7 +224,7 @@ killchild(int signo) - pid = sshpid; - if (pid > 1) { - kill(pid, SIGTERM); -- waitpid(pid, NULL, 0); -+ (void) waitpid(pid, NULL, 0); - } - - _exit(1); diff -up openssh-7.4p1/ssh-agent.c.coverity openssh-7.4p1/ssh-agent.c --- openssh-7.4p1/ssh-agent.c.coverity 2016-12-19 05:59:41.000000000 +0100 +++ openssh-7.4p1/ssh-agent.c 2016-12-23 16:40:26.903788691 +0100 @@ -301,28 +221,6 @@ diff -up openssh-7.4p1/ssh-agent.c.coverity openssh-7.4p1/ssh-agent.c return NULL; } /* validate also provider from URI */ -@@ -1220,8 +1220,8 @@ main(int ac, char **av) - sanitise_stdfd(); - - /* drop */ -- setegid(getgid()); -- setgid(getgid()); -+ (void) setegid(getgid()); -+ (void) setgid(getgid()); - - platform_disable_tracing(0); /* strict=no */ - -diff -up openssh-8.5p1/ssh.c.coverity openssh-8.5p1/ssh.c ---- openssh-8.5p1/ssh.c.coverity 2021-03-24 12:03:33.779968138 +0100 -+++ openssh-8.5p1/ssh.c 2021-03-24 12:03:33.786968187 +0100 -@@ -1746,6 +1746,7 @@ control_persist_detach(void) - close(muxserver_sock); - muxserver_sock = -1; - options.control_master = SSHCTL_MASTER_NO; -+ /* coverity[leaked_handle: FALSE]*/ - muxclient(options.control_path); - /* muxclient() doesn't return on success. */ - fatal("Failed to connect to new control master"); diff -up openssh-7.4p1/sshd.c.coverity openssh-7.4p1/sshd.c --- openssh-7.4p1/sshd.c.coverity 2016-12-23 16:40:26.897788690 +0100 +++ openssh-7.4p1/sshd.c 2016-12-23 16:40:26.904788692 +0100 diff --git a/openssh/openssh-7.2p2-x11.patch b/openssh/openssh-7.2p2-x11.patch index 0a19ecb..b27d7c4 100644 --- a/openssh/openssh-7.2p2-x11.patch +++ b/openssh/openssh-7.2p2-x11.patch @@ -1,21 +1,23 @@ -diff -up openssh-7.2p2/channels.c.x11 openssh-7.2p2/channels.c ---- openssh-7.2p2/channels.c.x11 2016-03-09 19:04:48.000000000 +0100 -+++ openssh-7.2p2/channels.c 2016-06-03 10:42:04.775164520 +0200 -@@ -3990,21 +3990,24 @@ x11_create_display_inet(int x11_display_ +diff --git a/channels.c b/channels.c +--- a/channels.c (revision 8241b9c0529228b4b86d88b1a6076fb9f97e4a99) ++++ b/channels.c (date 1703026069921) +@@ -5075,11 +5075,13 @@ } - + static int -connect_local_xsocket_path(const char *pathname) +connect_local_xsocket_path(const char *pathname, int len) { int sock; struct sockaddr_un addr; - -+ if (len <= 0) -+ return -1; + ++ if (len <= 0) ++ return -1; sock = socket(AF_UNIX, SOCK_STREAM, 0); - if (sock == -1) + if (sock == -1) { error("socket: %.100s", strerror(errno)); +@@ -5087,11 +5089,12 @@ + } memset(&addr, 0, sizeof(addr)); addr.sun_family = AF_UNIX; - strlcpy(addr.sun_path, pathname, sizeof addr.sun_path); @@ -29,8 +31,8 @@ diff -up openssh-7.2p2/channels.c.x11 openssh-7.2p2/channels.c - error("connect %.100s: %.100s", addr.sun_path, strerror(errno)); return -1; } - -@@ -4012,8 +4015,18 @@ static int + +@@ -5099,8 +5102,18 @@ connect_local_xsocket(u_int dnr) { char buf[1024]; diff --git a/openssh/openssh-7.8p1-role-mls.patch b/openssh/openssh-7.8p1-role-mls.patch index 4dc460a..347766d 100644 --- a/openssh/openssh-7.8p1-role-mls.patch +++ b/openssh/openssh-7.8p1-role-mls.patch @@ -23,7 +23,7 @@ diff -up openssh/auth2.c.role-mls openssh/auth2.c if ((style = strchr(user, ':')) != NULL) *style++ = 0; -@@ -296,8 +304,15 @@ input_userauth_request(int type, u_int32 +@@ -314,8 +314,15 @@ input_userauth_request(int type, u_int32 use_privsep ? " [net]" : ""); authctxt->service = xstrdup(service); authctxt->style = style ? xstrdup(style) : NULL; @@ -34,12 +34,12 @@ diff -up openssh/auth2.c.role-mls openssh/auth2.c + if (use_privsep) { mm_inform_authserv(service, style); +#ifdef WITH_SELINUX -+ mm_inform_authrole(role); ++ mm_inform_authrole(role); +#endif -+ } ++ } userauth_banner(ssh); - if (auth2_setup_methods_lists(authctxt) != 0) - ssh_packet_disconnect(ssh, + if ((r = kex_server_update_ext_info(ssh)) != 0) + fatal_fr(r, "kex_server_update_ext_info failed"); diff -up openssh/auth2-gss.c.role-mls openssh/auth2-gss.c --- openssh/auth2-gss.c.role-mls 2018-08-20 07:57:29.000000000 +0200 +++ openssh/auth2-gss.c 2018-08-22 11:15:42.459799171 +0200 diff --git a/openssh/openssh-8.7p1-minrsabits.patch b/openssh/openssh-8.7p1-minrsabits.patch index 2ed59a3..479b55d 100644 --- a/openssh/openssh-8.7p1-minrsabits.patch +++ b/openssh/openssh-8.7p1-minrsabits.patch @@ -1,23 +1,21 @@ diff --git a/readconf.c b/readconf.c -index 7f26c680..42be690b 100644 ---- a/readconf.c -+++ b/readconf.c -@@ -320,6 +320,7 @@ static struct { +--- a/readconf.c (revision 8241b9c0529228b4b86d88b1a6076fb9f97e4a99) ++++ b/readconf.c (date 1703169891147) +@@ -326,6 +326,7 @@ { "securitykeyprovider", oSecurityKeyProvider }, { "knownhostscommand", oKnownHostsCommand }, - { "requiredrsasize", oRequiredRSASize }, + { "requiredrsasize", oRequiredRSASize }, + { "rsaminsize", oRequiredRSASize }, /* alias */ { "enableescapecommandline", oEnableEscapeCommandline }, - - { NULL, oBadOption } + { "obscurekeystroketiming", oObscureKeystrokeTiming }, + { "channeltimeout", oChannelTimeout }, diff --git a/servconf.c b/servconf.c -index 29df0463..423772b1 100644 ---- a/servconf.c -+++ b/servconf.c -@@ -676,6 +680,7 @@ static struct { +--- a/servconf.c (revision 8241b9c0529228b4b86d88b1a6076fb9f97e4a99) ++++ b/servconf.c (date 1703169891148) +@@ -691,6 +691,7 @@ { "casignaturealgorithms", sCASignatureAlgorithms, SSHCFG_ALL }, { "securitykeyprovider", sSecurityKeyProvider, SSHCFG_GLOBAL }, - { "requiredrsasize", sRequiredRSASize, SSHCFG_ALL }, + { "requiredrsasize", sRequiredRSASize, SSHCFG_ALL }, + { "rsaminsize", sRequiredRSASize, SSHCFG_ALL }, /* alias */ { "channeltimeout", sChannelTimeout, SSHCFG_ALL }, { "unusedconnectiontimeout", sUnusedConnectionTimeout, SSHCFG_ALL }, diff --git a/openssh/openssh-8.7p1-recursive-scp.patch b/openssh/openssh-8.7p1-recursive-scp.patch index f0d9b0f..17c340e 100644 --- a/openssh/openssh-8.7p1-recursive-scp.patch +++ b/openssh/openssh-8.7p1-recursive-scp.patch @@ -1,28 +1,28 @@ -diff -up openssh-8.7p1/scp.c.scp-sftpdirs openssh-8.7p1/scp.c ---- openssh-8.7p1/scp.c.scp-sftpdirs 2022-02-07 12:31:07.407740407 +0100 -+++ openssh-8.7p1/scp.c 2022-02-07 12:31:07.409740424 +0100 -@@ -1324,7 +1324,7 @@ source_sftp(int argc, char *src, char *t - +diff --git a/scp.c b/scp.c +--- a/scp.c (revision 8241b9c0529228b4b86d88b1a6076fb9f97e4a99) ++++ b/scp.c (date 1703111453316) +@@ -1372,7 +1372,7 @@ + if (src_is_dir && iamrecursive) { - if (upload_dir(conn, src, abs_dst, pflag, + if (sftp_upload_dir(conn, src, abs_dst, pflag, - SFTP_PROGRESS_ONLY, 0, 0, 1, 1) != 0) { + SFTP_PROGRESS_ONLY, 0, 0, 1, 1, 1) != 0) { - error("failed to upload directory %s to %s", src, targ); - errs = 1; - } -diff -up openssh-8.7p1/sftp-client.c.scp-sftpdirs openssh-8.7p1/sftp-client.c ---- openssh-8.7p1/sftp-client.c.scp-sftpdirs 2021-08-20 06:03:49.000000000 +0200 -+++ openssh-8.7p1/sftp-client.c 2022-02-07 12:47:59.117516131 +0100 -@@ -971,7 +971,7 @@ do_fsetstat(struct sftp_conn *conn, cons - + error("failed to upload directory %s to %s", src, targ); + errs = 1; + } +diff --git a/sftp-client.c b/sftp-client.c +--- a/sftp-client.c (revision 8241b9c0529228b4b86d88b1a6076fb9f97e4a99) ++++ b/sftp-client.c (date 1703169614263) +@@ -1003,7 +1003,7 @@ + /* Implements both the realpath and expand-path operations */ static char * --do_realpath_expand(struct sftp_conn *conn, const char *path, int expand) -+do_realpath_expand(struct sftp_conn *conn, const char *path, int expand, int create_dir) +-sftp_realpath_expand(struct sftp_conn *conn, const char *path, int expand) ++sftp_realpath_expand(struct sftp_conn *conn, const char *path, int expand, int create_dir) { struct sshbuf *msg; u_int expected_id, count, id; -@@ -1033,11 +1033,43 @@ do_realpath_expand(struct sftp_conn *con +@@ -1049,11 +1049,43 @@ if ((r = sshbuf_get_u32(msg, &status)) != 0 || (r = sshbuf_get_cstring(msg, &errmsg, NULL)) != 0) fatal_fr(r, "parse status"); @@ -33,7 +33,7 @@ diff -up openssh-8.7p1/sftp-client.c.scp-sftpdirs openssh-8.7p1/sftp-client.c - return NULL; + if ((status == SSH2_FX_NO_SUCH_FILE) && create_dir) { + memset(&a, '\0', sizeof(a)); -+ if ((r = do_mkdir(conn, path, &a, 0)) != 0) { ++ if ((r = sftp_mkdir(conn, path, &a, 0)) != 0) { + sshbuf_free(msg); + return NULL; + } @@ -71,111 +71,112 @@ diff -up openssh-8.7p1/sftp-client.c.scp-sftpdirs openssh-8.7p1/sftp-client.c } else if (type != SSH2_FXP_NAME) fatal("Expected SSH2_FXP_NAME(%u) packet, got %u", SSH2_FXP_NAME, type); -@@ -1039,9 +1067,9 @@ do_realpath_expand(struct sftp_conn *con +@@ -1078,9 +1110,9 @@ } - + char * --do_realpath(struct sftp_conn *conn, const char *path) -+do_realpath(struct sftp_conn *conn, const char *path, int create_dir) +-sftp_realpath(struct sftp_conn *conn, const char *path) ++sftp_realpath(struct sftp_conn *conn, const char *path, int create_dir) { -- return do_realpath_expand(conn, path, 0); -+ return do_realpath_expand(conn, path, 0, create_dir); +- return sftp_realpath_expand(conn, path, 0); ++ return sftp_realpath_expand(conn, path, 0, create_dir); } - + int -@@ -1055,9 +1083,9 @@ do_expand_path(struct sftp_conn *conn, c +@@ -1094,9 +1126,9 @@ { - if (!can_expand_path(conn)) { + if (!sftp_can_expand_path(conn)) { debug3_f("no server support, fallback to realpath"); -- return do_realpath_expand(conn, path, 0); -+ return do_realpath_expand(conn, path, 0, 0); +- return sftp_realpath_expand(conn, path, 0); ++ return sftp_realpath_expand(conn, path, 0, 0); } -- return do_realpath_expand(conn, path, 1); -+ return do_realpath_expand(conn, path, 1, 0); +- return sftp_realpath_expand(conn, path, 1); ++ return sftp_realpath_expand(conn, path, 1, 0); } - + int -@@ -1807,7 +1835,7 @@ download_dir(struct sftp_conn *conn, con +@@ -2016,7 +2048,7 @@ char *src_canon; int ret; - -- if ((src_canon = do_realpath(conn, src)) == NULL) { -+ if ((src_canon = do_realpath(conn, src, 0)) == NULL) { - error("download \"%s\": path canonicalization failed", src); - return -1; - } -@@ -2115,12 +2143,12 @@ upload_dir_internal(struct sftp_conn *co + +- if ((src_canon = sftp_realpath(conn, src)) == NULL) { ++ if ((src_canon = sftp_realpath(conn, src, 0)) == NULL) { + error("download \"%s\": path canonicalization failed", src); + return -1; + } +@@ -2365,12 +2397,12 @@ int - upload_dir(struct sftp_conn *conn, const char *src, const char *dst, + sftp_upload_dir(struct sftp_conn *conn, const char *src, const char *dst, int preserve_flag, int print_flag, int resume, int fsync_flag, - int follow_link_flag, int inplace_flag) + int follow_link_flag, int inplace_flag, int create_dir) { char *dst_canon; int ret; - -- if ((dst_canon = do_realpath(conn, dst)) == NULL) { -+ if ((dst_canon = do_realpath(conn, dst, create_dir)) == NULL) { - error("upload \"%s\": path canonicalization failed", dst); - return -1; - } -@@ -2557,7 +2585,7 @@ crossload_dir(struct sftp_conn *from, st + +- if ((dst_canon = sftp_realpath(conn, dst)) == NULL) { ++ if ((dst_canon = sftp_realpath(conn, dst, create_dir)) == NULL) { + error("upload \"%s\": path canonicalization failed", dst); + return -1; + } +@@ -2825,7 +2857,7 @@ char *from_path_canon; int ret; - -- if ((from_path_canon = do_realpath(from, from_path)) == NULL) { -+ if ((from_path_canon = do_realpath(from, from_path, 0)) == NULL) { - error("crossload \"%s\": path canonicalization failed", - from_path); - return -1; -diff -up openssh-8.7p1/sftp-client.h.scp-sftpdirs openssh-8.7p1/sftp-client.h ---- openssh-8.7p1/sftp-client.h.scp-sftpdirs 2021-08-20 06:03:49.000000000 +0200 -+++ openssh-8.7p1/sftp-client.h 2022-02-07 12:31:07.410740433 +0100 -@@ -111,7 +111,7 @@ int do_fsetstat(struct sftp_conn *, cons - int do_lsetstat(struct sftp_conn *conn, const char *path, Attrib *a); - + +- if ((from_path_canon = sftp_realpath(from, from_path)) == NULL) { ++ if ((from_path_canon = sftp_realpath(from, from_path, 0)) == NULL) { + error("crossload \"%s\": path canonicalization failed", + from_path); + return -1; +diff --git a/sftp-client.h b/sftp-client.h +--- a/sftp-client.h (revision 8241b9c0529228b4b86d88b1a6076fb9f97e4a99) ++++ b/sftp-client.h (date 1703111691284) +@@ -111,7 +111,7 @@ + int sftp_lsetstat(struct sftp_conn *conn, const char *path, Attrib *a); + /* Canonicalise 'path' - caller must free result */ --char *do_realpath(struct sftp_conn *, const char *); -+char *do_realpath(struct sftp_conn *, const char *, int); - +-char *sftp_realpath(struct sftp_conn *, const char *); ++char *sftp_realpath(struct sftp_conn *, const char *, int); + /* Canonicalisation with tilde expansion (requires server extension) */ - char *do_expand_path(struct sftp_conn *, const char *); -@@ -159,7 +159,7 @@ int do_upload(struct sftp_conn *, const + char *sftp_expand_path(struct sftp_conn *, const char *); +@@ -163,7 +163,7 @@ * times if 'pflag' is set */ - int upload_dir(struct sftp_conn *, const char *, const char *, + int sftp_upload_dir(struct sftp_conn *, const char *, const char *, - int, int, int, int, int, int); + int, int, int, int, int, int, int); - + /* * Download a 'from_path' from the 'from' connection and upload it to -diff -up openssh-8.7p1/sftp.c.scp-sftpdirs openssh-8.7p1/sftp.c ---- openssh-8.7p1/sftp.c.scp-sftpdirs 2021-08-20 06:03:49.000000000 +0200 -+++ openssh-8.7p1/sftp.c 2022-02-07 12:31:07.411740442 +0100 -@@ -760,7 +760,7 @@ process_put(struct sftp_conn *conn, cons - if (globpath_is_dir(g.gl_pathv[i]) && (rflag || global_rflag)) { - if (upload_dir(conn, g.gl_pathv[i], abs_dst, + +diff --git a/sftp.c b/sftp.c +--- a/sftp.c (revision 8241b9c0529228b4b86d88b1a6076fb9f97e4a99) ++++ b/sftp.c (date 1703168795365) +@@ -807,7 +807,7 @@ + (rflag || global_rflag)) { + if (sftp_upload_dir(conn, g.gl_pathv[i], abs_dst, pflag || global_pflag, 1, resume, - fflag || global_fflag, 0, 0) == -1) + fflag || global_fflag, 0, 0, 0) == -1) err = -1; } else { - if (do_upload(conn, g.gl_pathv[i], abs_dst, -@@ -1577,7 +1577,7 @@ parse_dispatch_command(struct sftp_conn + if (sftp_upload(conn, g.gl_pathv[i], abs_dst, +@@ -1642,7 +1642,7 @@ if (path1 == NULL || *path1 == '\0') path1 = xstrdup(startdir); - path1 = make_absolute(path1, *pwd); -- if ((tmp = do_realpath(conn, path1)) == NULL) { -+ if ((tmp = do_realpath(conn, path1, 0)) == NULL) { + path1 = sftp_make_absolute(path1, *pwd); +- if ((tmp = sftp_realpath(conn, path1)) == NULL) { ++ if ((tmp = sftp_realpath(conn, path1, 0)) == NULL) { err = 1; break; } -@@ -2160,7 +2160,7 @@ interactive_loop(struct sftp_conn *conn, +@@ -2247,7 +2247,7 @@ } #endif /* USE_LIBEDIT */ - -- remote_path = do_realpath(conn, "."); -+ remote_path = do_realpath(conn, ".", 0); - if (remote_path == NULL) + +- if ((remote_path = sftp_realpath(conn, ".")) == NULL) ++ if ((remote_path = sftp_realpath(conn, ".", 0)) == NULL) fatal("Need cwd"); startdir = xstrdup(remote_path); + diff --git a/openssh/openssh-9.3p1-merged-openssl-evp.patch b/openssh/openssh-9.3p1-merged-openssl-evp.patch index 95d86c3..6a30485 100644 --- a/openssh/openssh-9.3p1-merged-openssl-evp.patch +++ b/openssh/openssh-9.3p1-merged-openssl-evp.patch @@ -659,15 +659,15 @@ diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x # ifdef OPENSSL_HAS_ECC # include # include -@@ -268,6 +271,10 @@ +@@ -266,6 +266,10 @@ const char *sshkey_ssh_name_plain(const struct sshkey *); - int sshkey_names_valid2(const char *, int); + int sshkey_names_valid2(const char *, int, int); char *sshkey_alg_list(int, int, int, char); +int sshkey_calculate_signature(EVP_PKEY*, int, u_char **, + int *, const u_char *, size_t); +int sshkey_verify_signature(EVP_PKEY *, int, const u_char *, + size_t, u_char *, int); - + int sshkey_from_blob(const u_char *, size_t, struct sshkey **); int sshkey_fromb(struct sshbuf *, struct sshkey **); @@ -324,6 +331,13 @@ @@ -695,11 +695,11 @@ diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x #if !defined(WITH_OPENSSL) # undef RSA # undef DSA -diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x config.status -x configure~ -x configure.ac openssh-9.3p1/ssh-pkcs11.c openssh-9.3p1-patched/ssh-pkcs11.c ---- openssh-9.3p1/ssh-pkcs11.c 2023-06-06 15:53:36.592443989 +0200 -+++ openssh-9.3p1-patched/ssh-pkcs11.c 2023-06-06 15:52:25.626551768 +0200 -@@ -777,8 +777,24 @@ - +diff --git a/ssh-pkcs11.c b/ssh-pkcs11.c +--- a/ssh-pkcs11.c (revision 8241b9c0529228b4b86d88b1a6076fb9f97e4a99) ++++ b/ssh-pkcs11.c (date 1703110934679) +@@ -620,8 +620,24 @@ + return (0); } + @@ -711,7 +711,7 @@ diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x + return 0; +} #endif /* OPENSSL_HAS_ECC && HAVE_EC_KEY_METHOD_NEW */ - + +int +is_rsa_pkcs11(RSA *rsa) +{ @@ -722,14 +722,14 @@ diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x + /* remove trailing spaces. Note, that this does NOT guarantee the buffer * will be null terminated if there are no trailing spaces! */ - static void -diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x config.status -x configure~ -x configure.ac openssh-9.3p1/ssh-pkcs11-client.c openssh-9.3p1-patched/ssh-pkcs11-client.c ---- openssh-9.3p1/ssh-pkcs11-client.c 2023-06-06 15:53:36.591443976 +0200 -+++ openssh-9.3p1-patched/ssh-pkcs11-client.c 2023-06-06 15:52:25.626551768 +0200 -@@ -225,8 +225,36 @@ - static RSA_METHOD *helper_rsa; - #if defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW) - static EC_KEY_METHOD *helper_ecdsa; + static char * +diff --git a/ssh-pkcs11-client.c b/ssh-pkcs11-client.c +--- a/ssh-pkcs11-client.c (revision 8241b9c0529228b4b86d88b1a6076fb9f97e4a99) ++++ b/ssh-pkcs11-client.c (date 1703110830967) +@@ -402,8 +402,36 @@ + if (helper->nrsa == 0 && helper->nec == 0) + helper_terminate(helper); + } + +int +is_ecdsa_pkcs11(EC_KEY *ecdsa) @@ -744,8 +744,8 @@ diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x + return 1; + return 0; +} - #endif /* OPENSSL_HAS_ECC && HAVE_EC_KEY_METHOD_NEW */ - + #endif /* defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW) */ + +int +is_rsa_pkcs11(RSA *rsa) +{ @@ -762,14 +762,15 @@ diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x + /* redirect private key crypto operations to the ssh-pkcs11-helper */ static void - wrap_key(struct sshkey *k) -diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x config.status -x configure~ -x configure.ac openssh-9.3p1/ssh-pkcs11.h openssh-9.3p1-patched/ssh-pkcs11.h ---- openssh-9.3p1/ssh-pkcs11.h 2023-06-06 15:53:36.592443989 +0200 -+++ openssh-9.3p1-patched/ssh-pkcs11.h 2023-06-06 15:52:25.626551768 +0200 -@@ -39,6 +39,11 @@ - u_int32_t *); - #endif - + wrap_key(struct helper *helper, struct sshkey *k) +diff --git a/ssh-pkcs11.h b/ssh-pkcs11.h +--- a/ssh-pkcs11.h (revision 8241b9c0529228b4b86d88b1a6076fb9f97e4a99) ++++ b/ssh-pkcs11.h (date 1703111023334) +@@ -38,6 +38,12 @@ + /* Only available in ssh-pkcs11-client.c so far */ + int pkcs11_make_cert(const struct sshkey *, + const struct sshkey *, struct sshkey **); ++ +#ifdef HAVE_EC_KEY_METHOD_NEW +int is_ecdsa_pkcs11(EC_KEY *ecdsa); +#endif diff --git a/openssh/openssh-9.3p1-openssl-compat.patch b/openssh/openssh-9.3p1-openssl-compat.patch deleted file mode 100644 index cf512ef..0000000 --- a/openssh/openssh-9.3p1-openssl-compat.patch +++ /dev/null @@ -1,40 +0,0 @@ ---- openssh-9.3p1/openbsd-compat/openssl-compat.c 2023-03-15 22:28:19.000000000 +0100 -+++ /home/dbelyavs/work/upstream/openssh-portable/openbsd-compat/openssl-compat.c 2023-05-25 14:19:42.870841944 +0200 -@@ -33,10 +33,10 @@ - - /* - * OpenSSL version numbers: MNNFFPPS: major minor fix patch status -- * We match major, minor, fix and status (not patch) for <1.0.0. -- * After that, we acceptable 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 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. -+ * See https://www.openssl.org/policies/releasestrat.html - */ - - int -@@ -48,15 +48,17 @@ - if (headerver == libver) - return 1; - -- /* for versions < 1.0.0, major,minor,fix,status must match */ -- if (headerver < 0x1000000f) { -- mask = 0xfffff00fL; /* major,minor,fix,status */ -+ /* -+ * For versions >= 3.0, only the major and status must match. -+ */ -+ if (headerver >= 0x3000000f) { -+ mask = 0xf000000fL; /* major,status */ - return (headerver & mask) == (libver & mask); - } - - /* -- * For versions >= 1.0.0, major,minor,status must match and library -- * fix version must be equal to or newer than the header. -+ * 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 */ - hfix = (headerver & 0x000ff000) >> 12; diff --git a/openssh/openssh-9.3p1-gssapi-keyex.patch b/openssh/openssh-9.7p1-gssapi-keyex.patch similarity index 89% rename from openssh/openssh-9.3p1-gssapi-keyex.patch rename to openssh/openssh-9.7p1-gssapi-keyex.patch index 68dc906..81aa6f6 100644 --- a/openssh/openssh-9.3p1-gssapi-keyex.patch +++ b/openssh/openssh-9.7p1-gssapi-keyex.patch @@ -1,37 +1,121 @@ -diff --git a/Makefile.in b/Makefile.in -index e7549470..b68c1710 100644 ---- a/Makefile.in -+++ b/Makefile.in -@@ -109,6 +109,7 @@ LIBSSH_OBJS=${LIBOPENSSH_OBJS} \ - kex.o kexdh.o kexgex.o kexecdh.o kexc25519.o \ - kexgexc.o kexgexs.o \ - kexsntrup761x25519.o sntrup761.o kexgen.o \ -+ kexgssc.o \ - sftp-realpath.o platform-pledge.o platform-tracing.o platform-misc.o \ - sshbuf-io.o +diff -Naur a/auth2.c b/auth2.c +--- a/auth2.c 2024-03-21 18:44:47.988756559 +0600 ++++ b/auth2.c 2024-03-21 18:52:37.708730004 +0600 +@@ -71,6 +71,7 @@ + extern Authmethod method_kbdint; + extern Authmethod method_hostbased; + #ifdef GSSAPI ++extern Authmethod method_gsskeyex; + extern Authmethod method_gssapi; + #endif -@@ -125,7 +126,7 @@ SSHDOBJS=sshd.o auth-rhosts.o auth-passwd.o \ - auth-bsdauth.o auth2-hostbased.o auth2-kbdint.o \ - auth2-none.o auth2-passwd.o auth2-pubkey.o auth2-pubkeyfile.o \ - monitor.o monitor_wrap.o auth-krb5.o \ -- auth2-gss.o gss-serv.o gss-serv-krb5.o \ -+ auth2-gss.o gss-serv.o gss-serv-krb5.o kexgsss.o \ - loginrec.o auth-pam.o auth-shadow.o auth-sia.o \ - srclimit.o sftp-server.o sftp-common.o \ - sandbox-null.o sandbox-rlimit.o sandbox-systrace.o sandbox-darwin.o \ -@@ -523,7 +523,7 @@ regress-prep: - ln -s `cd $(srcdir) && pwd`/regress/Makefile `pwd`/regress/Makefile +@@ -78,6 +79,7 @@ + &method_none, + &method_pubkey, + #ifdef GSSAPI ++ &method_gsskeyex, + &method_gssapi, + #endif + &method_passwd, +diff -Naur a/auth2-gss.c b/auth2-gss.c +--- a/auth2-gss.c 2024-03-21 18:44:47.988756559 +0600 ++++ b/auth2-gss.c 2024-03-21 18:51:24.405202322 +0600 +@@ -1,7 +1,7 @@ + /* $OpenBSD: auth2-gss.c,v 1.34 2023/03/31 04:22:27 djm Exp $ */ - REGRESSLIBS=libssh.a $(LIBCOMPAT) --TESTLIBS=$(LIBS) $(CHANNELLIBS) -+TESTLIBS=$(LIBS) $(CHANNELLIBS) $(GSSLIBS) + /* +- * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved. ++ * Copyright (c) 2001-2007 Simon Wilkinson. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions +@@ -58,6 +58,48 @@ + static int input_gssapi_errtok(int, u_int32_t, struct ssh *); - regress/modpipe$(EXEEXT): $(srcdir)/regress/modpipe.c $(REGRESSLIBS) - $(CC) $(CFLAGS) $(CPPFLAGS) -o $@ $(srcdir)/regress/modpipe.c \ -diff -up a/auth.c.gsskex b/auth.c ---- a/auth.c.gsskex 2021-08-20 06:03:49.000000000 +0200 -+++ b/auth.c 2021-08-27 12:41:51.262788953 +0200 -@@ -402,7 +402,8 @@ auth_root_allowed(struct ssh *ssh, const + /* ++ * The 'gssapi_keyex' userauth mechanism. ++ */ ++static int ++userauth_gsskeyex(struct ssh *ssh, const char *method) ++{ ++ Authctxt *authctxt = ssh->authctxt; ++ int r, authenticated = 0; ++ struct sshbuf *b = NULL; ++ gss_buffer_desc mic, gssbuf; ++ u_char *p; ++ size_t len; ++ ++ if ((r = sshpkt_get_string(ssh, &p, &len)) != 0 || ++ (r = sshpkt_get_end(ssh)) != 0) ++ fatal_fr(r, "parsing"); ++ ++ if ((b = sshbuf_new()) == NULL) ++ fatal_f("sshbuf_new failed"); ++ ++ mic.value = p; ++ mic.length = len; ++ ++ ssh_gssapi_buildmic(b, authctxt->user, authctxt->service, ++ "gssapi-keyex", ssh->kex->session_id); ++ ++ if ((gssbuf.value = sshbuf_mutable_ptr(b)) == NULL) ++ fatal_f("sshbuf_mutable_ptr failed"); ++ gssbuf.length = sshbuf_len(b); ++ ++ /* gss_kex_context is NULL with privsep, so we can't check it here */ ++ if (!GSS_ERROR(PRIVSEP(ssh_gssapi_checkmic(gss_kex_context, ++ &gssbuf, &mic)))) ++ authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user, ++ authctxt->pw, 1)); ++ ++ sshbuf_free(b); ++ free(mic.value); ++ ++ return (authenticated); ++} ++ ++/* + * We only support those mechanisms that we know about (ie ones that we know + * how to check local user kuserok and the like) + */ +@@ -267,7 +309,8 @@ + if ((r = sshpkt_get_end(ssh)) != 0) + fatal_fr(r, "parse packet"); + +- authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user)); ++ authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user, ++ authctxt->pw, 1)); + + if ((!use_privsep || mm_is_monitor()) && + (displayname = ssh_gssapi_displayname()) != NULL) +@@ -320,7 +363,8 @@ + gssbuf.length = sshbuf_len(b); + + if (!GSS_ERROR(PRIVSEP(ssh_gssapi_checkmic(gssctxt, &gssbuf, &mic)))) +- authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user)); ++ authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user, ++ authctxt->pw, 0)); + else + logit("GSSAPI MIC check failed"); + +@@ -342,6 +386,13 @@ + return 0; + } + ++Authmethod method_gsskeyex = { ++ "gssapi-keyex", ++ NULL, ++ userauth_gsskeyex, ++ &options.gss_authentication ++}; ++ + Authmethod method_gssapi = { + "gssapi-with-mic", + NULL, +diff -Naur a/auth.c b/auth.c +--- a/auth.c 2023-12-18 20:59:50.000000000 +0600 ++++ b/auth.c 2024-03-21 18:48:09.282459560 +0600 +@@ -357,7 +357,8 @@ case PERMIT_NO_PASSWD: if (strcmp(method, "publickey") == 0 || strcmp(method, "hostbased") == 0 || @@ -41,7 +125,7 @@ diff -up a/auth.c.gsskex b/auth.c return 1; break; case PERMIT_FORCED_ONLY: -@@ -730,97 +731,6 @@ fakepw(void) +@@ -638,97 +639,6 @@ } /* @@ -139,126 +223,9 @@ diff -up a/auth.c.gsskex b/auth.c * Return the canonical name of the host in the other side of the current * connection. The host name is cached, so it is efficient to call this * several times. -diff --git a/auth2-gss.c b/auth2-gss.c -index 9351e042..d6446c0c 100644 ---- a/auth2-gss.c -+++ b/auth2-gss.c -@@ -1,7 +1,7 @@ - /* $OpenBSD: auth2-gss.c,v 1.33 2021/12/19 22:12:07 djm Exp $ */ - - /* -- * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved. -+ * Copyright (c) 2001-2007 Simon Wilkinson. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions -@@ -54,6 +54,48 @@ static int input_gssapi_mic(int type, u_int32_t plen, struct ssh *ssh); - static int input_gssapi_exchange_complete(int type, u_int32_t plen, struct ssh *ssh); - static int input_gssapi_errtok(int, u_int32_t, struct ssh *); - -+/* -+ * The 'gssapi_keyex' userauth mechanism. -+ */ -+static int -+userauth_gsskeyex(struct ssh *ssh, const char *method) -+{ -+ Authctxt *authctxt = ssh->authctxt; -+ int r, authenticated = 0; -+ struct sshbuf *b = NULL; -+ gss_buffer_desc mic, gssbuf; -+ u_char *p; -+ size_t len; -+ -+ if ((r = sshpkt_get_string(ssh, &p, &len)) != 0 || -+ (r = sshpkt_get_end(ssh)) != 0) -+ fatal_fr(r, "parsing"); -+ -+ if ((b = sshbuf_new()) == NULL) -+ fatal_f("sshbuf_new failed"); -+ -+ mic.value = p; -+ mic.length = len; -+ -+ ssh_gssapi_buildmic(b, authctxt->user, authctxt->service, -+ "gssapi-keyex", ssh->kex->session_id); -+ -+ if ((gssbuf.value = sshbuf_mutable_ptr(b)) == NULL) -+ fatal_f("sshbuf_mutable_ptr failed"); -+ gssbuf.length = sshbuf_len(b); -+ -+ /* gss_kex_context is NULL with privsep, so we can't check it here */ -+ if (!GSS_ERROR(PRIVSEP(ssh_gssapi_checkmic(gss_kex_context, -+ &gssbuf, &mic)))) -+ authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user, -+ authctxt->pw, 1)); -+ -+ sshbuf_free(b); -+ free(mic.value); -+ -+ return (authenticated); -+} -+ - /* - * We only support those mechanisms that we know about (ie ones that we know - * how to check local user kuserok and the like) -@@ -260,7 +302,8 @@ input_gssapi_exchange_complete(int type, u_int32_t plen, struct ssh *ssh) - if ((r = sshpkt_get_end(ssh)) != 0) - fatal_fr(r, "parse packet"); - -- authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user)); -+ authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user, -+ authctxt->pw, 1)); - - if ((!use_privsep || mm_is_monitor()) && - (displayname = ssh_gssapi_displayname()) != NULL) -@@ -306,7 +349,8 @@ input_gssapi_mic(int type, u_int32_t plen, struct ssh *ssh) - gssbuf.length = sshbuf_len(b); - - if (!GSS_ERROR(PRIVSEP(ssh_gssapi_checkmic(gssctxt, &gssbuf, &mic)))) -- authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user)); -+ authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user, -+ authctxt->pw, 0)); - else - logit("GSSAPI MIC check failed"); - -@@ -326,6 +370,13 @@ input_gssapi_mic(int type, u_int32_t plen, struct ssh *ssh) - return 0; - } - -+Authmethod method_gsskeyex = { -+ "gssapi-keyex", -+ NULL, -+ userauth_gsskeyex, -+ &options.gss_authentication -+}; -+ - Authmethod method_gssapi = { - "gssapi-with-mic", - NULL, -diff --git a/auth2.c b/auth2.c -index 0e776224..1c217268 100644 ---- a/auth2.c -+++ b/auth2.c -@@ -73,6 +73,7 @@ extern Authmethod method_passwd; - extern Authmethod method_kbdint; - extern Authmethod method_hostbased; - #ifdef GSSAPI -+extern Authmethod method_gsskeyex; - extern Authmethod method_gssapi; - #endif - -@@ -80,6 +81,7 @@ Authmethod *authmethods[] = { - &method_none, - &method_pubkey, - #ifdef GSSAPI -+ &method_gsskeyex, - &method_gssapi, - #endif - &method_passwd, -diff --git a/canohost.c b/canohost.c -index abea9c6e..8e81b519 100644 ---- a/canohost.c -+++ b/canohost.c +diff -Naur a/canohost.c b/canohost.c +--- a/canohost.c 2023-12-18 20:59:50.000000000 +0600 ++++ b/canohost.c 2024-03-21 18:53:35.870355251 +0600 @@ -35,6 +35,99 @@ #include "canohost.h" #include "misc.h" @@ -359,10 +326,9 @@ index abea9c6e..8e81b519 100644 void ipv64_normalise_mapped(struct sockaddr_storage *addr, socklen_t *len) { -diff --git a/canohost.h b/canohost.h -index 26d62855..0cadc9f1 100644 ---- a/canohost.h -+++ b/canohost.h +diff -Naur a/canohost.h b/canohost.h +--- a/canohost.h 2023-12-18 20:59:50.000000000 +0600 ++++ b/canohost.h 2024-03-21 18:54:55.294843493 +0600 @@ -15,6 +15,9 @@ #ifndef _CANOHOST_H #define _CANOHOST_H @@ -373,11 +339,10 @@ index 26d62855..0cadc9f1 100644 char *get_peer_ipaddr(int); int get_peer_port(int); char *get_local_ipaddr(int); -diff --git a/clientloop.c b/clientloop.c -index ebd0dbca..1bdac6a4 100644 ---- a/clientloop.c -+++ b/clientloop.c -@@ -112,6 +112,10 @@ +diff -Naur a/clientloop.c b/clientloop.c +--- a/clientloop.c 2023-12-18 20:59:50.000000000 +0600 ++++ b/clientloop.c 2024-03-21 18:56:16.425320744 +0600 +@@ -115,6 +115,10 @@ #include "ssherr.h" #include "hostfile.h" @@ -388,7 +353,7 @@ index ebd0dbca..1bdac6a4 100644 /* Permitted RSA signature algorithms for UpdateHostkeys proofs */ #define HOSTKEY_PROOF_RSA_ALGS "rsa-sha2-512,rsa-sha2-256" -@@ -1379,6 +1383,14 @@ client_loop(struct ssh *ssh, int have_pty, int escape_char_arg, +@@ -1594,6 +1598,14 @@ /* Do channel operations. */ channel_after_poll(ssh, pfd, npfd_active); @@ -403,11 +368,10 @@ index ebd0dbca..1bdac6a4 100644 /* Buffer input from the connection. */ if (conn_in_ready) client_process_net_input(ssh); -diff --git a/configure.ac b/configure.ac -index b689db4b..efafb6bd 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -674,6 +674,30 @@ main() { if (NSVersionOfRunTimeLibrary("System") >= (60 << 16)) +diff -Naur a/configure.ac b/configure.ac +--- a/configure.ac 2024-03-21 18:44:47.997756501 +0600 ++++ b/configure.ac 2024-03-21 18:57:20.788906029 +0600 +@@ -766,6 +766,30 @@ [Use tunnel device compatibility to OpenBSD]) AC_DEFINE([SSH_TUN_PREPEND_AF], [1], [Prepend the address family to IP tunnel traffic]) @@ -438,12 +402,11 @@ index b689db4b..efafb6bd 100644 m4_pattern_allow([AU_IPv]) AC_CHECK_DECL([AU_IPv4], [], AC_DEFINE([AU_IPv4], [0], [System only supports IPv4 audit records]) -diff --git a/gss-genr.c b/gss-genr.c -index d56257b4..763a63ff 100644 ---- a/gss-genr.c -+++ b/gss-genr.c +diff -Naur a/gss-genr.c b/gss-genr.c +--- a/gss-genr.c 2023-12-18 20:59:50.000000000 +0600 ++++ b/gss-genr.c 2024-03-21 21:01:01.596219266 +0600 @@ -1,7 +1,7 @@ - /* $OpenBSD: gss-genr.c,v 1.28 2021/01/27 10:05:28 djm Exp $ */ + /* $OpenBSD: gss-genr.c,v 1.29 2024/02/01 02:37:33 djm Exp $ */ /* - * Copyright (c) 2001-2007 Simon Wilkinson. All rights reserved. @@ -451,7 +414,7 @@ index d56257b4..763a63ff 100644 * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions -@@ -41,9 +41,33 @@ +@@ -42,9 +42,33 @@ #include "sshbuf.h" #include "log.h" #include "ssh2.h" @@ -485,7 +448,7 @@ index d56257b4..763a63ff 100644 /* sshbuf_get for gss_buffer_desc */ int ssh_gssapi_get_buffer_desc(struct sshbuf *b, gss_buffer_desc *g) -@@ -62,6 +86,159 @@ ssh_gssapi_get_buffer_desc(struct sshbuf *b, gss_buffer_desc *g) +@@ -60,6 +84,159 @@ return 0; } @@ -645,7 +608,7 @@ index d56257b4..763a63ff 100644 /* Check that the OID in a data stream matches that in the context */ int ssh_gssapi_check_oid(Gssctxt *ctx, void *data, size_t len) -@@ -218,7 +398,7 @@ ssh_gssapi_init_ctx(Gssctxt *ctx, int deleg_creds, gss_buffer_desc *recv_tok, +@@ -216,7 +393,7 @@ } ctx->major = gss_init_sec_context(&ctx->minor, @@ -654,11 +617,10 @@ index d56257b4..763a63ff 100644 GSS_C_MUTUAL_FLAG | GSS_C_INTEG_FLAG | deleg_flag, 0, NULL, recv_tok, NULL, send_tok, flags, NULL); -@@ -247,9 +427,43 @@ ssh_gssapi_import_name(Gssctxt *ctx, const char *host) - return (ctx->major); +@@ -246,8 +423,42 @@ } -+OM_uint32 + OM_uint32 +ssh_gssapi_client_identity(Gssctxt *ctx, const char *name) +{ + gss_buffer_desc gssbuf; @@ -689,7 +651,7 @@ index d56257b4..763a63ff 100644 + return(ctx->major); +} + - OM_uint32 ++OM_uint32 ssh_gssapi_sign(Gssctxt *ctx, gss_buffer_t buffer, gss_buffer_t hash) { + if (ctx == NULL) @@ -698,7 +660,7 @@ index d56257b4..763a63ff 100644 if ((ctx->major = gss_get_mic(&ctx->minor, ctx->context, GSS_C_QOP_DEFAULT, buffer, hash))) ssh_gssapi_error(ctx); -@@ -257,6 +471,19 @@ ssh_gssapi_sign(Gssctxt *ctx, gss_buffer_t buffer, gss_buffer_t hash) +@@ -255,6 +466,19 @@ return (ctx->major); } @@ -718,7 +680,7 @@ index d56257b4..763a63ff 100644 void ssh_gssapi_buildmic(struct sshbuf *b, const char *user, const char *service, const char *context, const struct sshbuf *session_id) -@@ -273,11 +500,16 @@ ssh_gssapi_buildmic(struct sshbuf *b, const char *user, const char *service, +@@ -271,11 +495,16 @@ } int @@ -735,8 +697,8 @@ index d56257b4..763a63ff 100644 + ctx = &intctx; /* RFC 4462 says we MUST NOT do SPNEGO */ - if (oid->length == spnego_oid.length && -@@ -287,6 +519,10 @@ ssh_gssapi_check_mechanism(Gssctxt **ctx, gss_OID oid, const char *host) + if (oid->length == spnego_oid.length && +@@ -285,6 +514,10 @@ ssh_gssapi_build_ctx(ctx); ssh_gssapi_set_oid(*ctx, oid); major = ssh_gssapi_import_name(*ctx, host); @@ -745,13 +707,13 @@ index d56257b4..763a63ff 100644 + major = ssh_gssapi_client_identity(*ctx, client); + 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); -@@ -296,10 +532,66 @@ ssh_gssapi_check_mechanism(Gssctxt **ctx, gss_OID oid, const char *host) +@@ -294,10 +527,66 @@ GSS_C_NO_BUFFER); } -- if (GSS_ERROR(major)) +- if (GSS_ERROR(major)) + if (GSS_ERROR(major) || intctx != NULL) ssh_gssapi_delete_ctx(ctx); @@ -815,150 +777,10 @@ index d56257b4..763a63ff 100644 +} + #endif /* GSSAPI */ -diff --git a/gss-serv-krb5.c b/gss-serv-krb5.c -index a151bc1e..8d2b677f 100644 ---- a/gss-serv-krb5.c -+++ b/gss-serv-krb5.c -@@ -1,7 +1,7 @@ - /* $OpenBSD: gss-serv-krb5.c,v 1.9 2018/07/09 21:37:55 markus Exp $ */ - - /* -- * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved. -+ * Copyright (c) 2001-2007 Simon Wilkinson. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions -@@ -120,7 +120,7 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_client *client) - krb5_error_code problem; - krb5_principal princ; - OM_uint32 maj_status, min_status; -- int len; -+ const char *new_ccname, *new_cctype; - const char *errmsg; - - if (client->creds == NULL) { -@@ -180,11 +180,26 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_client *client) - return; - } - -- client->store.filename = xstrdup(krb5_cc_get_name(krb_context, ccache)); -+ new_cctype = krb5_cc_get_type(krb_context, ccache); -+ new_ccname = krb5_cc_get_name(krb_context, ccache); -+ - client->store.envvar = "KRB5CCNAME"; -- len = strlen(client->store.filename) + 6; -- client->store.envval = xmalloc(len); -- snprintf(client->store.envval, len, "FILE:%s", client->store.filename); -+#ifdef USE_CCAPI -+ xasprintf(&client->store.envval, "API:%s", new_ccname); -+ client->store.filename = NULL; -+#else -+ if (new_ccname[0] == ':') -+ new_ccname++; -+ xasprintf(&client->store.envval, "%s:%s", new_cctype, new_ccname); -+ if (strcmp(new_cctype, "DIR") == 0) { -+ char *p; -+ p = strrchr(client->store.envval, '/'); -+ if (p) -+ *p = '\0'; -+ } -+ if ((strcmp(new_cctype, "FILE") == 0) || (strcmp(new_cctype, "DIR") == 0)) -+ client->store.filename = xstrdup(new_ccname); -+#endif - - #ifdef USE_PAM - if (options.use_pam) -@@ -193,9 +208,76 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_client *client) - - krb5_cc_close(krb_context, ccache); - -+ client->store.data = krb_context; -+ - return; - } - -+int -+ssh_gssapi_krb5_updatecreds(ssh_gssapi_ccache *store, -+ ssh_gssapi_client *client) -+{ -+ krb5_ccache ccache = NULL; -+ krb5_principal principal = NULL; -+ char *name = NULL; -+ krb5_error_code problem; -+ OM_uint32 maj_status, min_status; -+ -+ if ((problem = krb5_cc_resolve(krb_context, store->envval, &ccache))) { -+ logit("krb5_cc_resolve(): %.100s", -+ krb5_get_err_text(krb_context, problem)); -+ return 0; -+ } -+ -+ /* Find out who the principal in this cache is */ -+ if ((problem = krb5_cc_get_principal(krb_context, ccache, -+ &principal))) { -+ logit("krb5_cc_get_principal(): %.100s", -+ krb5_get_err_text(krb_context, problem)); -+ krb5_cc_close(krb_context, ccache); -+ return 0; -+ } -+ -+ if ((problem = krb5_unparse_name(krb_context, principal, &name))) { -+ logit("krb5_unparse_name(): %.100s", -+ krb5_get_err_text(krb_context, problem)); -+ krb5_free_principal(krb_context, principal); -+ krb5_cc_close(krb_context, ccache); -+ return 0; -+ } -+ -+ -+ if (strcmp(name,client->exportedname.value)!=0) { -+ debug("Name in local credentials cache differs. Not storing"); -+ krb5_free_principal(krb_context, principal); -+ krb5_cc_close(krb_context, ccache); -+ krb5_free_unparsed_name(krb_context, name); -+ return 0; -+ } -+ krb5_free_unparsed_name(krb_context, name); -+ -+ /* Name matches, so lets get on with it! */ -+ -+ if ((problem = krb5_cc_initialize(krb_context, ccache, principal))) { -+ logit("krb5_cc_initialize(): %.100s", -+ krb5_get_err_text(krb_context, problem)); -+ krb5_free_principal(krb_context, principal); -+ krb5_cc_close(krb_context, ccache); -+ return 0; -+ } -+ -+ krb5_free_principal(krb_context, principal); -+ -+ if ((maj_status = gss_krb5_copy_ccache(&min_status, client->creds, -+ ccache))) { -+ logit("gss_krb5_copy_ccache() failed. Sorry!"); -+ krb5_cc_close(krb_context, ccache); -+ return 0; -+ } -+ -+ return 1; -+} -+ - ssh_gssapi_mech gssapi_kerberos_mech = { - "toWM5Slw5Ew8Mqkay+al2g==", - "Kerberos", -@@ -203,7 +285,8 @@ ssh_gssapi_mech gssapi_kerberos_mech = { - NULL, - &ssh_gssapi_krb5_userok, - NULL, -- &ssh_gssapi_krb5_storecreds -+ &ssh_gssapi_krb5_storecreds, -+ &ssh_gssapi_krb5_updatecreds - }; - - #endif /* KRB5 */ -diff --git a/gss-serv.c b/gss-serv.c -index ab3a15f0..6ce56e92 100644 ---- a/gss-serv.c -+++ b/gss-serv.c + +diff -Naur a/gss-serv.c b/gss-serv.c +--- a/gss-serv.c 2023-12-18 20:59:50.000000000 +0600 ++++ b/gss-serv.c 2024-03-21 19:18:48.328717471 +0600 @@ -1,7 +1,7 @@ /* $OpenBSD: gss-serv.c,v 1.32 2020/03/13 03:17:07 djm Exp $ */ @@ -991,11 +813,10 @@ index ab3a15f0..6ce56e92 100644 #ifdef KRB5 extern ssh_gssapi_mech gssapi_kerberos_mech; -@@ -140,6 +142,29 @@ ssh_gssapi_server_ctx(Gssctxt **ctx, gss_OID oid) - return (ssh_gssapi_acquire_cred(*ctx)); +@@ -141,6 +143,29 @@ } -+/* Unprivileged */ + /* Unprivileged */ +char * +ssh_gssapi_server_mechanisms(void) { + if (supported_oids == NULL) @@ -1018,10 +839,11 @@ index ab3a15f0..6ce56e92 100644 + return (res); +} + - /* Unprivileged */ ++/* Unprivileged */ void ssh_gssapi_supported_oids(gss_OID_set *oidset) -@@ -150,7 +175,9 @@ ssh_gssapi_supported_oids(gss_OID_set *oidset) + { +@@ -150,7 +175,9 @@ gss_OID_set supported; gss_create_empty_oid_set(&min_status, oidset); @@ -1032,7 +854,7 @@ index ab3a15f0..6ce56e92 100644 while (supported_mechs[i]->name != NULL) { if (GSS_ERROR(gss_test_oid_set_member(&min_status, -@@ -276,8 +303,48 @@ OM_uint32 +@@ -276,8 +303,48 @@ ssh_gssapi_getclient(Gssctxt *ctx, ssh_gssapi_client *client) { int i = 0; @@ -1054,8 +876,7 @@ index ab3a15f0..6ce56e92 100644 + ssh_gssapi_error(ctx); + return (ctx->major); + } - -- gss_buffer_desc ename; ++ + ctx->major = gss_compare_name(&ctx->minor, client->name, + new_name, &equal); + @@ -1068,7 +889,8 @@ index ab3a15f0..6ce56e92 100644 + debug("Rekeyed credentials have different name"); + return GSS_S_COMPLETE; + } -+ + +- gss_buffer_desc ename; + debug("Marking rekeyed credentials for export"); + + gss_release_name(&ctx->minor, &client->name); @@ -1082,7 +904,7 @@ index ab3a15f0..6ce56e92 100644 client->mech = NULL; -@@ -292,6 +359,13 @@ ssh_gssapi_getclient(Gssctxt *ctx, ssh_gssapi_client *client) +@@ -292,6 +359,13 @@ if (client->mech == NULL) return GSS_S_FAILURE; @@ -1096,7 +918,7 @@ index ab3a15f0..6ce56e92 100644 if ((ctx->major = gss_display_name(&ctx->minor, ctx->client, &client->displayname, NULL))) { ssh_gssapi_error(ctx); -@@ -309,6 +383,8 @@ ssh_gssapi_getclient(Gssctxt *ctx, ssh_gssapi_client *client) +@@ -309,6 +383,8 @@ return (ctx->major); } @@ -1105,7 +927,7 @@ index ab3a15f0..6ce56e92 100644 /* We can't copy this structure, so we just move the pointer to it */ client->creds = ctx->client_creds; ctx->client_creds = GSS_C_NO_CREDENTIAL; -@@ -319,11 +395,20 @@ ssh_gssapi_getclient(Gssctxt *ctx, ssh_gssapi_client *client) +@@ -319,11 +395,20 @@ void ssh_gssapi_cleanup_creds(void) { @@ -1131,7 +953,7 @@ index ab3a15f0..6ce56e92 100644 } } -@@ -356,19 +441,23 @@ ssh_gssapi_do_child(char ***envp, u_int *envsizep) +@@ -356,19 +441,23 @@ /* Privileged */ int @@ -1158,7 +980,7 @@ index ab3a15f0..6ce56e92 100644 /* Destroy delegated credentials if userok fails */ gss_release_buffer(&lmin, &gssapi_client.displayname); gss_release_buffer(&lmin, &gssapi_client.exportedname); -@@ -382,14 +471,90 @@ ssh_gssapi_userok(char *user) +@@ -382,14 +471,90 @@ return (0); } @@ -1255,11 +1077,149 @@ index ab3a15f0..6ce56e92 100644 } /* Privileged */ -diff --git a/kex.c b/kex.c -index ce85f043..574c7609 100644 ---- a/kex.c -+++ b/kex.c -@@ -57,6 +57,10 @@ +diff -Naur a/gss-serv-krb5.c b/gss-serv-krb5.c +--- a/gss-serv-krb5.c 2023-12-18 20:59:50.000000000 +0600 ++++ b/gss-serv-krb5.c 2024-03-21 19:09:10.453380019 +0600 +@@ -1,7 +1,7 @@ + /* $OpenBSD: gss-serv-krb5.c,v 1.9 2018/07/09 21:37:55 markus Exp $ */ + + /* +- * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved. ++ * Copyright (c) 2001-2007 Simon Wilkinson. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions +@@ -120,7 +120,7 @@ + krb5_error_code problem; + krb5_principal princ; + OM_uint32 maj_status, min_status; +- int len; ++ const char *new_ccname, *new_cctype; + const char *errmsg; + + if (client->creds == NULL) { +@@ -180,11 +180,26 @@ + return; + } + +- client->store.filename = xstrdup(krb5_cc_get_name(krb_context, ccache)); ++ new_cctype = krb5_cc_get_type(krb_context, ccache); ++ new_ccname = krb5_cc_get_name(krb_context, ccache); ++ + client->store.envvar = "KRB5CCNAME"; +- len = strlen(client->store.filename) + 6; +- client->store.envval = xmalloc(len); +- snprintf(client->store.envval, len, "FILE:%s", client->store.filename); ++#ifdef USE_CCAPI ++ xasprintf(&client->store.envval, "API:%s", new_ccname); ++ client->store.filename = NULL; ++#else ++ if (new_ccname[0] == ':') ++ new_ccname++; ++ xasprintf(&client->store.envval, "%s:%s", new_cctype, new_ccname); ++ if (strcmp(new_cctype, "DIR") == 0) { ++ char *p; ++ p = strrchr(client->store.envval, '/'); ++ if (p) ++ *p = '\0'; ++ } ++ if ((strcmp(new_cctype, "FILE") == 0) || (strcmp(new_cctype, "DIR") == 0)) ++ client->store.filename = xstrdup(new_ccname); ++#endif + + #ifdef USE_PAM + if (options.use_pam) +@@ -193,9 +208,76 @@ + + krb5_cc_close(krb_context, ccache); + ++ client->store.data = krb_context; ++ + return; + } + ++int ++ssh_gssapi_krb5_updatecreds(ssh_gssapi_ccache *store, ++ ssh_gssapi_client *client) ++{ ++ krb5_ccache ccache = NULL; ++ krb5_principal principal = NULL; ++ char *name = NULL; ++ krb5_error_code problem; ++ OM_uint32 maj_status, min_status; ++ ++ if ((problem = krb5_cc_resolve(krb_context, store->envval, &ccache))) { ++ logit("krb5_cc_resolve(): %.100s", ++ krb5_get_err_text(krb_context, problem)); ++ return 0; ++ } ++ ++ /* Find out who the principal in this cache is */ ++ if ((problem = krb5_cc_get_principal(krb_context, ccache, ++ &principal))) { ++ logit("krb5_cc_get_principal(): %.100s", ++ krb5_get_err_text(krb_context, problem)); ++ krb5_cc_close(krb_context, ccache); ++ return 0; ++ } ++ ++ if ((problem = krb5_unparse_name(krb_context, principal, &name))) { ++ logit("krb5_unparse_name(): %.100s", ++ krb5_get_err_text(krb_context, problem)); ++ krb5_free_principal(krb_context, principal); ++ krb5_cc_close(krb_context, ccache); ++ return 0; ++ } ++ ++ ++ if (strcmp(name,client->exportedname.value)!=0) { ++ debug("Name in local credentials cache differs. Not storing"); ++ krb5_free_principal(krb_context, principal); ++ krb5_cc_close(krb_context, ccache); ++ krb5_free_unparsed_name(krb_context, name); ++ return 0; ++ } ++ krb5_free_unparsed_name(krb_context, name); ++ ++ /* Name matches, so lets get on with it! */ ++ ++ if ((problem = krb5_cc_initialize(krb_context, ccache, principal))) { ++ logit("krb5_cc_initialize(): %.100s", ++ krb5_get_err_text(krb_context, problem)); ++ krb5_free_principal(krb_context, principal); ++ krb5_cc_close(krb_context, ccache); ++ return 0; ++ } ++ ++ krb5_free_principal(krb_context, principal); ++ ++ if ((maj_status = gss_krb5_copy_ccache(&min_status, client->creds, ++ ccache))) { ++ logit("gss_krb5_copy_ccache() failed. Sorry!"); ++ krb5_cc_close(krb_context, ccache); ++ return 0; ++ } ++ ++ return 1; ++} ++ + ssh_gssapi_mech gssapi_kerberos_mech = { + "toWM5Slw5Ew8Mqkay+al2g==", + "Kerberos", +@@ -203,7 +285,8 @@ + NULL, + &ssh_gssapi_krb5_userok, + NULL, +- &ssh_gssapi_krb5_storecreds ++ &ssh_gssapi_krb5_storecreds, ++ &ssh_gssapi_krb5_updatecreds + }; + + #endif /* KRB5 */ +diff -Naur a/kex.c b/kex.c +--- a/kex.c 2023-12-18 20:59:50.000000000 +0600 ++++ b/kex.c 2024-03-21 19:54:42.020183299 +0600 +@@ -64,6 +64,10 @@ #include "digest.h" #include "xmalloc.h" @@ -1268,12 +1228,14 @@ index ce85f043..574c7609 100644 +#endif + /* prototype */ - static int kex_choose_conf(struct ssh *); + static int kex_choose_conf(struct ssh *, uint32_t seq); static int kex_input_newkeys(int, u_int32_t, struct ssh *); -@@ -115,15 +120,28 @@ static const struct kexalg kexalgs[] = { - #endif /* HAVE_EVP_SHA256 || !WITH_OPENSSL */ +@@ -120,14 +124,28 @@ { NULL, 0, -1, -1}, }; + +-char * +-kex_alg_list(char sep) +static const struct kexalg gss_kexalgs[] = { +#ifdef GSSAPI + { KEX_GSS_GEX_SHA1_ID, KEX_GSS_GEX_SHA1, 0, SSH_DIGEST_SHA1 }, @@ -1287,9 +1249,7 @@ index ce85f043..574c7609 100644 +#endif + { NULL, 0, -1, -1}, +}; - --char * --kex_alg_list(char sep) ++ +static char * +kex_alg_list_internal(char sep, const struct kexalg *algs) { @@ -1302,7 +1262,7 @@ index ce85f043..574c7609 100644 if (ret != NULL) ret[rlen++] = sep; nlen = strlen(k->name); -@@ -138,6 +156,18 @@ kex_alg_list(char sep) +@@ -142,6 +160,18 @@ return ret; } @@ -1321,7 +1281,7 @@ index ce85f043..574c7609 100644 static const struct kexalg * kex_alg_by_name(const char *name) { -@@ -147,6 +177,10 @@ kex_alg_by_name(const char *name) +@@ -151,6 +181,10 @@ if (strcmp(k->name, name) == 0) return k; } @@ -1332,7 +1292,7 @@ index ce85f043..574c7609 100644 return NULL; } -@@ -315,6 +349,29 @@ kex_assemble_names(char **listp, const char *def, const char *all) +@@ -329,6 +363,29 @@ return r; } @@ -1362,7 +1322,7 @@ index ce85f043..574c7609 100644 /* * Fill out a proposal array with dynamically allocated values, which may * be modified as required for compatibility reasons. -@@ -698,6 +755,9 @@ kex_free(struct kex *kex) +@@ -962,6 +1019,9 @@ sshbuf_free(kex->server_version); sshbuf_free(kex->client_pub); sshbuf_free(kex->session_id); @@ -1372,81 +1332,10 @@ index ce85f043..574c7609 100644 sshbuf_free(kex->initial_sig); sshkey_free(kex->initial_hostkey); free(kex->failed_choice); -diff --git a/kex.h b/kex.h -index a5ae6ac0..fe714141 100644 ---- a/kex.h -+++ b/kex.h -@@ -102,6 +102,15 @@ enum kex_exchange { - KEX_ECDH_SHA2, - KEX_C25519_SHA256, - KEX_KEM_SNTRUP761X25519_SHA512, -+#ifdef GSSAPI -+ KEX_GSS_GRP1_SHA1, -+ KEX_GSS_GRP14_SHA1, -+ KEX_GSS_GRP14_SHA256, -+ KEX_GSS_GRP16_SHA512, -+ KEX_GSS_GEX_SHA1, -+ KEX_GSS_NISTP256_SHA256, -+ KEX_GSS_C25519_SHA256, -+#endif - KEX_MAX - }; - -@@ -153,6 +162,12 @@ struct kex { - u_int flags; - int hash_alg; - int ec_nid; -+#ifdef GSSAPI -+ int gss_deleg_creds; -+ int gss_trust_dns; -+ char *gss_host; -+ char *gss_client; -+#endif - char *failed_choice; - int (*verify_host_key)(struct sshkey *, struct ssh *); - struct sshkey *(*load_host_public_key)(int, int, struct ssh *); -@@ -174,8 +189,10 @@ struct kex { - - int kex_names_valid(const char *); - char *kex_alg_list(char); -+char *kex_gss_alg_list(char); - char *kex_names_cat(const char *, const char *); - int kex_assemble_names(char **, const char *, const char *); -+int kex_gss_names_valid(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]); -@@ -202,6 +219,12 @@ int kexgex_client(struct ssh *); - int kexgex_server(struct ssh *); - int kex_gen_client(struct ssh *); - int kex_gen_server(struct ssh *); -+#if defined(GSSAPI) && defined(WITH_OPENSSL) -+int kexgssgex_client(struct ssh *); -+int kexgssgex_server(struct ssh *); -+int kexgss_client(struct ssh *); -+int kexgss_server(struct ssh *); -+#endif - - int kex_dh_keypair(struct kex *); - int kex_dh_enc(struct kex *, const struct sshbuf *, struct sshbuf **, -@@ -234,6 +257,12 @@ int kexgex_hash(int, const struct sshbuf *, const struct sshbuf *, - const BIGNUM *, const u_char *, size_t, - u_char *, size_t *); - -+int kex_gen_hash(int hash_alg, const struct sshbuf *client_version, -+ const struct sshbuf *server_version, const struct sshbuf *client_kexinit, -+ const struct sshbuf *server_kexinit, const struct sshbuf *server_host_key_blob, -+ const struct sshbuf *client_pub, const struct sshbuf *server_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))); -diff --git a/kexdh.c b/kexdh.c -index 67133e33..edaa4676 100644 ---- a/kexdh.c -+++ b/kexdh.c -@@ -48,13 +48,23 @@ kex_dh_keygen(struct kex *kex) +diff -Naur a/kexdh.c b/kexdh.c +--- a/kexdh.c 2023-12-18 20:59:50.000000000 +0600 ++++ b/kexdh.c 2024-03-21 19:59:22.298424097 +0600 +@@ -49,13 +49,23 @@ { switch (kex->kex_type) { case KEX_DH_GRP1_SHA1: @@ -1470,10 +1359,9 @@ index 67133e33..edaa4676 100644 kex->dh = dh_new_group16(); break; case KEX_DH_GRP18_SHA512: -diff --git a/kexgen.c b/kexgen.c -index 69348b96..c0e8c2f4 100644 ---- a/kexgen.c -+++ b/kexgen.c +diff -Naur a/kexgen.c b/kexgen.c +--- a/kexgen.c 2023-12-18 20:59:50.000000000 +0600 ++++ b/kexgen.c 2024-03-21 19:59:58.746195328 +0600 @@ -44,7 +44,7 @@ static int input_kex_gen_init(int, u_int32_t, struct ssh *); static int input_kex_gen_reply(int type, u_int32_t seq, struct ssh *ssh); @@ -1483,12 +1371,10 @@ index 69348b96..c0e8c2f4 100644 kex_gen_hash( int hash_alg, const struct sshbuf *client_version, -diff --git a/kexgssc.c b/kexgssc.c -new file mode 100644 -index 00000000..f6e1405e ---- /dev/null -+++ b/kexgssc.c -@@ -0,0 +1,600 @@ +diff -Naur a/kexgssc.c b/kexgssc.c +--- a/kexgssc.c 1970-01-01 06:00:00.000000000 +0600 ++++ b/kexgssc.c 2024-03-21 20:01:14.965716927 +0600 +@@ -0,0 +1,612 @@ +/* + * Copyright (c) 2001-2009 Simon Wilkinson. All rights reserved. + * @@ -1589,8 +1475,10 @@ index 00000000..f6e1405e + default: + fatal_f("Unexpected KEX type %d", kex->kex_type); + } -+ if (r != 0) ++ if (r != 0) { ++ ssh_gssapi_delete_ctx(&ctxt); + return r; ++ } + + token_ptr = GSS_C_NO_BUFFER; + @@ -1653,11 +1541,16 @@ index 00000000..f6e1405e + do { + type = ssh_packet_read(ssh); + if (type == SSH2_MSG_KEXGSS_HOSTKEY) { ++ u_char *tmp = NULL; ++ size_t tmp_len = 0; ++ + debug("Received KEXGSS_HOSTKEY"); + if (server_host_key_blob) + fatal("Server host key received more than once"); -+ if ((r = sshpkt_getb_froms(ssh, &server_host_key_blob)) != 0) ++ if ((r = sshpkt_get_string(ssh, &tmp, &tmp_len)) != 0) + fatal("Failed to read server host key: %s", ssh_err(r)); ++ if ((server_host_key_blob = sshbuf_from(tmp, tmp_len)) == NULL) ++ fatal("sshbuf_from failed"); + } + } while (type == SSH2_MSG_KEXGSS_HOSTKEY); + @@ -1944,11 +1837,16 @@ index 00000000..f6e1405e + do { + type = ssh_packet_read(ssh); + if (type == SSH2_MSG_KEXGSS_HOSTKEY) { ++ u_char *tmp = NULL; ++ size_t tmp_len = 0; ++ + debug("Received KEXGSS_HOSTKEY"); + if (server_host_key_blob) + fatal("Server host key received more than once"); -+ if ((r = sshpkt_getb_froms(ssh, &server_host_key_blob)) != 0) ++ if ((r = sshpkt_get_string(ssh, &tmp, &tmp_len)) != 0) + fatal("sshpkt failed: %s", ssh_err(r)); ++ if ((server_host_key_blob = sshbuf_from(tmp, tmp_len)) == NULL) ++ fatal("sshbuf_from failed"); + } + } while (type == SSH2_MSG_KEXGSS_HOSTKEY); + @@ -2089,12 +1987,10 @@ index 00000000..f6e1405e +} + +#endif /* defined(GSSAPI) && defined(WITH_OPENSSL) */ -diff --git a/kexgsss.c b/kexgsss.c -new file mode 100644 -index 00000000..60bc02de ---- /dev/null -+++ b/kexgsss.c -@@ -0,0 +1,474 @@ +diff -Naur a/kexgsss.c b/kexgsss.c +--- a/kexgsss.c 1970-01-01 06:00:00.000000000 +0600 ++++ b/kexgsss.c 2024-03-21 20:01:57.205451804 +0600 +@@ -0,0 +1,482 @@ +/* + * Copyright (c) 2001-2009 Simon Wilkinson. All rights reserved. + * @@ -2161,7 +2057,7 @@ index 00000000..60bc02de + */ + + OM_uint32 ret_flags = 0; -+ gss_buffer_desc gssbuf, recv_tok, msg_tok; ++ gss_buffer_desc gssbuf = {0, NULL}, recv_tok, msg_tok; + gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER; + Gssctxt *ctxt = NULL; + struct sshbuf *shared_secret = NULL; @@ -2201,7 +2097,7 @@ index 00000000..60bc02de + type = ssh_packet_read(ssh); + switch(type) { + case SSH2_MSG_KEXGSS_INIT: -+ if (client_pubkey != NULL) ++ if (gssbuf.value != NULL) + fatal("Received KEXGSS_INIT after initialising"); + if ((r = ssh_gssapi_sshpkt_get_buffer_desc(ssh, + &recv_tok)) != 0 || @@ -2232,6 +2128,31 @@ index 00000000..60bc02de + goto out; + + /* Send SSH_MSG_KEXGSS_HOSTKEY here, if we want */ ++ ++ /* Calculate the hash early so we can free the ++ * client_pubkey, which has reference to the parent ++ * buffer state->incoming_packet ++ */ ++ hashlen = sizeof(hash); ++ if ((r = kex_gen_hash( ++ kex->hash_alg, ++ kex->client_version, ++ kex->server_version, ++ kex->peer, ++ kex->my, ++ empty, ++ client_pubkey, ++ server_pubkey, ++ shared_secret, ++ hash, &hashlen)) != 0) ++ goto out; ++ ++ gssbuf.value = hash; ++ gssbuf.length = hashlen; ++ ++ sshbuf_free(client_pubkey); ++ client_pubkey = NULL; ++ + break; + case SSH2_MSG_KEXGSS_CONTINUE: + if ((r = ssh_gssapi_sshpkt_get_buffer_desc(ssh, @@ -2253,7 +2174,7 @@ index 00000000..60bc02de + if (maj_status != GSS_S_COMPLETE && send_tok.length == 0) + fatal("Zero length token output when incomplete"); + -+ if (client_pubkey == NULL) ++ if (gssbuf.value == NULL) + fatal("No client public key"); + + if (maj_status & GSS_S_CONTINUE_NEEDED) { @@ -2282,23 +2203,6 @@ index 00000000..60bc02de + if (!(ret_flags & GSS_C_INTEG_FLAG)) + fatal("Integrity flag wasn't set"); + -+ hashlen = sizeof(hash); -+ if ((r = kex_gen_hash( -+ kex->hash_alg, -+ kex->client_version, -+ kex->server_version, -+ kex->peer, -+ kex->my, -+ empty, -+ client_pubkey, -+ server_pubkey, -+ shared_secret, -+ hash, &hashlen)) != 0) -+ goto out; -+ -+ gssbuf.value = hash; -+ gssbuf.length = hashlen; -+ + if (GSS_ERROR(PRIVSEP(ssh_gssapi_sign(ctxt, &gssbuf, &msg_tok)))) + fatal("Couldn't get MIC"); + @@ -2569,11 +2473,109 @@ index 00000000..60bc02de + return r; +} +#endif /* defined(GSSAPI) && defined(WITH_OPENSSL) */ -diff --git a/monitor.c b/monitor.c -index 2ce89fe9..ebf76c7f 100644 ---- a/monitor.c -+++ b/monitor.c -@@ -148,6 +148,8 @@ int mm_answer_gss_setup_ctx(struct ssh *, int, struct sshbuf *); +diff -Naur a/kex.h b/kex.h +--- a/kex.h 2023-12-18 20:59:50.000000000 +0600 ++++ b/kex.h 2024-03-21 19:58:01.759929607 +0600 +@@ -102,6 +102,15 @@ + KEX_ECDH_SHA2, + KEX_C25519_SHA256, + KEX_KEM_SNTRUP761X25519_SHA512, ++#ifdef GSSAPI ++ KEX_GSS_GRP1_SHA1, ++ KEX_GSS_GRP14_SHA1, ++ KEX_GSS_GRP14_SHA256, ++ KEX_GSS_GRP16_SHA512, ++ KEX_GSS_GEX_SHA1, ++ KEX_GSS_NISTP256_SHA256, ++ KEX_GSS_C25519_SHA256, ++#endif + KEX_MAX + }; + +@@ -164,6 +173,12 @@ + u_int flags; + int hash_alg; + int ec_nid; ++#ifdef GSSAPI ++ int gss_deleg_creds; ++ int gss_trust_dns; ++ char *gss_host; ++ char *gss_client; ++#endif + char *failed_choice; + int (*verify_host_key)(struct sshkey *, struct ssh *); + struct sshkey *(*load_host_public_key)(int, int, struct ssh *); +@@ -185,8 +200,10 @@ + + int kex_names_valid(const char *); + char *kex_alg_list(char); ++char *kex_gss_alg_list(char); + char *kex_names_cat(const char *, const char *); + int kex_assemble_names(char **, const char *, const char *); ++int kex_gss_names_valid(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]); +@@ -219,6 +236,12 @@ + int kexgex_server(struct ssh *); + int kex_gen_client(struct ssh *); + int kex_gen_server(struct ssh *); ++#if defined(GSSAPI) && defined(WITH_OPENSSL) ++int kexgssgex_client(struct ssh *); ++int kexgssgex_server(struct ssh *); ++int kexgss_client(struct ssh *); ++int kexgss_server(struct ssh *); ++#endif + + int kex_dh_keypair(struct kex *); + int kex_dh_enc(struct kex *, const struct sshbuf *, struct sshbuf **, +@@ -251,6 +274,13 @@ + const BIGNUM *, const u_char *, size_t, + u_char *, size_t *); + ++int kex_gen_hash(int hash_alg, const struct sshbuf *client_version, ++ const struct sshbuf *server_version, const struct sshbuf *client_kexinit, ++ const struct sshbuf *server_kexinit, const struct sshbuf *server_host_key_blob, ++ const struct sshbuf *client_pub, const struct sshbuf *server_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))); +diff -Naur a/Makefile.in b/Makefile.in +--- a/Makefile.in 2024-03-21 18:44:47.996756508 +0600 ++++ b/Makefile.in 2024-03-21 18:46:34.424070763 +0600 +@@ -112,6 +112,7 @@ + kex.o kexdh.o kexgex.o kexecdh.o kexc25519.o \ + kexgexc.o kexgexs.o \ + kexsntrup761x25519.o sntrup761.o kexgen.o \ ++ kexgssc.o \ + sftp-realpath.o platform-pledge.o platform-tracing.o platform-misc.o \ + sshbuf-io.o + +@@ -128,7 +129,7 @@ + auth-bsdauth.o auth2-hostbased.o auth2-kbdint.o \ + auth2-none.o auth2-passwd.o auth2-pubkey.o auth2-pubkeyfile.o \ + monitor.o monitor_wrap.o auth-krb5.o \ +- auth2-gss.o gss-serv.o gss-serv-krb5.o \ ++ auth2-gss.o gss-serv.o gss-serv-krb5.o kexgsss.o \ + loginrec.o auth-pam.o auth-shadow.o auth-sia.o \ + srclimit.o sftp-server.o sftp-common.o \ + sandbox-null.o sandbox-rlimit.o sandbox-systrace.o sandbox-darwin.o \ +@@ -517,7 +518,7 @@ + ln -s `cd $(srcdir) && pwd`/regress/Makefile `pwd`/regress/Makefile + + REGRESSLIBS=libssh.a $(LIBCOMPAT) +-TESTLIBS=$(LIBS) $(CHANNELLIBS) ++TESTLIBS=$(LIBS) $(CHANNELLIBS) $(GSSLIBS) + + regress/modpipe$(EXEEXT): $(srcdir)/regress/modpipe.c $(REGRESSLIBS) + $(CC) $(CFLAGS) $(CPPFLAGS) -o $@ $(srcdir)/regress/modpipe.c \ +diff -Naur a/monitor.c b/monitor.c +--- a/monitor.c 2024-03-21 18:44:47.990756547 +0600 ++++ b/monitor.c 2024-03-21 20:08:19.629051473 +0600 +@@ -145,6 +145,8 @@ 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 *); @@ -2582,11 +2584,11 @@ index 2ce89fe9..ebf76c7f 100644 #endif #ifdef SSH_AUDIT_EVENTS -@@ -220,11 +222,18 @@ struct mon_table mon_dispatch_proto20[] = { +@@ -220,11 +222,18 @@ {MONITOR_REQ_GSSSTEP, 0, mm_answer_gss_accept_ctx}, {MONITOR_REQ_GSSUSEROK, MON_ONCE|MON_AUTHDECIDE, mm_answer_gss_userok}, {MONITOR_REQ_GSSCHECKMIC, MON_ONCE, mm_answer_gss_checkmic}, -+ {MONITOR_REQ_GSSSIGN, MON_ONCE, mm_answer_gss_sign}, ++ {MONITOR_REQ_GSSSIGN, MON_ONCE, mm_answer_gss_sign}, #endif {0, 0, NULL} }; @@ -2601,7 +2603,7 @@ index 2ce89fe9..ebf76c7f 100644 #ifdef WITH_OPENSSL {MONITOR_REQ_MODULI, 0, mm_answer_moduli}, #endif -@@ -293,6 +302,10 @@ monitor_child_preauth(struct ssh *ssh, struct monitor *pmonitor) +@@ -293,6 +302,10 @@ /* Permit requests for moduli and signatures */ monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1); monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1); @@ -2612,7 +2614,7 @@ index 2ce89fe9..ebf76c7f 100644 /* The first few requests do not require asynchronous access */ while (!authenticated) { -@@ -376,8 +376,15 @@ monitor_child_preauth(struct ssh *ssh, s +@@ -341,8 +354,15 @@ if (ent->flags & (MON_AUTHDECIDE|MON_ALOG)) { auth_log(ssh, authenticated, partial, auth_method, auth_submethod); @@ -2629,7 +2631,7 @@ index 2ce89fe9..ebf76c7f 100644 if (authenticated || partial) { auth2_update_session_info(authctxt, auth_method, auth_submethod); -@@ -406,6 +419,10 @@ monitor_child_postauth(struct ssh *ssh, struct monitor *pmonitor) +@@ -409,6 +429,10 @@ monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1); monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1); monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1); @@ -2640,7 +2642,7 @@ index 2ce89fe9..ebf76c7f 100644 if (auth_opts->permit_pty_flag) { monitor_permit(mon_dispatch, MONITOR_REQ_PTY, 1); -@@ -1713,6 +1730,17 @@ monitor_apply_keystate(struct ssh *ssh, struct monitor *pmonitor) +@@ -1778,6 +1802,17 @@ # ifdef OPENSSL_HAS_ECC kex->kex[KEX_ECDH_SHA2] = kex_gen_server; # endif @@ -2658,7 +2660,7 @@ index 2ce89fe9..ebf76c7f 100644 #endif /* WITH_OPENSSL */ kex->kex[KEX_C25519_SHA256] = kex_gen_server; kex->kex[KEX_KEM_SNTRUP761X25519_SHA512] = kex_gen_server; -@@ -1806,8 +1834,8 @@ mm_answer_gss_setup_ctx(struct ssh *ssh, int sock, struct sshbuf *m) +@@ -1870,8 +1905,8 @@ u_char *p; int r; @@ -2669,18 +2671,7 @@ index 2ce89fe9..ebf76c7f 100644 if ((r = sshbuf_get_string(m, &p, &len)) != 0) fatal_fr(r, "parse"); -@@ -1839,8 +1867,8 @@ mm_answer_gss_accept_ctx(struct ssh *ssh, int sock, struct sshbuf *m) - OM_uint32 flags = 0; /* GSI needs this */ - int r; - -- if (!options.gss_authentication) -- fatal_f("GSSAPI authentication not enabled"); -+ if (!options.gss_authentication && !options.gss_keyex) -+ fatal_f("GSSAPI not enabled"); - - if ((r = ssh_gssapi_get_buffer_desc(m, &in)) != 0) - fatal_fr(r, "ssh_gssapi_get_buffer_desc"); -@@ -1860,6 +1888,7 @@ mm_answer_gss_accept_ctx(struct ssh *ssh, int sock, struct sshbuf *m) +@@ -1924,6 +1959,7 @@ monitor_permit(mon_dispatch, MONITOR_REQ_GSSSTEP, 0); monitor_permit(mon_dispatch, MONITOR_REQ_GSSUSEROK, 1); monitor_permit(mon_dispatch, MONITOR_REQ_GSSCHECKMIC, 1); @@ -2688,7 +2679,7 @@ index 2ce89fe9..ebf76c7f 100644 } return (0); } -@@ -1871,8 +1900,8 @@ mm_answer_gss_checkmic(struct ssh *ssh, int sock, struct sshbuf *m) +@@ -1935,8 +1971,8 @@ OM_uint32 ret; int r; @@ -2699,7 +2690,7 @@ index 2ce89fe9..ebf76c7f 100644 if ((r = ssh_gssapi_get_buffer_desc(m, &gssbuf)) != 0 || (r = ssh_gssapi_get_buffer_desc(m, &mic)) != 0) -@@ -1898,13 +1927,17 @@ mm_answer_gss_checkmic(struct ssh *ssh, int sock, struct sshbuf *m) +@@ -1962,13 +1998,17 @@ int mm_answer_gss_userok(struct ssh *ssh, int sock, struct sshbuf *m) { @@ -2721,7 +2712,7 @@ index 2ce89fe9..ebf76c7f 100644 sshbuf_reset(m); if ((r = sshbuf_put_u32(m, authenticated)) != 0) -@@ -1913,7 +1946,11 @@ mm_answer_gss_userok(struct ssh *ssh, int sock, struct sshbuf *m) +@@ -1977,7 +2017,11 @@ debug3_f("sending result %d", authenticated); mm_request_send(sock, MONITOR_ANS_GSSUSEROK, m); @@ -2734,7 +2725,7 @@ index 2ce89fe9..ebf76c7f 100644 if ((displayname = ssh_gssapi_displayname()) != NULL) auth2_record_info(authctxt, "%s", displayname); -@@ -1921,5 +1958,84 @@ mm_answer_gss_userok(struct ssh *ssh, int sock, struct sshbuf *m) +@@ -1985,5 +2029,84 @@ /* Monitor loop will terminate if authenticated */ return (authenticated); } @@ -2819,11 +2810,10 @@ index 2ce89fe9..ebf76c7f 100644 + #endif /* GSSAPI */ -diff --git a/monitor.h b/monitor.h -index 683e5e07..2b1a2d59 100644 ---- a/monitor.h -+++ b/monitor.h -@@ -63,6 +63,8 @@ enum monitor_reqtype { +diff -Naur a/monitor.h b/monitor.h +--- a/monitor.h 2024-03-21 18:44:47.990756547 +0600 ++++ b/monitor.h 2024-03-21 20:09:09.321739571 +0600 +@@ -67,6 +67,8 @@ MONITOR_REQ_PAM_FREE_CTX = 110, MONITOR_ANS_PAM_FREE_CTX = 111, MONITOR_REQ_AUDIT_EVENT = 112, MONITOR_REQ_AUDIT_COMMAND = 113, @@ -2832,11 +2822,10 @@ index 683e5e07..2b1a2d59 100644 }; struct ssh; -diff --git a/monitor_wrap.c b/monitor_wrap.c -index 001a8fa1..6edb509a 100644 ---- a/monitor_wrap.c -+++ b/monitor_wrap.c -@@ -993,13 +993,15 @@ mm_ssh_gssapi_checkmic(Gssctxt *ctx, gss_buffer_t gssbuf, gss_buffer_t gssmic) +diff -Naur a/monitor_wrap.c b/monitor_wrap.c +--- a/monitor_wrap.c 2024-03-21 18:44:47.990756547 +0600 ++++ b/monitor_wrap.c 2024-03-21 20:10:27.703247599 +0600 +@@ -1019,13 +1019,15 @@ } int @@ -2853,7 +2842,7 @@ index 001a8fa1..6edb509a 100644 mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSUSEROK, m); mm_request_receive_expect(pmonitor->m_recvfd, -@@ -1012,4 +1014,57 @@ mm_ssh_gssapi_userok(char *user) +@@ -1038,4 +1040,57 @@ debug3_f("user %sauthenticated", authenticated ? "" : "not "); return (authenticated); } @@ -2911,11 +2900,10 @@ index 001a8fa1..6edb509a 100644 +} + #endif /* GSSAPI */ -diff --git a/monitor_wrap.h b/monitor_wrap.h -index 23ab096a..485590c1 100644 ---- a/monitor_wrap.h -+++ b/monitor_wrap.h -@@ -64,8 +64,10 @@ int mm_sshkey_verify(const struct sshkey *, const u_char *, size_t, +diff -Naur a/monitor_wrap.h b/monitor_wrap.h +--- a/monitor_wrap.h 2024-03-21 18:44:47.990756547 +0600 ++++ b/monitor_wrap.h 2024-03-21 20:11:01.063038283 +0600 +@@ -68,8 +68,10 @@ OM_uint32 mm_ssh_gssapi_server_ctx(Gssctxt **, gss_OID); OM_uint32 mm_ssh_gssapi_accept_ctx(Gssctxt *, gss_buffer_desc *, gss_buffer_desc *, OM_uint32 *); @@ -2927,10 +2915,54 @@ index 23ab096a..485590c1 100644 #endif #ifdef USE_PAM -diff -up a/readconf.c.gsskex b/readconf.c ---- a/readconf.c.gsskex 2021-08-20 06:03:49.000000000 +0200 -+++ b/readconf.c 2021-08-27 12:25:42.556421509 +0200 -@@ -67,6 +67,7 @@ +diff -Naur a/packet.c b/packet.c +--- a/packet.c 2023-12-18 20:59:50.000000000 +0600 ++++ b/packet.c 2024-03-21 20:48:08.141071820 +0600 +@@ -1425,6 +1425,29 @@ + return type; + } + ++/* ++ * Waits until a packet has been received, verifies that its type matches ++ * that given, and gives a fatal error and exits if there is a mismatch. ++ */ ++ ++int ++ssh_packet_read_expect(struct ssh *ssh, u_int expected_type) ++{ ++ int r; ++ u_char type; ++ ++ if ((r = ssh_packet_read_seqnr(ssh, &type, NULL)) != 0) ++ return r; ++ if (type != expected_type) { ++ if ((r = sshpkt_disconnect(ssh, ++ "Protocol error: expected packet type %d, got %d", ++ expected_type, type)) != 0) ++ return r; ++ return SSH_ERR_PROTOCOL_ERROR; ++ } ++ return 0; ++} ++ + static int + ssh_packet_read_poll2_mux(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p) + { +diff -Naur a/packet.h b/packet.h +--- a/packet.h 2023-12-18 20:59:50.000000000 +0600 ++++ b/packet.h 2024-03-21 20:47:31.489301769 +0600 +@@ -124,6 +124,7 @@ + int ssh_packet_send2(struct ssh *); + + int ssh_packet_read(struct ssh *); ++int ssh_packet_read_expect(struct ssh *, u_int type); + 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); +diff -Naur a/readconf.c b/readconf.c +--- a/readconf.c 2023-12-18 20:59:50.000000000 +0600 ++++ b/readconf.c 2024-03-21 20:16:25.346003983 +0600 +@@ -70,6 +70,7 @@ #include "uidswap.h" #include "myproposal.h" #include "digest.h" @@ -2938,7 +2970,7 @@ diff -up a/readconf.c.gsskex b/readconf.c /* Format of the configuration file: -@@ -161,6 +162,8 @@ typedef enum { +@@ -164,6 +165,8 @@ oClearAllForwardings, oNoHostAuthenticationForLocalhost, oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout, oAddressFamily, oGssAuthentication, oGssDelegateCreds, @@ -2947,7 +2979,7 @@ diff -up a/readconf.c.gsskex b/readconf.c oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly, oSendEnv, oSetEnv, oControlPath, oControlMaster, oControlPersist, oHashKnownHosts, -@@ -206,10 +209,22 @@ static struct { +@@ -210,10 +213,22 @@ /* Sometimes-unsupported options */ #if defined(GSSAPI) { "gssapiauthentication", oGssAuthentication }, @@ -2970,7 +3002,7 @@ diff -up a/readconf.c.gsskex b/readconf.c #endif #ifdef ENABLE_PKCS11 { "pkcs11provider", oPKCS11Provider }, -@@ -1113,10 +1128,42 @@ parse_time: +@@ -1210,10 +1225,42 @@ intptr = &options->gss_authentication; goto parse_flag; @@ -3013,7 +3045,7 @@ diff -up a/readconf.c.gsskex b/readconf.c case oBatchMode: intptr = &options->batch_mode; goto parse_flag; -@@ -2306,7 +2353,13 @@ initialize_options(Options * options) +@@ -2505,7 +2552,13 @@ options->fwd_opts.streamlocal_bind_unlink = -1; options->pubkey_authentication = -1; options->gss_authentication = -1; @@ -3027,7 +3059,7 @@ diff -up a/readconf.c.gsskex b/readconf.c options->password_authentication = -1; options->kbd_interactive_authentication = -1; options->kbd_interactive_devices = NULL; -@@ -2463,8 +2516,18 @@ fill_default_options(Options * options) +@@ -2668,8 +2721,18 @@ options->pubkey_authentication = SSH_PUBKEY_AUTH_ALL; if (options->gss_authentication == -1) options->gss_authentication = 0; @@ -3046,7 +3078,7 @@ diff -up a/readconf.c.gsskex b/readconf.c if (options->password_authentication == -1) options->password_authentication = 1; if (options->kbd_interactive_authentication == -1) -@@ -3246,7 +3309,14 @@ dump_client_config(Options *o, const cha +@@ -3494,7 +3557,14 @@ dump_cfg_fmtint(oGatewayPorts, o->fwd_opts.gateway_ports); #ifdef GSSAPI dump_cfg_fmtint(oGssAuthentication, o->gss_authentication); @@ -3061,10 +3093,10 @@ diff -up a/readconf.c.gsskex b/readconf.c #endif /* GSSAPI */ dump_cfg_fmtint(oHashKnownHosts, o->hash_known_hosts); dump_cfg_fmtint(oHostbasedAuthentication, o->hostbased_authentication); -diff -up a/readconf.h.gsskex b/readconf.h ---- a/readconf.h.gsskex 2021-08-27 12:05:29.248142431 +0200 -+++ b/readconf.h 2021-08-27 12:22:19.270679852 +0200 -@@ -39,7 +39,13 @@ typedef struct { +diff -Naur a/readconf.h b/readconf.h +--- a/readconf.h 2023-12-18 20:59:50.000000000 +0600 ++++ b/readconf.h 2024-03-21 20:17:09.344727969 +0600 +@@ -40,7 +40,13 @@ int pubkey_authentication; /* Try ssh2 pubkey authentication. */ int hostbased_authentication; /* ssh2's rhosts_rsa */ int gss_authentication; /* Try GSS authentication */ @@ -3078,10 +3110,10 @@ diff -up a/readconf.h.gsskex b/readconf.h int password_authentication; /* Try password * authentication. */ int kbd_interactive_authentication; /* Try keyboard-interactive auth. */ -diff -up a/servconf.c.gsskex b/servconf.c ---- a/servconf.c.gsskex 2021-08-20 06:03:49.000000000 +0200 -+++ b/servconf.c 2021-08-27 12:28:15.887735189 +0200 -@@ -70,6 +70,7 @@ +diff -Naur a/servconf.c b/servconf.c +--- a/servconf.c 2023-12-18 20:59:50.000000000 +0600 ++++ b/servconf.c 2024-03-21 20:21:54.602938480 +0600 +@@ -68,6 +68,7 @@ #include "auth.h" #include "myproposal.h" #include "digest.h" @@ -3089,7 +3121,7 @@ diff -up a/servconf.c.gsskex b/servconf.c static void add_listen_addr(ServerOptions *, const char *, const char *, int); -@@ -136,8 +137,11 @@ initialize_server_options(ServerOptions +@@ -134,8 +135,11 @@ options->kerberos_ticket_cleanup = -1; options->kerberos_get_afs_token = -1; options->gss_authentication=-1; @@ -3101,7 +3133,7 @@ diff -up a/servconf.c.gsskex b/servconf.c options->password_authentication = -1; options->kbd_interactive_authentication = -1; options->permit_empty_passwd = -1; -@@ -356,10 +360,18 @@ fill_default_server_options(ServerOption +@@ -358,10 +362,18 @@ options->kerberos_get_afs_token = 0; if (options->gss_authentication == -1) options->gss_authentication = 0; @@ -3120,7 +3152,7 @@ diff -up a/servconf.c.gsskex b/servconf.c if (options->password_authentication == -1) options->password_authentication = 1; if (options->kbd_interactive_authentication == -1) -@@ -506,6 +518,7 @@ typedef enum { +@@ -518,6 +530,7 @@ sHostKeyAlgorithms, sPerSourceMaxStartups, sPerSourceNetBlockSize, sClientAliveInterval, sClientAliveCountMax, sAuthorizedKeysFile, sGssAuthentication, sGssCleanupCreds, sGssStrictAcceptor, @@ -3128,7 +3160,7 @@ diff -up a/servconf.c.gsskex b/servconf.c sAcceptEnv, sSetEnv, sPermitTunnel, sMatch, sPermitOpen, sPermitListen, sForceCommand, sChrootDirectory, sUsePrivilegeSeparation, sAllowAgentForwarding, -@@ -587,12 +600,22 @@ static struct { +@@ -600,12 +613,22 @@ #ifdef GSSAPI { "gssapiauthentication", sGssAuthentication, SSHCFG_ALL }, { "gssapicleanupcredentials", sGssCleanupCreds, SSHCFG_GLOBAL }, @@ -3151,7 +3183,7 @@ diff -up a/servconf.c.gsskex b/servconf.c { "passwordauthentication", sPasswordAuthentication, SSHCFG_ALL }, { "kbdinteractiveauthentication", sKbdInteractiveAuthentication, SSHCFG_ALL }, { "challengeresponseauthentication", sKbdInteractiveAuthentication, SSHCFG_ALL }, /* alias */ -@@ -1576,6 +1599,10 @@ process_server_config_line_depth(ServerO +@@ -1616,6 +1639,10 @@ intptr = &options->gss_authentication; goto parse_flag; @@ -3162,7 +3194,7 @@ diff -up a/servconf.c.gsskex b/servconf.c case sGssCleanupCreds: intptr = &options->gss_cleanup_creds; goto parse_flag; -@@ -1584,6 +1611,22 @@ process_server_config_line_depth(ServerO +@@ -1624,6 +1651,22 @@ intptr = &options->gss_strict_acceptor; goto parse_flag; @@ -3185,7 +3217,7 @@ diff -up a/servconf.c.gsskex b/servconf.c case sPasswordAuthentication: intptr = &options->password_authentication; goto parse_flag; -@@ -2892,6 +2935,10 @@ dump_config(ServerOptions *o) +@@ -3058,6 +3101,10 @@ #ifdef GSSAPI dump_cfg_fmtint(sGssAuthentication, o->gss_authentication); dump_cfg_fmtint(sGssCleanupCreds, o->gss_cleanup_creds); @@ -3196,11 +3228,10 @@ diff -up a/servconf.c.gsskex b/servconf.c #endif dump_cfg_fmtint(sPasswordAuthentication, o->password_authentication); dump_cfg_fmtint(sKbdInteractiveAuthentication, -diff --git a/servconf.h b/servconf.h -index 4202a2d0..3f47ea25 100644 ---- a/servconf.h -+++ b/servconf.h -@@ -132,8 +132,11 @@ typedef struct { +diff -Naur a/servconf.h b/servconf.h +--- a/servconf.h 2023-12-18 20:59:50.000000000 +0600 ++++ b/servconf.h 2024-03-21 20:23:14.714435923 +0600 +@@ -139,8 +139,11 @@ int kerberos_get_afs_token; /* If true, try to get AFS token if * authenticated with Kerberos. */ int gss_authentication; /* If true, permit GSSAPI authentication */ @@ -3212,11 +3243,10 @@ index 4202a2d0..3f47ea25 100644 int password_authentication; /* If true, permit password * authentication. */ int kbd_interactive_authentication; /* If true, permit */ -diff --git a/session.c b/session.c -index 8c0e54f7..06a33442 100644 ---- a/session.c -+++ b/session.c -@@ -2678,13 +2678,19 @@ do_cleanup(struct ssh *ssh, Authctxt *authctxt) +diff -Naur a/session.c b/session.c +--- a/session.c 2024-03-21 18:44:47.993756527 +0600 ++++ b/session.c 2024-03-21 20:24:30.736959016 +0600 +@@ -2689,13 +2689,19 @@ #ifdef KRB5 if (options.kerberos_ticket_cleanup && @@ -3238,135 +3268,10 @@ index 8c0e54f7..06a33442 100644 #endif /* remove agent socket */ -diff --git a/ssh-gss.h b/ssh-gss.h -index 36180d07..70dd3665 100644 ---- a/ssh-gss.h -+++ b/ssh-gss.h -@@ -1,6 +1,6 @@ - /* $OpenBSD: ssh-gss.h,v 1.15 2021/01/27 10:05:28 djm Exp $ */ - /* -- * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved. -+ * Copyright (c) 2001-2009 Simon Wilkinson. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions -@@ -61,10 +61,34 @@ - - #define SSH_GSS_OIDTYPE 0x06 - -+#define SSH2_MSG_KEXGSS_INIT 30 -+#define SSH2_MSG_KEXGSS_CONTINUE 31 -+#define SSH2_MSG_KEXGSS_COMPLETE 32 -+#define SSH2_MSG_KEXGSS_HOSTKEY 33 -+#define SSH2_MSG_KEXGSS_ERROR 34 -+#define SSH2_MSG_KEXGSS_GROUPREQ 40 -+#define SSH2_MSG_KEXGSS_GROUP 41 -+#define KEX_GSS_GRP1_SHA1_ID "gss-group1-sha1-" -+#define KEX_GSS_GRP14_SHA1_ID "gss-group14-sha1-" -+#define KEX_GSS_GRP14_SHA256_ID "gss-group14-sha256-" -+#define KEX_GSS_GRP16_SHA512_ID "gss-group16-sha512-" -+#define KEX_GSS_GEX_SHA1_ID "gss-gex-sha1-" -+#define KEX_GSS_NISTP256_SHA256_ID "gss-nistp256-sha256-" -+#define KEX_GSS_C25519_SHA256_ID "gss-curve25519-sha256-" -+ -+#define GSS_KEX_DEFAULT_KEX \ -+ KEX_GSS_GRP14_SHA256_ID "," \ -+ KEX_GSS_GRP16_SHA512_ID "," \ -+ KEX_GSS_NISTP256_SHA256_ID "," \ -+ KEX_GSS_C25519_SHA256_ID "," \ -+ KEX_GSS_GRP14_SHA1_ID "," \ -+ KEX_GSS_GEX_SHA1_ID -+ - typedef struct { - char *filename; - char *envvar; - char *envval; -+ struct passwd *owner; - void *data; - } ssh_gssapi_ccache; - -@@ -72,8 +92,11 @@ typedef struct { - gss_buffer_desc displayname; - gss_buffer_desc exportedname; - gss_cred_id_t creds; -+ gss_name_t name; - struct ssh_gssapi_mech_struct *mech; - ssh_gssapi_ccache store; -+ int used; -+ int updated; - } ssh_gssapi_client; - - typedef struct ssh_gssapi_mech_struct { -@@ -84,6 +107,7 @@ typedef struct ssh_gssapi_mech_struct { - int (*userok) (ssh_gssapi_client *, char *); - int (*localname) (ssh_gssapi_client *, char **); - void (*storecreds) (ssh_gssapi_client *); -+ int (*updatecreds) (ssh_gssapi_ccache *, ssh_gssapi_client *); - } ssh_gssapi_mech; - - typedef struct { -@@ -94,10 +118,11 @@ typedef struct { - gss_OID oid; /* client */ - gss_cred_id_t creds; /* server */ - gss_name_t client; /* server */ -- gss_cred_id_t client_creds; /* server */ -+ gss_cred_id_t client_creds; /* both */ - } Gssctxt; - - extern ssh_gssapi_mech *supported_mechs[]; -+extern Gssctxt *gss_kex_context; - - int ssh_gssapi_check_oid(Gssctxt *, void *, size_t); - void ssh_gssapi_set_oid_data(Gssctxt *, void *, size_t); -@@ -109,6 +134,7 @@ OM_uint32 ssh_gssapi_test_oid_supported(OM_uint32 *, gss_OID, int *); - - struct sshbuf; - int ssh_gssapi_get_buffer_desc(struct sshbuf *, gss_buffer_desc *); -+int ssh_gssapi_sshpkt_get_buffer_desc(struct ssh *, gss_buffer_desc *); - - OM_uint32 ssh_gssapi_import_name(Gssctxt *, const char *); - OM_uint32 ssh_gssapi_init_ctx(Gssctxt *, int, -@@ -123,17 +149,33 @@ void ssh_gssapi_delete_ctx(Gssctxt **); - OM_uint32 ssh_gssapi_sign(Gssctxt *, gss_buffer_t, gss_buffer_t); - void ssh_gssapi_buildmic(struct sshbuf *, const char *, - const char *, const char *, const struct sshbuf *); --int ssh_gssapi_check_mechanism(Gssctxt **, gss_OID, const char *); -+int ssh_gssapi_check_mechanism(Gssctxt **, gss_OID, const char *, const char *); -+OM_uint32 ssh_gssapi_client_identity(Gssctxt *, const char *); -+int ssh_gssapi_credentials_updated(Gssctxt *); - - /* In the server */ -+typedef int ssh_gssapi_check_fn(Gssctxt **, gss_OID, const char *, -+ const char *); -+char *ssh_gssapi_client_mechanisms(const char *, const char *, const char *); -+char *ssh_gssapi_kex_mechs(gss_OID_set, ssh_gssapi_check_fn *, const char *, -+ const char *, const char *); -+gss_OID ssh_gssapi_id_kex(Gssctxt *, char *, int); -+int ssh_gssapi_server_check_mech(Gssctxt **,gss_OID, const char *, -+ const char *); - OM_uint32 ssh_gssapi_server_ctx(Gssctxt **, gss_OID); --int ssh_gssapi_userok(char *name); -+int ssh_gssapi_userok(char *name, struct passwd *, int kex); - OM_uint32 ssh_gssapi_checkmic(Gssctxt *, gss_buffer_t, gss_buffer_t); - void ssh_gssapi_do_child(char ***, u_int *); - void ssh_gssapi_cleanup_creds(void); - void ssh_gssapi_storecreds(void); - const char *ssh_gssapi_displayname(void); - -+char *ssh_gssapi_server_mechanisms(void); -+int ssh_gssapi_oid_table_ok(void); -+ -+int ssh_gssapi_update_creds(ssh_gssapi_ccache *store); -+void ssh_gssapi_rekey_creds(void); -+ - #endif /* GSSAPI */ - - #endif /* _SSH_GSS_H */ -diff --git a/ssh.1 b/ssh.1 -index 60de6087..db5c65bc 100644 ---- a/ssh.1 -+++ b/ssh.1 -@@ -503,7 +503,13 @@ For full details of the options listed below, and their possible values, see +diff -Naur a/ssh.1 b/ssh.1 +--- a/ssh.1 2024-03-21 18:44:48.000756482 +0600 ++++ b/ssh.1 2024-03-21 20:30:14.421803653 +0600 +@@ -536,7 +536,13 @@ .It GatewayPorts .It GlobalKnownHostsFile .It GSSAPIAuthentication @@ -3380,7 +3285,7 @@ index 60de6087..db5c65bc 100644 .It HashKnownHosts .It Host .It HostbasedAcceptedAlgorithms -@@ -579,6 +585,8 @@ flag), +@@ -624,6 +630,8 @@ (supported message integrity codes), .Ar kex (key exchange algorithms), @@ -3388,12 +3293,11 @@ index 60de6087..db5c65bc 100644 +(GSSAPI key exchange algorithms), .Ar key (key types), - .Ar key-cert -diff --git a/ssh.c b/ssh.c -index 15aee569..110cf9c1 100644 ---- a/ssh.c -+++ b/ssh.c -@@ -747,6 +747,8 @@ main(int ac, char **av) + .Ar key-ca-sign +diff -Naur a/ssh.c b/ssh.c +--- a/ssh.c 2023-12-18 20:59:50.000000000 +0600 ++++ b/ssh.c 2024-03-21 20:31:22.128379217 +0600 +@@ -827,6 +827,8 @@ else if (strcmp(optarg, "kex") == 0 || strcasecmp(optarg, "KexAlgorithms") == 0) cp = kex_alg_list('\n'); @@ -3402,7 +3306,7 @@ index 15aee569..110cf9c1 100644 else if (strcmp(optarg, "key") == 0) cp = sshkey_alg_list(0, 0, 0, '\n'); else if (strcmp(optarg, "key-cert") == 0) -@@ -772,8 +774,8 @@ main(int ac, char **av) +@@ -857,8 +859,8 @@ } else if (strcmp(optarg, "help") == 0) { cp = xstrdup( "cipher\ncipher-auth\ncompression\nkex\n" @@ -3413,10 +3317,9 @@ index 15aee569..110cf9c1 100644 } if (cp == NULL) fatal("Unsupported query \"%s\"", optarg); -diff --git a/ssh_config b/ssh_config -index 5e8ef548..1ff999b6 100644 ---- a/ssh_config -+++ b/ssh_config +diff -Naur a/ssh_config b/ssh_config +--- a/ssh_config 2024-03-21 18:44:48.008756431 +0600 ++++ b/ssh_config 2024-03-21 20:31:55.248171597 +0600 @@ -24,6 +24,8 @@ # HostbasedAuthentication no # GSSAPIAuthentication no @@ -3424,13 +3327,12 @@ index 5e8ef548..1ff999b6 100644 +# GSSAPIKeyExchange no +# GSSAPITrustDNS no # BatchMode no - # CheckHostIP yes + # CheckHostIP no # AddressFamily any -diff --git a/ssh_config.5 b/ssh_config.5 -index 06a32d31..3f490697 100644 ---- a/ssh_config.5 -+++ b/ssh_config.5 -@@ -766,10 +766,68 @@ The default is +diff -Naur a/ssh_config.5 b/ssh_config.5 +--- a/ssh_config.5 2023-12-18 20:59:50.000000000 +0600 ++++ b/ssh_config.5 2024-03-21 20:33:48.232463326 +0600 +@@ -928,10 +928,68 @@ Specifies whether user authentication based on GSSAPI is allowed. The default is .Cm no . @@ -3499,10 +3401,9 @@ index 06a32d31..3f490697 100644 .It Cm HashKnownHosts Indicates that .Xr ssh 1 -diff --git a/sshconnect2.c b/sshconnect2.c -index af00fb30..03bc87eb 100644 ---- a/sshconnect2.c -+++ b/sshconnect2.c +diff -Naur a/sshconnect2.c b/sshconnect2.c +--- a/sshconnect2.c 2023-12-18 20:59:50.000000000 +0600 ++++ b/sshconnect2.c 2024-03-21 20:39:28.075332934 +0600 @@ -80,8 +80,6 @@ #endif @@ -3512,8 +3413,8 @@ index af00fb30..03bc87eb 100644 extern Options options; /* -@@ -163,6 +161,11 @@ ssh_kex2(struct ssh *ssh, char *host, struct sockaddr *hostaddr, u_short port) - char *s, *all_key, *hkalgs = NULL; +@@ -224,6 +222,11 @@ + char *all_key, *hkalgs = NULL; int r, use_known_hosts_order = 0; +#if defined(GSSAPI) && defined(WITH_OPENSSL) @@ -3524,11 +3425,10 @@ index af00fb30..03bc87eb 100644 xxx_host = host; xxx_hostaddr = hostaddr; xxx_conn_info = cinfo; -@@ -206,6 +209,42 @@ ssh_kex2(struct ssh *ssh, char *host, struct sockaddr *hostaddr, u_short port) - kex_proposal_populate_entries(ssh, myproposal, s, options.ciphers, - options.macs, compression_alg_list(options.compression), +@@ -257,6 +260,42 @@ + compression_alg_list(options.compression), hkalgs ? hkalgs : options.hostkeyalgorithms); -+ + +#if defined(GSSAPI) && defined(WITH_OPENSSL) + if (options.gss_keyex) { + /* Add the GSSAPI mechanisms currently supported on this @@ -3564,10 +3464,11 @@ index af00fb30..03bc87eb 100644 + } + } +#endif - ++ free(hkalgs); -@@ -224,17 +256,47 @@ ssh_kex2(struct ssh *ssh, char *host, struct sockaddr *hostaddr, u_short port) + /* start key exchange */ +@@ -273,14 +312,45 @@ # ifdef OPENSSL_HAS_ECC ssh->kex->kex[KEX_ECDH_SHA2] = kex_gen_client; # endif @@ -3598,11 +3499,8 @@ index af00fb30..03bc87eb 100644 +#endif + ssh_dispatch_run_fatal(ssh, DISPATCH_BLOCK, &ssh->kex->done); + kex_proposal_free_entries(myproposal); - /* 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 defined(GSSAPI) && defined(WITH_OPENSSL) + /* repair myproposal after it was crumpled by the */ + /* ext-info removal above */ @@ -3613,10 +3511,11 @@ index af00fb30..03bc87eb 100644 + free(gss); + } +#endif - if ((r = kex_prop2buf(ssh->kex->my, myproposal)) != 0) - fatal_r(r, "kex_prop2buf"); - -@@ -330,6 +392,7 @@ static int input_gssapi_response(int type, u_int32_t, struct ssh *); ++ + #ifdef DEBUG_KEXDH + /* send 1st encrypted/maced/compressed message */ + if ((r = sshpkt_start(ssh, SSH2_MSG_IGNORE)) != 0 || +@@ -370,6 +440,7 @@ static int input_gssapi_token(int type, u_int32_t, struct ssh *); static int input_gssapi_error(int, u_int32_t, struct ssh *); static int input_gssapi_errtok(int, u_int32_t, struct ssh *); @@ -3624,7 +3523,7 @@ index af00fb30..03bc87eb 100644 #endif void userauth(struct ssh *, char *); -@@ -346,6 +409,11 @@ static char *authmethods_get(void); +@@ -386,6 +457,11 @@ Authmethod authmethods[] = { #ifdef GSSAPI @@ -3636,7 +3535,7 @@ index af00fb30..03bc87eb 100644 {"gssapi-with-mic", userauth_gssapi, userauth_gssapi_cleanup, -@@ -716,12 +784,32 @@ userauth_gssapi(struct ssh *ssh) +@@ -757,12 +833,32 @@ OM_uint32 min; int r, ok = 0; gss_OID mech = NULL; @@ -3670,7 +3569,7 @@ index af00fb30..03bc87eb 100644 /* Check to see whether the mechanism is usable before we offer it */ while (authctxt->mech_tried < authctxt->gss_supported_mechs->count && -@@ -730,13 +811,15 @@ userauth_gssapi(struct ssh *ssh) +@@ -771,13 +867,15 @@ elements[authctxt->mech_tried]; /* My DER encoding requires length<128 */ if (mech->length < 128 && ssh_gssapi_check_mechanism(&gssctxt, @@ -3687,7 +3586,7 @@ index af00fb30..03bc87eb 100644 if (!ok || mech == NULL) return 0; -@@ -976,6 +1059,55 @@ input_gssapi_error(int type, u_int32_t plen, struct ssh *ssh) +@@ -1011,6 +1109,55 @@ free(lang); return r; } @@ -3743,11 +3642,10 @@ index af00fb30..03bc87eb 100644 #endif /* GSSAPI */ static int -diff --git a/sshd.c b/sshd.c -index 60b2aaf7..d92f03aa 100644 ---- a/sshd.c -+++ b/sshd.c -@@ -817,8 +817,8 @@ notify_hostkeys(struct ssh *ssh) +diff -Naur a/sshd.c b/sshd.c +--- a/sshd.c 2024-03-21 18:44:48.011756411 +0600 ++++ b/sshd.c 2024-03-21 20:42:19.994255217 +0600 +@@ -805,8 +805,8 @@ } debug3_f("sent %u hostkeys", nkeys); if (nkeys == 0) @@ -3758,7 +3656,7 @@ index 60b2aaf7..d92f03aa 100644 sshpkt_fatal(ssh, r, "%s: send", __func__); sshbuf_free(buf); } -@@ -1852,7 +1852,8 @@ main(int ac, char **av) +@@ -1961,7 +1961,8 @@ free(fp); } accumulate_host_timing_secret(cfg, NULL); @@ -3768,7 +3666,7 @@ index 60b2aaf7..d92f03aa 100644 logit("sshd: no hostkeys available -- exiting."); exit(1); } -@@ -2347,6 +2348,48 @@ do_ssh2_kex(struct ssh *ssh) +@@ -2436,6 +2437,48 @@ free(hkalgs); @@ -3817,7 +3715,7 @@ index 60b2aaf7..d92f03aa 100644 /* start key exchange */ if ((r = kex_setup(ssh, myproposal)) != 0) fatal_r(r, "kex_setup"); -@@ -2362,7 +2405,18 @@ do_ssh2_kex(struct ssh *ssh) +@@ -2453,7 +2496,18 @@ # ifdef OPENSSL_HAS_ECC kex->kex[KEX_ECDH_SHA2] = kex_gen_server; # endif @@ -3837,11 +3735,10 @@ index 60b2aaf7..d92f03aa 100644 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; -diff --git a/sshd_config b/sshd_config -index 19b7c91a..2c48105f 100644 ---- a/sshd_config -+++ b/sshd_config -@@ -69,6 +69,8 @@ AuthorizedKeysFile .ssh/authorized_keys +diff -Naur a/sshd_config b/sshd_config +--- a/sshd_config 2024-03-21 18:44:48.011756411 +0600 ++++ b/sshd_config 2024-03-21 20:42:57.256021632 +0600 +@@ -77,6 +77,8 @@ # GSSAPI options #GSSAPIAuthentication no #GSSAPICleanupCredentials yes @@ -3850,11 +3747,10 @@ index 19b7c91a..2c48105f 100644 # Set this to 'yes' to enable PAM authentication, account processing, # and session processing. If this is enabled, PAM authentication will -diff --git a/sshd_config.5 b/sshd_config.5 -index 70ccea44..f6b41a2f 100644 ---- a/sshd_config.5 -+++ b/sshd_config.5 -@@ -646,6 +646,11 @@ Specifies whether to automatically destroy the user's credentials cache +diff -Naur a/sshd_config.5 b/sshd_config.5 +--- a/sshd_config.5 2024-03-21 18:44:48.009756424 +0600 ++++ b/sshd_config.5 2024-03-21 20:44:32.081427195 +0600 +@@ -731,6 +731,11 @@ on logout. The default is .Cm yes . @@ -3866,7 +3762,7 @@ index 70ccea44..f6b41a2f 100644 .It Cm GSSAPIStrictAcceptorCheck Determines whether to be strict about the identity of the GSSAPI acceptor a client authenticates against. -@@ -660,6 +665,32 @@ machine's default store. +@@ -745,6 +750,32 @@ This facility is provided to assist with operation on multi homed machines. The default is .Cm yes . @@ -3899,15 +3795,195 @@ index 70ccea44..f6b41a2f 100644 .It Cm HostbasedAcceptedAlgorithms Specifies the signature algorithms that will be accepted for hostbased authentication as a list of comma-separated patterns. -diff --git a/sshkey.c b/sshkey.c -index 57995ee6..fd5b7724 100644 ---- a/sshkey.c -+++ b/sshkey.c -@@ -127,6 +127,17 @@ - extern const struct sshkey_impl sshkey_xmss_impl; +diff -Naur a/ssh-gss.h b/ssh-gss.h +--- a/ssh-gss.h 2023-12-18 20:59:50.000000000 +0600 ++++ b/ssh-gss.h 2024-03-21 20:29:14.562178898 +0600 +@@ -1,6 +1,6 @@ + /* $OpenBSD: ssh-gss.h,v 1.15 2021/01/27 10:05:28 djm Exp $ */ + /* +- * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved. ++ * Copyright (c) 2001-2009 Simon Wilkinson. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions +@@ -61,10 +61,35 @@ + + #define SSH_GSS_OIDTYPE 0x06 + ++#define SSH2_MSG_KEXGSS_INIT 30 ++#define SSH2_MSG_KEXGSS_CONTINUE 31 ++#define SSH2_MSG_KEXGSS_COMPLETE 32 ++#define SSH2_MSG_KEXGSS_HOSTKEY 33 ++#define SSH2_MSG_KEXGSS_ERROR 34 ++#define SSH2_MSG_KEXGSS_GROUPREQ 40 ++#define SSH2_MSG_KEXGSS_GROUP 41 ++#define KEX_GSS_GRP1_SHA1_ID "gss-group1-sha1-" ++#define KEX_GSS_GRP14_SHA1_ID "gss-group14-sha1-" ++#define KEX_GSS_GRP14_SHA256_ID "gss-group14-sha256-" ++#define KEX_GSS_GRP16_SHA512_ID "gss-group16-sha512-" ++#define KEX_GSS_GEX_SHA1_ID "gss-gex-sha1-" ++#define KEX_GSS_NISTP256_SHA256_ID "gss-nistp256-sha256-" ++#define KEX_GSS_C25519_SHA256_ID "gss-curve25519-sha256-" ++ ++#define GSS_KEX_DEFAULT_KEX \ ++ KEX_GSS_GRP14_SHA256_ID "," \ ++ KEX_GSS_GRP16_SHA512_ID "," \ ++ KEX_GSS_NISTP256_SHA256_ID "," \ ++ KEX_GSS_C25519_SHA256_ID "," \ ++ KEX_GSS_GRP14_SHA1_ID "," \ ++ KEX_GSS_GEX_SHA1_ID ++ ++ + typedef struct { + char *filename; + char *envvar; + char *envval; ++ struct passwd *owner; + void *data; + } ssh_gssapi_ccache; + +@@ -72,8 +97,11 @@ + gss_buffer_desc displayname; + gss_buffer_desc exportedname; + gss_cred_id_t creds; ++ gss_name_t name; + struct ssh_gssapi_mech_struct *mech; + ssh_gssapi_ccache store; ++ int used; ++ int updated; + } ssh_gssapi_client; + + typedef struct ssh_gssapi_mech_struct { +@@ -84,6 +112,7 @@ + int (*userok) (ssh_gssapi_client *, char *); + int (*localname) (ssh_gssapi_client *, char **); + void (*storecreds) (ssh_gssapi_client *); ++ int (*updatecreds) (ssh_gssapi_ccache *, ssh_gssapi_client *); + } ssh_gssapi_mech; + + typedef struct { +@@ -94,10 +123,11 @@ + gss_OID oid; /* client */ + gss_cred_id_t creds; /* server */ + gss_name_t client; /* server */ +- gss_cred_id_t client_creds; /* server */ ++ gss_cred_id_t client_creds; /* both */ + } Gssctxt; + + extern ssh_gssapi_mech *supported_mechs[]; ++extern Gssctxt *gss_kex_context; + + int ssh_gssapi_check_oid(Gssctxt *, void *, size_t); + void ssh_gssapi_set_oid_data(Gssctxt *, void *, size_t); +@@ -109,6 +139,7 @@ + + struct sshbuf; + int ssh_gssapi_get_buffer_desc(struct sshbuf *, gss_buffer_desc *); ++int ssh_gssapi_sshpkt_get_buffer_desc(struct ssh *, gss_buffer_desc *); + + OM_uint32 ssh_gssapi_import_name(Gssctxt *, const char *); + OM_uint32 ssh_gssapi_init_ctx(Gssctxt *, int, +@@ -123,17 +154,33 @@ + OM_uint32 ssh_gssapi_sign(Gssctxt *, gss_buffer_t, gss_buffer_t); + void ssh_gssapi_buildmic(struct sshbuf *, const char *, + const char *, const char *, const struct sshbuf *); +-int ssh_gssapi_check_mechanism(Gssctxt **, gss_OID, const char *); ++int ssh_gssapi_check_mechanism(Gssctxt **, gss_OID, const char *, const char *); ++OM_uint32 ssh_gssapi_client_identity(Gssctxt *, const char *); ++int ssh_gssapi_credentials_updated(Gssctxt *); + + /* In the server */ ++typedef int ssh_gssapi_check_fn(Gssctxt **, gss_OID, const char *, ++ const char *); ++char *ssh_gssapi_client_mechanisms(const char *, const char *, const char *); ++char *ssh_gssapi_kex_mechs(gss_OID_set, ssh_gssapi_check_fn *, const char *, ++ const char *, const char *); ++gss_OID ssh_gssapi_id_kex(Gssctxt *, char *, int); ++int ssh_gssapi_server_check_mech(Gssctxt **,gss_OID, const char *, ++ const char *); + OM_uint32 ssh_gssapi_server_ctx(Gssctxt **, gss_OID); +-int ssh_gssapi_userok(char *name); ++int ssh_gssapi_userok(char *name, struct passwd *, int kex); + OM_uint32 ssh_gssapi_checkmic(Gssctxt *, gss_buffer_t, gss_buffer_t); + void ssh_gssapi_do_child(char ***, u_int *); + void ssh_gssapi_cleanup_creds(void); + void ssh_gssapi_storecreds(void); + const char *ssh_gssapi_displayname(void); + ++char *ssh_gssapi_server_mechanisms(void); ++int ssh_gssapi_oid_table_ok(void); ++ ++int ssh_gssapi_update_creds(ssh_gssapi_ccache *store); ++void ssh_gssapi_rekey_creds(void); ++ + #endif /* GSSAPI */ + + #endif /* _SSH_GSS_H */ +diff -Naur a/sshkey.c b/sshkey.c +--- a/sshkey.c 2023-12-18 20:59:50.000000000 +0600 ++++ b/sshkey.c 2024-03-21 20:46:14.826782739 +0600 +@@ -129,6 +129,75 @@ extern const struct sshkey_impl sshkey_xmss_cert_impl; #endif -+const struct sshkey_impl sshkey_null_impl = { + ++static int ssh_gss_equal(const struct sshkey *, const struct sshkey *) ++{ ++ return SSH_ERR_FEATURE_UNSUPPORTED; ++} ++ ++static int ssh_gss_serialize_public(const struct sshkey *, struct sshbuf *, ++ enum sshkey_serialize_rep) ++{ ++ return SSH_ERR_FEATURE_UNSUPPORTED; ++} ++ ++static int ssh_gss_deserialize_public(const char *, struct sshbuf *, ++ struct sshkey *) ++{ ++ return SSH_ERR_FEATURE_UNSUPPORTED; ++} ++ ++static int ssh_gss_serialize_private(const struct sshkey *, struct sshbuf *, ++ enum sshkey_serialize_rep) ++{ ++ return SSH_ERR_FEATURE_UNSUPPORTED; ++} ++ ++static int ssh_gss_deserialize_private(const char *, struct sshbuf *, ++ struct sshkey *) ++{ ++ return SSH_ERR_FEATURE_UNSUPPORTED; ++} ++ ++static int ssh_gss_copy_public(const struct sshkey *, struct sshkey *) ++{ ++ return SSH_ERR_FEATURE_UNSUPPORTED; ++} ++ ++static int ssh_gss_verify(const struct sshkey *, const u_char *, size_t, ++ const u_char *, size_t, const char *, u_int, ++ struct sshkey_sig_details **) ++{ ++ return SSH_ERR_FEATURE_UNSUPPORTED; ++} ++ ++static const struct sshkey_impl_funcs sshkey_gss_funcs = { ++ /* .size = */ NULL, ++ /* .alloc = */ NULL, ++ /* .cleanup = */ NULL, ++ /* .equal = */ ssh_gss_equal, ++ /* .ssh_serialize_public = */ ssh_gss_serialize_public, ++ /* .ssh_deserialize_public = */ ssh_gss_deserialize_public, ++ /* .ssh_serialize_private = */ ssh_gss_serialize_private, ++ /* .ssh_deserialize_private = */ ssh_gss_deserialize_private, ++ /* .generate = */ NULL, ++ /* .copy_public = */ ssh_gss_copy_public, ++ /* .sign = */ NULL, ++ /* .verify = */ ssh_gss_verify, ++}; ++ ++/* The struct is intentionally dummy and has no gss calls */ ++static const struct sshkey_impl sshkey_gss_kex_impl = { + /* .name = */ "null", + /* .shortname = */ "null", + /* .sigalg = */ NULL, @@ -3915,21 +3991,22 @@ index 57995ee6..fd5b7724 100644 + /* .nid = */ 0, + /* .cert = */ 0, + /* .sigonly = */ 0, -+ /* .keybits = */ 0, -+ /* .funcs = */ NULL, ++ /* .keybits = */ 0, /* FIXME */ ++ /* .funcs = */ &sshkey_gss_funcs, +}; - ++ const struct sshkey_impl * const keyimpls[] = { &sshkey_ed25519_impl, -@@ -162,6 +179,7 @@ static const struct keytype keytypes[] = + &sshkey_ed25519_cert_impl, +@@ -165,6 +234,7 @@ &sshkey_xmss_impl, &sshkey_xmss_cert_impl, #endif -+ &sshkey_null_impl, ++ &sshkey_gss_kex_impl, NULL }; -@@ -286,7 +304,7 @@ sshkey_alg_list(int certs_only, int plai +@@ -320,7 +390,7 @@ for (i = 0; keyimpls[i] != NULL; i++) { impl = keyimpls[i]; @@ -3938,11 +4015,10 @@ index 57995ee6..fd5b7724 100644 continue; if (!include_sigonly && impl->sigonly) continue; -diff --git a/sshkey.h b/sshkey.h -index 71a3fddc..37a43a67 100644 ---- a/sshkey.h -+++ b/sshkey.h -@@ -69,6 +69,7 @@ enum sshkey_types { +diff -Naur a/sshkey.h b/sshkey.h +--- a/sshkey.h 2023-12-18 20:59:50.000000000 +0600 ++++ b/sshkey.h 2024-03-21 20:46:45.705589010 +0600 +@@ -71,6 +71,7 @@ KEY_ECDSA_SK_CERT, KEY_ED25519_SK, KEY_ED25519_SK_CERT, diff --git a/openssh/openssh-9.7p1-negotiate-supported-algs.patch b/openssh/openssh-9.7p1-negotiate-supported-algs.patch new file mode 100644 index 0000000..ff9a5e5 --- /dev/null +++ b/openssh/openssh-9.7p1-negotiate-supported-algs.patch @@ -0,0 +1,118 @@ +diff -up openssh-9.3p1/regress/hostkey-agent.sh.xxx openssh-9.3p1/regress/hostkey-agent.sh +--- openssh-9.3p1/regress/hostkey-agent.sh.xxx 2023-05-29 18:15:56.311236887 +0200 ++++ openssh-9.3p1/regress/hostkey-agent.sh 2023-05-29 18:16:07.598503551 +0200 +@@ -17,8 +17,21 @@ trace "make CA key" + + ${SSHKEYGEN} -qt ed25519 -f $OBJ/agent-ca -N '' || fatal "ssh-keygen CA" + ++PUBKEY_ACCEPTED_ALGOS=`$SSH -G "example.com" | \ ++ grep -i "PubkeyAcceptedAlgorithms" | cut -d ' ' -f2- | tr "," "|"` ++SSH_ACCEPTED_KEYTYPES=`echo "$SSH_KEYTYPES" | egrep "$PUBKEY_ACCEPTED_ALGOS"` ++echo $PUBKEY_ACCEPTED_ALGOS | grep "rsa" ++r=$? ++if [ $r == 0 ]; then ++echo $SSH_ACCEPTED_KEYTYPES | grep "rsa" ++r=$? ++if [ $r -ne 0 ]; then ++SSH_ACCEPTED_KEYTYPES="$SSH_ACCEPTED_KEYTYPES ssh-rsa" ++fi ++fi ++ + trace "load hostkeys" +-for k in $SSH_KEYTYPES ; do ++for k in $SSH_ACCEPTED_KEYTYPES ; 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,12 +48,16 @@ rm $OBJ/agent-ca # Don't need CA private + + unset SSH_AUTH_SOCK + +-for k in $SSH_KEYTYPES ; do ++for k in $SSH_ACCEPTED_KEYTYPES ; do + verbose "key type $k" ++ hka=$k ++ if [ $k = "ssh-rsa" ]; then ++ hka="rsa-sha2-512" ++ fi + cp $OBJ/sshd_proxy.orig $OBJ/sshd_proxy +- echo "HostKeyAlgorithms $k" >> $OBJ/sshd_proxy ++ echo "HostKeyAlgorithms $hka" >> $OBJ/sshd_proxy + echo "Hostkey $OBJ/agent-key.${k}" >> $OBJ/sshd_proxy +- opts="-oHostKeyAlgorithms=$k -F $OBJ/ssh_proxy" ++ opts="-oHostKeyAlgorithms=$hka -F $OBJ/ssh_proxy" + ( printf 'localhost-with-alias,127.0.0.1,::1 ' ; + cat $OBJ/agent-key.$k.pub) > $OBJ/known_hosts + SSH_CONNECTION=`${SSH} $opts host 'echo $SSH_CONNECTION'` +@@ -50,15 +70,16 @@ for k in $SSH_KEYTYPES ; do + done + + SSH_CERTTYPES=`ssh -Q key-sig | grep 'cert-v01@openssh.com'` ++SSH_ACCEPTED_CERTTYPES=`echo "$SSH_CERTTYPES" | egrep "$PUBKEY_ACCEPTED_ALGOS"` + + # Prepare sshd_proxy for certificates. + cp $OBJ/sshd_proxy.orig $OBJ/sshd_proxy + HOSTKEYALGS="" +-for k in $SSH_CERTTYPES ; do ++for k in $SSH_ACCEPTED_CERTTYPES ; do + test -z "$HOSTKEYALGS" || HOSTKEYALGS="${HOSTKEYALGS}," + HOSTKEYALGS="${HOSTKEYALGS}${k}" + done +-for k in $SSH_KEYTYPES ; do ++for k in $SSH_ACCEPTED_KEYTYPES ; do + echo "Hostkey $OBJ/agent-key.${k}.pub" >> $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" +@@ -70,7 +93,7 @@ echo "HostKeyAlgorithms $HOSTKEYALGS" >> + ( printf '@cert-authority localhost-with-alias ' ; + cat $OBJ/agent-ca.pub) > $OBJ/known_hosts + +-for k in $SSH_CERTTYPES ; do ++for k in $SSH_ACCEPTED_CERTTYPES ; do + verbose "cert type $k" + opts="-oHostKeyAlgorithms=$k -F $OBJ/ssh_proxy" + SSH_CONNECTION=`${SSH} $opts host 'echo $SSH_CONNECTION'` +diff -up openssh-9.3p1/sshconnect2.c.xxx openssh-9.3p1/sshconnect2.c +--- openssh-9.3p1/sshconnect2.c.xxx 2023-04-26 17:37:35.100827792 +0200 ++++ openssh-9.3p1/sshconnect2.c 2023-04-26 17:50:31.860748877 +0200 +@@ -221,7 +221,7 @@ + const struct ssh_conn_info *cinfo) + { + char *myproposal[PROPOSAL_MAX]; +- char *all_key, *hkalgs = NULL; ++ char *s, *all_key, *hkalgs = NULL, *filtered_algs = NULL; + int r, use_known_hosts_order = 0; + + #if defined(GSSAPI) && defined(WITH_OPENSSL) +@@ -257,10 +257,22 @@ + if (use_known_hosts_order) + hkalgs = order_hostkeyalgs(host, hostaddr, port, cinfo); + ++ filtered_algs = hkalgs ? match_filter_allowlist(hkalgs, options.pubkey_accepted_algos) ++ : match_filter_allowlist(options.hostkeyalgorithms, ++ options.pubkey_accepted_algos); ++ if (filtered_algs == NULL) { ++ if (hkalgs) ++ fatal_f("No match between algorithms for %s (host %s) and pubkey accepted algorithms %s", ++ hkalgs, host, options.pubkey_accepted_algos); ++ else ++ fatal_f("No match between host key algorithms %s and pubkey accepted algorithms %s", ++ options.hostkeyalgorithms, options.pubkey_accepted_algos); ++ } ++ + kex_proposal_populate_entries(ssh, myproposal, + options.kex_algorithms, options.ciphers, options.macs, + compression_alg_list(options.compression), +- hkalgs ? hkalgs : options.hostkeyalgorithms); ++ filtered_algs); + + #if defined(GSSAPI) && defined(WITH_OPENSSL) + if (options.gss_keyex) { +@@ -304,6 +316,7 @@ + #endif + + free(hkalgs); ++ free(filtered_algs); + + /* start key exchange */ + if ((r = kex_setup(ssh, myproposal)) != 0) diff --git a/openssh/openssh-8.7p1-nohostsha1proof.patch b/openssh/openssh-9.7p1-nohostsha1proof.patch similarity index 75% rename from openssh/openssh-8.7p1-nohostsha1proof.patch rename to openssh/openssh-9.7p1-nohostsha1proof.patch index 7fea800..a2cb9e2 100644 --- a/openssh/openssh-8.7p1-nohostsha1proof.patch +++ b/openssh/openssh-9.7p1-nohostsha1proof.patch @@ -1,6 +1,6 @@ -diff -up openssh-8.7p1/compat.c.sshrsacheck openssh-8.7p1/compat.c ---- openssh-8.7p1/compat.c.sshrsacheck 2023-01-12 13:29:06.338710923 +0100 -+++ openssh-8.7p1/compat.c 2023-01-12 13:29:06.357711165 +0100 +diff -up openssh-9.7p1/compat.c.sshrsacheck openssh-9.7p1/compat.c +--- openssh-9.7p1/compat.c.sshrsacheck 2023-01-12 13:29:06.338710923 +0100 ++++ openssh-9.7p1/compat.c 2023-01-12 13:29:06.357711165 +0100 @@ -43,6 +43,7 @@ void compat_banner(struct ssh *ssh, const char *version) { @@ -31,9 +31,9 @@ diff -up openssh-8.7p1/compat.c.sshrsacheck openssh-8.7p1/compat.c } /* Always returns pointer to allocated memory, caller must free. */ -diff -up openssh-8.7p1/compat.h.sshrsacheck openssh-8.7p1/compat.h ---- openssh-8.7p1/compat.h.sshrsacheck 2021-08-20 06:03:49.000000000 +0200 -+++ openssh-8.7p1/compat.h 2023-01-12 13:29:06.358711178 +0100 +diff -up openssh-9.7p1/compat.h.sshrsacheck openssh-9.7p1/compat.h +--- openssh-9.7p1/compat.h.sshrsacheck 2021-08-20 06:03:49.000000000 +0200 ++++ openssh-9.7p1/compat.h 2023-01-12 13:29:06.358711178 +0100 @@ -30,7 +30,7 @@ #define SSH_BUG_UTF8TTYMODE 0x00000001 #define SSH_BUG_SIGTYPE 0x00000002 @@ -43,9 +43,9 @@ diff -up openssh-8.7p1/compat.h.sshrsacheck openssh-8.7p1/compat.h #define SSH_OLD_SESSIONID 0x00000010 /* #define unused 0x00000020 */ #define SSH_BUG_DEBUG 0x00000040 -diff -up openssh-8.7p1/monitor.c.sshrsacheck openssh-8.7p1/monitor.c ---- openssh-8.7p1/monitor.c.sshrsacheck 2023-01-20 13:07:54.279676981 +0100 -+++ openssh-8.7p1/monitor.c 2023-01-20 15:01:07.007821379 +0100 +diff -up openssh-9.7p1/monitor.c.sshrsacheck openssh-9.7p1/monitor.c +--- openssh-9.7p1/monitor.c.sshrsacheck 2023-01-20 13:07:54.279676981 +0100 ++++ openssh-9.7p1/monitor.c 2023-01-20 15:01:07.007821379 +0100 @@ -660,11 +660,12 @@ mm_answer_sign(struct ssh *ssh, int sock struct sshkey *key; struct sshbuf *sigbuf = NULL; @@ -94,9 +94,9 @@ diff -up openssh-8.7p1/monitor.c.sshrsacheck openssh-8.7p1/monitor.c is_proof ? "hostkey proof" : "KEX", siglen); sshbuf_reset(m); -diff -up openssh-8.7p1/regress/cert-userkey.sh.sshrsacheck openssh-8.7p1/regress/cert-userkey.sh ---- openssh-8.7p1/regress/cert-userkey.sh.sshrsacheck 2023-01-25 14:26:52.885963113 +0100 -+++ openssh-8.7p1/regress/cert-userkey.sh 2023-01-25 14:27:25.757219800 +0100 +diff -up openssh-9.7p1/regress/cert-userkey.sh.sshrsacheck openssh-9.7p1/regress/cert-userkey.sh +--- openssh-9.7p1/regress/cert-userkey.sh.sshrsacheck 2023-01-25 14:26:52.885963113 +0100 ++++ openssh-9.7p1/regress/cert-userkey.sh 2023-01-25 14:27:25.757219800 +0100 @@ -7,7 +7,8 @@ rm -f $OBJ/authorized_keys_$USER $OBJ/us cp $OBJ/sshd_proxy $OBJ/sshd_proxy_bak cp $OBJ/ssh_proxy $OBJ/ssh_proxy_bak @@ -107,9 +107,9 @@ diff -up openssh-8.7p1/regress/cert-userkey.sh.sshrsacheck openssh-8.7p1/regress EXTRA_TYPES="" rsa="" -diff -up openssh-8.7p1/regress/Makefile.sshrsacheck openssh-8.7p1/regress/Makefile ---- openssh-8.7p1/regress/Makefile.sshrsacheck 2023-01-20 13:07:54.169676051 +0100 -+++ openssh-8.7p1/regress/Makefile 2023-01-20 13:07:54.290677074 +0100 +diff -up openssh-9.7p1/regress/Makefile.sshrsacheck openssh-9.7p1/regress/Makefile +--- openssh-9.7p1/regress/Makefile.sshrsacheck 2023-01-20 13:07:54.169676051 +0100 ++++ openssh-9.7p1/regress/Makefile 2023-01-20 13:07:54.290677074 +0100 @@ -2,7 +2,8 @@ tests: prep file-tests t-exec unit @@ -120,9 +120,9 @@ diff -up openssh-8.7p1/regress/Makefile.sshrsacheck openssh-8.7p1/regress/Makefi # File based tests file-tests: $(REGRESS_TARGETS) -diff -up openssh-8.7p1/regress/test-exec.sh.sshrsacheck openssh-8.7p1/regress/test-exec.sh ---- openssh-8.7p1/regress/test-exec.sh.sshrsacheck 2023-01-25 14:24:54.778040819 +0100 -+++ openssh-8.7p1/regress/test-exec.sh 2023-01-25 14:26:39.500858590 +0100 +diff -up openssh-9.7p1/regress/test-exec.sh.sshrsacheck openssh-9.7p1/regress/test-exec.sh +--- openssh-9.7p1/regress/test-exec.sh.sshrsacheck 2023-01-25 14:24:54.778040819 +0100 ++++ openssh-9.7p1/regress/test-exec.sh 2023-01-25 14:26:39.500858590 +0100 @@ -581,8 +581,9 @@ maybe_filter_sk() { fi } @@ -135,10 +135,10 @@ diff -up openssh-8.7p1/regress/test-exec.sh.sshrsacheck openssh-8.7p1/regress/te for t in ${SSH_KEYTYPES}; do # generate user key -diff -up openssh-8.7p1/regress/unittests/kex/test_kex.c.sshrsacheck openssh-8.7p1/regress/unittests/kex/test_kex.c ---- openssh-8.7p1/regress/unittests/kex/test_kex.c.sshrsacheck 2023-01-26 13:34:52.645743677 +0100 -+++ openssh-8.7p1/regress/unittests/kex/test_kex.c 2023-01-26 13:36:56.220745823 +0100 -@@ -97,7 +97,8 @@ do_kex_with_key(char *kex, int keytype, +diff -up openssh-9.7p1/regress/unittests/kex/test_kex.c.sshrsacheck openssh-9.7p1/regress/unittests/kex/test_kex.c +--- openssh-9.7p1/regress/unittests/kex/test_kex.c.nosha1hostproof 2024-03-11 11:20:49.000000000 +0600 ++++ openssh-9.7p1/regress/unittests/kex/test_kex.c 2024-03-21 21:26:44.502547206 +0600 +@@ -96,7 +96,8 @@ memcpy(kex_params.proposal, myproposal, sizeof(myproposal)); if (kex != NULL) kex_params.proposal[PROPOSAL_KEX_ALGS] = kex; @@ -148,18 +148,19 @@ diff -up openssh-8.7p1/regress/unittests/kex/test_kex.c.sshrsacheck openssh-8.7p ASSERT_PTR_NE(keyname, NULL); kex_params.proposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = keyname; ASSERT_INT_EQ(ssh_init(&client, 0, &kex_params), 0); -@@ -180,7 +181,7 @@ do_kex(char *kex) - { +@@ -180,7 +181,7 @@ #ifdef WITH_OPENSSL do_kex_with_key(kex, KEY_RSA, 2048); + #ifdef WITH_DSA - do_kex_with_key(kex, KEY_DSA, 1024); + /* do_kex_with_key(kex, KEY_DSA, 1024); */ + #endif #ifdef OPENSSL_HAS_ECC do_kex_with_key(kex, KEY_ECDSA, 256); - #endif /* OPENSSL_HAS_ECC */ -diff -up openssh-8.7p1/regress/unittests/sshkey/test_file.c.sshrsacheck openssh-8.7p1/regress/unittests/sshkey/test_file.c ---- openssh-8.7p1/regress/unittests/sshkey/test_file.c.sshrsacheck 2023-01-26 12:04:55.946343408 +0100 -+++ openssh-8.7p1/regress/unittests/sshkey/test_file.c 2023-01-26 12:06:35.235164432 +0100 + +diff -up openssh-9.7p1/regress/unittests/sshkey/test_file.c.sshrsacheck openssh-9.7p1/regress/unittests/sshkey/test_file.c +--- openssh-9.7p1/regress/unittests/sshkey/test_file.c.sshrsacheck 2023-01-26 12:04:55.946343408 +0100 ++++ openssh-9.7p1/regress/unittests/sshkey/test_file.c 2023-01-26 12:06:35.235164432 +0100 @@ -110,6 +110,7 @@ sshkey_file_tests(void) sshkey_free(k2); TEST_DONE(); @@ -177,10 +178,10 @@ diff -up openssh-8.7p1/regress/unittests/sshkey/test_file.c.sshrsacheck openssh- TEST_START("load RSA cert with SHA512 signature"); ASSERT_INT_EQ(sshkey_load_cert(test_data_file("rsa_1_sha512"), &k2), 0); -diff -up openssh-8.7p1/regress/unittests/sshkey/test_fuzz.c.sshrsacheck openssh-8.7p1/regress/unittests/sshkey/test_fuzz.c ---- openssh-8.7p1/regress/unittests/sshkey/test_fuzz.c.sshrsacheck 2023-01-26 12:10:37.533168013 +0100 -+++ openssh-8.7p1/regress/unittests/sshkey/test_fuzz.c 2023-01-26 12:15:35.637631860 +0100 -@@ -333,13 +333,14 @@ sshkey_fuzz_tests(void) +diff -up openssh-9.7p1/regress/unittests/sshkey/test_fuzz.c.sshrsacheck openssh-9.7p1/regress/unittests/sshkey/test_fuzz.c +--- openssh-9.7p1/regress/unittests/sshkey/test_fuzz.c.nosha1hostproof 2024-03-11 11:20:49.000000000 +0600 ++++ openssh-9.7p1/regress/unittests/sshkey/test_fuzz.c 2024-03-21 21:28:07.606026626 +0600 +@@ -338,13 +338,14 @@ TEST_DONE(); #ifdef WITH_OPENSSL @@ -196,25 +197,25 @@ diff -up openssh-8.7p1/regress/unittests/sshkey/test_fuzz.c.sshrsacheck openssh- TEST_START("fuzz RSA SHA256 sig"); buf = load_file("rsa_1"); -@@ -357,6 +358,7 @@ sshkey_fuzz_tests(void) +@@ -362,6 +363,7 @@ sshkey_free(k1); TEST_DONE(); -+ /* Skip this test, SHA1 signatures are not supported ++/* Skip this test, SHA1 signatures are not supported + #ifdef WITH_DSA TEST_START("fuzz DSA sig"); buf = load_file("dsa_1"); - ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0); -@@ -364,6 +366,7 @@ sshkey_fuzz_tests(void) - sig_fuzz(k1, NULL); +@@ -371,6 +373,7 @@ sshkey_free(k1); TEST_DONE(); -+ */ + #endif ++*/ #ifdef OPENSSL_HAS_ECC TEST_START("fuzz ECDSA sig"); -diff -up openssh-8.7p1/regress/unittests/sshkey/test_sshkey.c.sshrsacheck openssh-8.7p1/regress/unittests/sshkey/test_sshkey.c ---- openssh-8.7p1/regress/unittests/sshkey/test_sshkey.c.sshrsacheck 2023-01-26 11:02:52.339413463 +0100 -+++ openssh-8.7p1/regress/unittests/sshkey/test_sshkey.c 2023-01-26 11:58:42.324253896 +0100 +diff -up openssh-9.7p1/regress/unittests/sshkey/test_sshkey.c.sshrsacheck openssh-9.7p1/regress/unittests/sshkey/test_sshkey.c +--- openssh-9.7p1/regress/unittests/sshkey/test_sshkey.c.sshrsacheck 2023-01-26 11:02:52.339413463 +0100 ++++ openssh-9.7p1/regress/unittests/sshkey/test_sshkey.c 2023-01-26 11:58:42.324253896 +0100 @@ -60,6 +60,9 @@ build_cert(struct sshbuf *b, struct sshk u_char *sigblob; size_t siglen; @@ -277,24 +278,26 @@ diff -up openssh-8.7p1/regress/unittests/sshkey/test_sshkey.c.sshrsacheck openss ASSERT_INT_EQ(sshkey_from_blob(sshbuf_ptr(b), sshbuf_len(b), &k4), SSH_ERR_KEY_CERT_INVALID_SIGN_KEY); ASSERT_PTR_EQ(k4, NULL); -diff -up openssh-8.7p1/regress/unittests/sshsig/tests.c.sshrsacheck openssh-8.7p1/regress/unittests/sshsig/tests.c ---- openssh-8.7p1/regress/unittests/sshsig/tests.c.sshrsacheck 2023-01-26 12:19:23.659513651 +0100 -+++ openssh-8.7p1/regress/unittests/sshsig/tests.c 2023-01-26 12:20:28.021044803 +0100 -@@ -102,9 +102,11 @@ tests(void) +diff -up openssh-9.7p1/regress/unittests/sshsig/tests.c.sshrsacheck openssh-9.7p1/regress/unittests/sshsig/tests.c +--- openssh-9.7p1/regress/unittests/sshsig/tests.c.nosha1hostproof 2024-03-11 11:20:49.000000000 +0600 ++++ openssh-9.7p1/regress/unittests/sshsig/tests.c 2024-03-21 21:29:14.951604758 +0600 +@@ -103,11 +103,13 @@ check_sig("rsa.pub", "rsa.sig", msg, namespace); TEST_DONE(); -+ /* Skip this test, SHA1 signatures are not supported ++/* Skip this test, SHA1 signatures are not supported + #ifdef WITH_DSA TEST_START("check DSA signature"); check_sig("dsa.pub", "dsa.sig", msg, namespace); TEST_DONE(); -+ */ + #endif ++*/ #ifdef OPENSSL_HAS_ECC TEST_START("check ECDSA signature"); -diff -up openssh-8.7p1/serverloop.c.sshrsacheck openssh-8.7p1/serverloop.c ---- openssh-8.7p1/serverloop.c.sshrsacheck 2023-01-12 14:57:08.118400073 +0100 -+++ openssh-8.7p1/serverloop.c 2023-01-12 14:59:17.330470518 +0100 +diff -up openssh-9.7p1/serverloop.c.sshrsacheck openssh-9.7p1/serverloop.c +--- openssh-9.7p1/serverloop.c.sshrsacheck 2023-01-12 14:57:08.118400073 +0100 ++++ openssh-9.7p1/serverloop.c 2023-01-12 14:59:17.330470518 +0100 @@ -80,6 +80,7 @@ #include "auth-options.h" #include "serverloop.h" @@ -314,9 +317,9 @@ diff -up openssh-8.7p1/serverloop.c.sshrsacheck openssh-8.7p1/serverloop.c debug3_f("sign %s key (index %d) using sigalg %s", sshkey_type(key), ndx, sigalg == NULL ? "default" : sigalg); if ((r = sshbuf_put_cstring(sigbuf, -diff -up openssh-8.7p1/sshconnect2.c.sshrsacheck openssh-8.7p1/sshconnect2.c ---- openssh-8.7p1/sshconnect2.c.sshrsacheck 2023-01-25 15:33:29.140353651 +0100 -+++ openssh-8.7p1/sshconnect2.c 2023-01-25 15:59:34.225364883 +0100 +diff -up openssh-9.7p1/sshconnect2.c.sshrsacheck openssh-9.7p1/sshconnect2.c +--- openssh-9.7p1/sshconnect2.c.sshrsacheck 2023-01-25 15:33:29.140353651 +0100 ++++ openssh-9.7p1/sshconnect2.c 2023-01-25 15:59:34.225364883 +0100 @@ -1461,6 +1464,14 @@ identity_sign(struct identity *id, u_cha retried = 1; goto retry_pin; @@ -332,9 +335,9 @@ diff -up openssh-8.7p1/sshconnect2.c.sshrsacheck openssh-8.7p1/sshconnect2.c goto out; } -diff -up openssh-8.7p1/sshd.c.sshrsacheck openssh-8.7p1/sshd.c ---- openssh-8.7p1/sshd.c.sshrsacheck 2023-01-12 13:29:06.355711140 +0100 -+++ openssh-8.7p1/sshd.c 2023-01-12 13:29:06.358711178 +0100 +diff -up openssh-9.7p1/sshd.c.sshrsacheck openssh-9.7p1/sshd.c +--- openssh-9.7p1/sshd.c.sshrsacheck 2023-01-12 13:29:06.355711140 +0100 ++++ openssh-9.7p1/sshd.c 2023-01-12 13:29:06.358711178 +0100 @@ -1640,6 +1651,7 @@ main(int ac, char **av) Authctxt *authctxt; struct connection_info *connection_info = NULL; @@ -387,9 +390,9 @@ diff -up openssh-8.7p1/sshd.c.sshrsacheck openssh-8.7p1/sshd.c /* Prepare the channels layer */ channel_init_channels(ssh); channel_set_af(ssh, options.address_family); -diff -up openssh-8.7p1/ssh-rsa.c.sshrsacheck openssh-8.7p1/ssh-rsa.c ---- openssh-8.7p1/ssh-rsa.c.sshrsacheck 2023-01-20 13:07:54.180676144 +0100 -+++ openssh-8.7p1/ssh-rsa.c 2023-01-20 13:07:54.290677074 +0100 +diff -up openssh-9.7p1/ssh-rsa.c.sshrsacheck openssh-9.7p1/ssh-rsa.c +--- openssh-9.7p1/ssh-rsa.c.sshrsacheck 2023-01-20 13:07:54.180676144 +0100 ++++ openssh-9.7p1/ssh-rsa.c 2023-01-20 13:07:54.290677074 +0100 @@ -254,7 +254,8 @@ ssh_rsa_verify(const struct sshkey *key, ret = SSH_ERR_INVALID_ARGUMENT; goto out; diff --git a/openssh/openssh-9.3p2-pkcs11-uri.patch b/openssh/openssh-9.7p1-pkcs11-uri.patch similarity index 88% rename from openssh/openssh-9.3p2-pkcs11-uri.patch rename to openssh/openssh-9.7p1-pkcs11-uri.patch index ffaf98a..bd015d3 100644 --- a/openssh/openssh-9.3p2-pkcs11-uri.patch +++ b/openssh/openssh-9.7p1-pkcs11-uri.patch @@ -1,7 +1,7 @@ -diff -Naur a/configure.ac b/configure.ac ---- a/configure.ac 2023-10-20 19:13:59.336263852 +0600 -+++ b/configure.ac 2023-10-20 19:11:41.812164445 +0600 -@@ -2056,12 +2056,14 @@ +diff -up openssh-9.6p1/configure.ac.pkcs11-uri openssh-9.6p1/configure.ac +--- openssh-9.6p1/configure.ac.pkcs11-uri 2024-01-12 14:25:25.228942213 +0100 ++++ openssh-9.6p1/configure.ac 2024-01-12 14:25:25.233942336 +0100 +@@ -2066,12 +2066,14 @@ AC_LINK_IFELSE( [AC_DEFINE([HAVE_ISBLANK], [1], [Define if you have isblank(3C).]) ]) @@ -16,7 +16,7 @@ diff -Naur a/configure.ac b/configure.ac fi ] ) -@@ -2085,6 +2087,40 @@ +@@ -2095,6 +2097,40 @@ AC_SEARCH_LIBS([dlopen], [dl]) AC_CHECK_FUNCS([dlopen]) AC_CHECK_DECL([RTLD_NOW], [], [], [#include ]) @@ -57,7 +57,7 @@ diff -Naur a/configure.ac b/configure.ac # IRIX has a const char return value for gai_strerror() AC_CHECK_FUNCS([gai_strerror], [ AC_DEFINE([HAVE_GAI_STRERROR]) -@@ -5692,6 +5728,7 @@ +@@ -5708,6 +5744,7 @@ echo " BSD Auth support echo " Random number source: $RAND_MSG" echo " Privsep sandbox style: $SANDBOX_STYLE" echo " PKCS#11 support: $enable_pkcs11" @@ -65,10 +65,10 @@ diff -Naur a/configure.ac b/configure.ac echo " U2F/FIDO support: $enable_sk" echo "" -diff -Naur a/Makefile.in b/Makefile.in ---- a/Makefile.in 2023-10-20 19:13:59.290264154 +0600 -+++ b/Makefile.in 2023-10-20 19:11:41.813164439 +0600 -@@ -105,7 +105,7 @@ +diff -up openssh-9.6p1/Makefile.in.pkcs11-uri openssh-9.6p1/Makefile.in +--- openssh-9.6p1/Makefile.in.pkcs11-uri 2024-01-12 14:25:25.204941622 +0100 ++++ openssh-9.6p1/Makefile.in 2024-01-12 14:25:25.233942336 +0100 +@@ -105,7 +105,7 @@ LIBSSH_OBJS=${LIBOPENSSH_OBJS} \ 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 \ @@ -77,7 +77,7 @@ diff -Naur a/Makefile.in b/Makefile.in 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 \ -@@ -299,6 +299,8 @@ +@@ -299,6 +299,8 @@ clean: regressclean rm -f regress/unittests/sshsig/test_sshsig$(EXEEXT) rm -f regress/unittests/utf8/*.o rm -f regress/unittests/utf8/test_utf8$(EXEEXT) @@ -86,7 +86,7 @@ diff -Naur a/Makefile.in b/Makefile.in rm -f regress/misc/sk-dummy/*.o rm -f regress/misc/sk-dummy/*.lo rm -f regress/misc/sk-dummy/sk-dummy.so -@@ -336,6 +338,8 @@ +@@ -336,6 +338,8 @@ distclean: regressclean rm -f regress/unittests/sshsig/test_sshsig rm -f regress/unittests/utf8/*.o rm -f regress/unittests/utf8/test_utf8 @@ -95,7 +95,7 @@ diff -Naur a/Makefile.in b/Makefile.in rm -f regress/misc/sk-dummy/*.o rm -f regress/misc/sk-dummy/*.lo rm -f regress/misc/sk-dummy/sk-dummy.so -@@ -513,6 +517,7 @@ +@@ -513,6 +517,7 @@ regress-prep: $(MKDIR_P) `pwd`/regress/unittests/sshkey $(MKDIR_P) `pwd`/regress/unittests/sshsig $(MKDIR_P) `pwd`/regress/unittests/utf8 @@ -103,7 +103,7 @@ diff -Naur a/Makefile.in b/Makefile.in $(MKDIR_P) `pwd`/regress/misc/sk-dummy [ -f `pwd`/regress/Makefile ] || \ ln -s `cd $(srcdir) && pwd`/regress/Makefile `pwd`/regress/Makefile -@@ -685,6 +690,17 @@ +@@ -685,6 +690,16 @@ regress/unittests/utf8/test_utf8$(EXEEXT regress/unittests/test_helper/libtest_helper.a \ -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(TESTLIBS) @@ -116,37 +116,24 @@ diff -Naur a/Makefile.in b/Makefile.in + $(LD) -o $@ $(LDFLAGS) $(UNITTESTS_TEST_PKCS11_OBJS) \ + regress/unittests/test_helper/libtest_helper.a \ + -lssh -lopenbsd-compat -lcrypto $(LIBS) -+ + # These all need to be compiled -fPIC, so they are treated differently. SK_DUMMY_OBJS=\ regress/misc/sk-dummy/sk-dummy.lo \ -@@ -720,7 +736,8 @@ +@@ -720,7 +735,8 @@ regress-unit-binaries: regress-prep $(RE regress/unittests/sshbuf/test_sshbuf$(EXEEXT) \ regress/unittests/sshkey/test_sshkey$(EXEEXT) \ regress/unittests/sshsig/test_sshsig$(EXEEXT) \ - regress/unittests/utf8/test_utf8$(EXEEXT) + regress/unittests/utf8/test_utf8$(EXEEXT) \ -+ regress/unittests/pkcs11/test_pkcs11$(EXEEXT) ++ regress/unittests/pkcs11/test_pkcs11$(EXEEXT) \ - tests: file-tests t-exec interop-tests unit + tests: file-tests t-exec interop-tests extra-tests unit echo all tests passed -diff -Naur a/regress/agent-pkcs11.sh b/regress/agent-pkcs11.sh ---- a/regress/agent-pkcs11.sh 2023-07-19 12:31:34.000000000 +0600 -+++ b/regress/agent-pkcs11.sh 2023-10-20 19:11:41.813164439 +0600 -@@ -113,7 +113,7 @@ - done - - trace "remove pkcs11 keys" -- echo ${TEST_SSH_PIN} | notty ${SSHADD} -e ${TEST_SSH_PKCS11} > /dev/null 2>&1 -+ ${SSHADD} -e ${TEST_SSH_PKCS11} > /dev/null 2>&1 - r=$? - if [ $r -ne 0 ]; then - fail "ssh-add -e failed: exit code $r" -diff -Naur a/regress/Makefile b/regress/Makefile ---- a/regress/Makefile 2023-07-19 12:31:34.000000000 +0600 -+++ b/regress/Makefile 2023-10-20 19:11:41.813164439 +0600 -@@ -127,7 +127,8 @@ +diff -up openssh-9.6p1/regress/Makefile.pkcs11-uri openssh-9.6p1/regress/Makefile +--- openssh-9.6p1/regress/Makefile.pkcs11-uri 2023-12-18 15:59:50.000000000 +0100 ++++ openssh-9.6p1/regress/Makefile 2024-01-12 14:25:25.233942336 +0100 +@@ -134,7 +134,8 @@ CLEANFILES= *.core actual agent-key.* au known_hosts known_hosts-cert known_hosts.* krl-* ls.copy \ modpipe netcat no_identity_config \ pidfile putty.rsa2 ready regress.log remote_pid \ @@ -156,7 +143,7 @@ diff -Naur a/regress/Makefile b/regress/Makefile rsa_ssh2_crnl.prv scp-ssh-wrapper.exe \ scp-ssh-wrapper.scp setuid-allowed sftp-server.log \ sftp-server.sh sftp.log ssh-log-wrapper.sh ssh.log \ -@@ -258,8 +259,9 @@ +@@ -273,8 +274,9 @@ unit: V="" ; \ test "x${USE_VALGRIND}" = "x" || \ V=${.CURDIR}/valgrind-unit.sh ; \ @@ -168,9 +155,9 @@ diff -Naur a/regress/Makefile b/regress/Makefile -d ${.CURDIR}/unittests/sshkey/testdata ; \ $$V ${.OBJDIR}/unittests/sshsig/test_sshsig \ -d ${.CURDIR}/unittests/sshsig/testdata ; \ -diff -Naur a/regress/pkcs11.sh b/regress/pkcs11.sh ---- a/regress/pkcs11.sh 1970-01-01 06:00:00.000000000 +0600 -+++ b/regress/pkcs11.sh 2023-10-20 19:11:41.813164439 +0600 +diff -up openssh-9.6p1/regress/pkcs11.sh.pkcs11-uri openssh-9.6p1/regress/pkcs11.sh +--- openssh-9.6p1/regress/pkcs11.sh.pkcs11-uri 2024-01-12 14:25:25.233942336 +0100 ++++ openssh-9.6p1/regress/pkcs11.sh 2024-01-12 14:25:25.233942336 +0100 @@ -0,0 +1,349 @@ +# +# Copyright (c) 2017 Red Hat @@ -521,21 +508,20 @@ diff -Naur a/regress/pkcs11.sh b/regress/pkcs11.sh + trace "kill agent" + ${SSHAGENT} -k > /dev/null +fi -\ В конце файла нет новой строки -diff -Naur a/regress/unittests/Makefile b/regress/unittests/Makefile ---- a/regress/unittests/Makefile 2023-07-19 12:31:34.000000000 +0600 -+++ b/regress/unittests/Makefile 2023-10-20 19:11:41.813164439 +0600 -@@ -2,6 +2,6 @@ +diff -up openssh-9.6p1/regress/unittests/Makefile.pkcs11-uri openssh-9.6p1/regress/unittests/Makefile +--- openssh-9.6p1/regress/unittests/Makefile.pkcs11-uri 2023-12-18 15:59:50.000000000 +0100 ++++ openssh-9.6p1/regress/unittests/Makefile 2024-01-12 14:25:25.233942336 +0100 +@@ -1,6 +1,6 @@ + # $OpenBSD: Makefile,v 1.13 2023/09/24 08:14:13 claudio Exp $ - REGRESS_FAIL_EARLY?= yes SUBDIR= test_helper sshbuf sshkey bitmap kex hostkeys utf8 match conversion -SUBDIR+=authopt misc sshsig +SUBDIR+=authopt misc sshsig pkcs11 .include -diff -Naur a/regress/unittests/pkcs11/tests.c b/regress/unittests/pkcs11/tests.c ---- a/regress/unittests/pkcs11/tests.c 1970-01-01 06:00:00.000000000 +0600 -+++ b/regress/unittests/pkcs11/tests.c 2023-10-20 19:11:41.814164432 +0600 +diff -up openssh-9.6p1/regress/unittests/pkcs11/tests.c.pkcs11-uri openssh-9.6p1/regress/unittests/pkcs11/tests.c +--- openssh-9.6p1/regress/unittests/pkcs11/tests.c.pkcs11-uri 2024-01-12 14:25:25.233942336 +0100 ++++ openssh-9.6p1/regress/unittests/pkcs11/tests.c 2024-01-12 14:25:25.233942336 +0100 @@ -0,0 +1,346 @@ +/* + * Copyright (c) 2017 Red Hat @@ -883,10 +869,9 @@ diff -Naur a/regress/unittests/pkcs11/tests.c b/regress/unittests/pkcs11/tests.c + test_parse_invalid(); + test_generate_valid(); +} -\ В конце файла нет новой строки -diff -Naur a/ssh-add.c b/ssh-add.c ---- a/ssh-add.c 2023-07-19 12:31:34.000000000 +0600 -+++ b/ssh-add.c 2023-10-20 19:11:41.814164432 +0600 +diff -up openssh-9.6p1/ssh-add.c.pkcs11-uri openssh-9.6p1/ssh-add.c +--- openssh-9.6p1/ssh-add.c.pkcs11-uri 2023-12-18 15:59:50.000000000 +0100 ++++ openssh-9.6p1/ssh-add.c 2024-01-12 14:25:25.233942336 +0100 @@ -69,6 +69,7 @@ #include "ssh-sk.h" #include "sk-api.h" @@ -895,12 +880,16 @@ diff -Naur a/ssh-add.c b/ssh-add.c /* argv0 */ extern char *__progname; -@@ -230,6 +231,34 @@ +@@ -240,6 +241,38 @@ delete_all(int agent_fd, int qflag) return ret; } +#ifdef ENABLE_PKCS11 -+static int update_card(int, int, const char *, int, struct dest_constraint **, size_t, char *); ++static int ++update_card(int agent_fd, int add, const char *id, int qflag, ++ int key_only, int cert_only, ++ struct dest_constraint **dest_constraints, size_t ndest_constraints, ++ struct sshkey **certs, size_t ncerts, char *pin); + +int +update_pkcs11_uri(int agent_fd, int adding, const char *pkcs11_uri, int qflag, @@ -922,32 +911,35 @@ diff -Naur a/ssh-add.c b/ssh-add.c + } + pkcs11_uri_cleanup(uri); + -+ return update_card(agent_fd, adding, pkcs11_uri, qflag, -+ dest_constraints, ndest_constraints, pin); ++ return update_card(agent_fd, adding, pkcs11_uri, qflag, 1, 0, ++ dest_constraints, ndest_constraints, NULL, 0, pin); +} +#endif + static int - add_file(int agent_fd, const char *filename, int key_only, int qflag, - const char *skprovider, struct dest_constraint **dest_constraints, -@@ -445,12 +474,11 @@ - - static int + add_file(int agent_fd, const char *filename, int key_only, int cert_only, + int qflag, const char *skprovider, +@@ -460,15 +489,14 @@ static int update_card(int agent_fd, int add, const char *id, int qflag, -- struct dest_constraint **dest_constraints, size_t ndest_constraints) -+ struct dest_constraint **dest_constraints, size_t ndest_constraints, char *pin) + int key_only, int cert_only, + struct dest_constraint **dest_constraints, size_t ndest_constraints, +- struct sshkey **certs, size_t ncerts) ++ struct sshkey **certs, size_t ncerts, char *pin) { - char *pin = NULL; int r, ret = -1; + if (key_only) + ncerts = 0; + - if (add) { + if (add && pin == NULL) { if ((pin = read_passphrase("Enter passphrase for PKCS#11: ", RP_ALLOW_STDIN)) == NULL) return -1; -@@ -637,6 +665,14 @@ - const char *skprovider, struct dest_constraint **dest_constraints, - size_t ndest_constraints) +@@ -656,6 +684,14 @@ do_file(int agent_fd, int deleting, int + char *file, int qflag, const char *skprovider, + struct dest_constraint **dest_constraints, size_t ndest_constraints) { +#ifdef ENABLE_PKCS11 + if (strlen(file) >= strlen(PKCS11_URI_SCHEME) && @@ -958,24 +950,24 @@ diff -Naur a/ssh-add.c b/ssh-add.c + } +#endif if (deleting) { - if (delete_file(agent_fd, file, key_only, qflag) == -1) - return -1; -@@ -963,7 +999,7 @@ - } - if (pkcs11provider != NULL) { + if (delete_file(agent_fd, file, key_only, + cert_only, qflag) == -1) +@@ -999,7 +1035,7 @@ main(int argc, char **argv) if (update_card(agent_fd, !deleting, pkcs11provider, -- qflag, dest_constraints, ndest_constraints) == -1) -+ qflag, dest_constraints, ndest_constraints, NULL) == -1) + qflag, key_only, cert_only, + dest_constraints, ndest_constraints, +- certs, ncerts) == -1) ++ certs, ncerts, NULL) == -1) ret = 1; goto done; } -diff -Naur a/ssh-agent.c b/ssh-agent.c ---- a/ssh-agent.c 2023-07-19 12:31:34.000000000 +0600 -+++ b/ssh-agent.c 2023-10-20 19:11:41.814164432 +0600 -@@ -1379,10 +1379,72 @@ +diff -up openssh-9.6p1/ssh-agent.c.pkcs11-uri openssh-9.6p1/ssh-agent.c +--- openssh-9.7p1/ssh-agent.c.pkcs11-uri 2023-12-18 15:59:50.000000000 +0100 ++++ openssh-9.7p1/ssh-agent.c 2024-01-12 14:25:25.234942360 +0100 +@@ -1553,10 +1553,73 @@ + idtab->nentries++; } - #ifdef ENABLE_PKCS11 +static char * +sanitize_pkcs11_provider(const char *provider) +{ @@ -1037,6 +1029,7 @@ diff -Naur a/ssh-agent.c b/ssh-agent.c + return xstrdup(canonical_provider); /* simple path */ + } +} ++ + static void process_add_smartcard_key(SocketEntry *e) @@ -1046,49 +1039,54 @@ diff -Naur a/ssh-agent.c b/ssh-agent.c char **comments = NULL; int r, i, count = 0, success = 0, confirm = 0; u_int seconds = 0; -@@ -1408,33 +1470,28 @@ +@@ -1585,25 +1648,18 @@ "providers is disabled", provider); goto send; } - if (realpath(provider, canonical_provider) == NULL) { - verbose("failed PKCS#11 add of \"%.100s\": realpath: %s", - provider, strerror(errno)); -- goto send; -- } -- if (match_pattern_list(canonical_provider, allowed_providers, 0) != 1) { -- verbose("refusing PKCS#11 add of \"%.100s\": " -- "provider not allowed", canonical_provider); + sane_uri = sanitize_pkcs11_provider(provider); + if (sane_uri == NULL) goto send; - } +- if (match_pattern_list(canonical_provider, allowed_providers, 0) != 1) { +- verbose("refusing PKCS#11 add of \"%.100s\": " +- "provider not allowed", canonical_provider); +- goto send; +- } - debug_f("add %.100s", canonical_provider); -+ if (lifetime && !death) death = monotime() + lifetime; - count = pkcs11_add_provider(canonical_provider, pin, &keys, &comments); -+ + debug_f("add %.100s", sane_uri); + count = pkcs11_add_provider(sane_uri, 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); -+ id->provider = xstrdup(sane_uri); - if (*comments[i] != '\0') { - id->comment = comments[i]; - comments[i] = NULL; /* transferred */ - } else { -- id->comment = xstrdup(canonical_provider); -+ id->comment = xstrdup(sane_uri); - } - id->death = death; - id->confirm = confirm; -@@ -1453,6 +1510,7 @@ + if (comments[i] == NULL || comments[i][0] == '\0') { + free(comments[i]); +- comments[i] = xstrdup(canonical_provider); ++ comments[i] = xstrdup(sane_uri); + } + for (j = 0; j < ncerts; j++) { + if (!sshkey_is_cert(certs[j])) +@@ -1613,13 +1669,13 @@ + if (pkcs11_make_cert(keys[i], certs[j], &k) != 0) + continue; + add_p11_identity(k, xstrdup(comments[i]), +- canonical_provider, death, confirm, ++ sane_uri, death, confirm, + dest_constraints, ndest_constraints); + success = 1; + } + if (!cert_only && lookup_identity(keys[i]) == NULL) { + add_p11_identity(keys[i], comments[i], +- canonical_provider, death, confirm, ++ sane_uri, death, confirm, + dest_constraints, ndest_constraints); + keys[i] = NULL; /* transferred */ + comments[i] = NULL; /* transferred */ +@@ -1632,6 +1688,7 @@ send: free(pin); free(provider); @@ -1096,7 +1094,7 @@ diff -Naur a/ssh-agent.c b/ssh-agent.c free(keys); free(comments); free_dest_constraints(dest_constraints, ndest_constraints); -@@ -1462,7 +1520,7 @@ +@@ -1644,7 +1701,7 @@ static void process_remove_smartcard_key(SocketEntry *e) { @@ -1105,7 +1103,7 @@ diff -Naur a/ssh-agent.c b/ssh-agent.c int r, success = 0; Identity *id, *nxt; -@@ -1474,30 +1532,28 @@ +@@ -1656,30 +1713,29 @@ } free(pin); @@ -1123,9 +1121,8 @@ diff -Naur a/ssh-agent.c b/ssh-agent.c nxt = TAILQ_NEXT(id, next); /* Skip file--based keys */ if (id->provider == NULL) -- continue; + continue; - if (!strcmp(canonical_provider, id->provider)) { -+ + if (!strcmp(sane_uri, id->provider)) { TAILQ_REMOVE(&idtab->idlist, id, next); free_identity(id); @@ -1138,15 +1135,40 @@ diff -Naur a/ssh-agent.c b/ssh-agent.c else error_f("pkcs11_del_provider failed"); send: -- free(provider); + free(provider); + free(sane_uri); send_status(e, success); } #endif /* ENABLE_PKCS11 */ -diff -Naur a/ssh.c b/ssh.c ---- a/ssh.c 2023-10-20 19:13:59.298264101 +0600 -+++ b/ssh.c 2023-10-20 19:11:41.815164426 +0600 -@@ -840,6 +840,14 @@ +diff -up openssh-9.6p1/ssh_config.5.pkcs11-uri openssh-9.6p1/ssh_config.5 +--- openssh-9.6p1/ssh_config.5.pkcs11-uri 2024-01-12 14:25:25.208941721 +0100 ++++ openssh-9.6p1/ssh_config.5 2024-01-12 14:25:25.234942360 +0100 +@@ -1216,6 +1216,21 @@ may also be used in conjunction with + .Cm CertificateFile + in order to provide any certificate also needed for authentication with + the identity. ++.Pp ++The authentication identity can be also specified in a form of PKCS#11 URI ++starting with a string ++.Cm pkcs11: . ++There is supported a subset of the PKCS#11 URI as defined ++in RFC 7512 (implemented path arguments ++.Cm id , ++.Cm manufacturer , ++.Cm object , ++.Cm token ++and query arguments ++.Cm module-path ++and ++.Cm pin-value ++). The URI can not be in quotes. + .It Cm IgnoreUnknown + Specifies a pattern-list of unknown options to be ignored if they are + encountered in configuration parsing. +diff -up openssh-9.6p1/ssh.c.pkcs11-uri openssh-9.6p1/ssh.c +--- openssh-9.6p1/ssh.c.pkcs11-uri 2024-01-12 14:25:25.208941721 +0100 ++++ openssh-9.6p1/ssh.c 2024-01-12 14:25:25.234942360 +0100 +@@ -882,6 +882,14 @@ main(int ac, char **av) options.gss_deleg_creds = 1; break; case 'i': @@ -1161,7 +1183,7 @@ diff -Naur a/ssh.c b/ssh.c p = tilde_expand_filename(optarg, getuid()); if (stat(p, &st) == -1) fprintf(stderr, "Warning: Identity file %s " -@@ -1712,6 +1720,7 @@ +@@ -1784,6 +1792,7 @@ main(int ac, char **av) #ifdef ENABLE_PKCS11 (void)pkcs11_del_provider(options.pkcs11_provider); #endif @@ -1169,7 +1191,7 @@ diff -Naur a/ssh.c b/ssh.c skip_connect: exit_status = ssh_session2(ssh, cinfo); -@@ -2228,6 +2237,45 @@ +@@ -2307,6 +2316,45 @@ ssh_session2(struct ssh *ssh, const stru options.escape_char : SSH_ESCAPECHAR_NONE, id); } @@ -1215,7 +1237,7 @@ diff -Naur a/ssh.c b/ssh.c /* Loads all IdentityFile and CertificateFile keys */ static void load_public_identity_files(const struct ssh_conn_info *cinfo) -@@ -2242,11 +2290,6 @@ +@@ -2321,11 +2369,6 @@ load_public_identity_files(const struct char *certificate_files[SSH_MAX_CERTIFICATE_FILES]; struct sshkey *certificates[SSH_MAX_CERTIFICATE_FILES]; int certificate_file_userprovided[SSH_MAX_CERTIFICATE_FILES]; @@ -1227,7 +1249,7 @@ diff -Naur a/ssh.c b/ssh.c n_ids = n_certs = 0; memset(identity_files, 0, sizeof(identity_files)); -@@ -2259,33 +2302,46 @@ +@@ -2338,33 +2381,46 @@ load_public_identity_files(const struct sizeof(certificate_file_userprovided)); #ifdef ENABLE_PKCS11 @@ -1293,35 +1315,10 @@ diff -Naur a/ssh.c b/ssh.c filename = default_client_percent_dollar_expand(cp, cinfo); free(cp); check_load(sshkey_load_public(filename, &public, NULL), -diff -Naur a/ssh_config.5 b/ssh_config.5 ---- a/ssh_config.5 2023-10-20 19:13:59.299264095 +0600 -+++ b/ssh_config.5 2023-10-20 19:11:41.815164426 +0600 -@@ -1124,6 +1124,21 @@ - .Cm CertificateFile - in order to provide any certificate also needed for authentication with - the identity. -+.Pp -+The authentication identity can be also specified in a form of PKCS#11 URI -+starting with a string -+.Cm pkcs11: . -+There is supported a subset of the PKCS#11 URI as defined -+in RFC 7512 (implemented path arguments -+.Cm id , -+.Cm manufacturer , -+.Cm object , -+.Cm token -+and query arguments -+.Cm module-path -+and -+.Cm pin-value -+). The URI can not be in quotes. - .It Cm IgnoreUnknown - Specifies a pattern-list of unknown options to be ignored if they are - encountered in configuration parsing. -diff -Naur a/ssh-keygen.c b/ssh-keygen.c ---- a/ssh-keygen.c 2023-07-19 12:31:34.000000000 +0600 -+++ b/ssh-keygen.c 2023-10-20 19:11:41.816164419 +0600 -@@ -866,8 +866,11 @@ +diff -up openssh-9.6p1/ssh-keygen.c.pkcs11-uri openssh-9.6p1/ssh-keygen.c +--- openssh-9.6p1/ssh-keygen.c.pkcs11-uri 2023-12-18 15:59:50.000000000 +0100 ++++ openssh-9.6p1/ssh-keygen.c 2024-01-12 14:25:25.234942360 +0100 +@@ -862,8 +862,11 @@ do_download(struct passwd *pw) free(fp); } else { (void) sshkey_write(keys[i], stdout); /* XXX check */ @@ -1335,10 +1332,30 @@ diff -Naur a/ssh-keygen.c b/ssh-keygen.c } free(comments[i]); sshkey_free(keys[i]); -diff -Naur a/ssh-pkcs11.c b/ssh-pkcs11.c ---- a/ssh-pkcs11.c 2023-07-19 12:31:34.000000000 +0600 -+++ b/ssh-pkcs11.c 2023-10-20 19:15:23.755711022 +0600 -@@ -55,8 +55,8 @@ +diff -up openssh-9.6p1/ssh-pkcs11-client.c.pkcs11-uri openssh-9.6p1/ssh-pkcs11-client.c +--- openssh-9.6p1/ssh-pkcs11-client.c.pkcs11-uri 2023-12-18 15:59:50.000000000 +0100 ++++ openssh-9.6p1/ssh-pkcs11-client.c 2024-01-12 14:25:25.234942360 +0100 +@@ -592,6 +592,8 @@ pkcs11_add_provider(char *name, char *pi + struct sshbuf *msg; + struct helper *helper; + ++ debug_f("called, name = %s", name); ++ + if ((helper = helper_by_provider(name)) == NULL && + (helper = pkcs11_start_helper(name)) == NULL) + return -1; +@@ -612,6 +614,7 @@ pkcs11_add_provider(char *name, char *pi + *keysp = xcalloc(nkeys, sizeof(struct sshkey *)); + if (labelsp) + *labelsp = xcalloc(nkeys, sizeof(char *)); ++ debug_f("nkeys = %u", nkeys); + for (i = 0; i < nkeys; i++) { + /* XXX clean up properly instead of fatal() */ + if ((r = sshbuf_get_string(msg, &blob, &blen)) != 0 || +diff -up openssh-9.6p1/ssh-pkcs11.c.pkcs11-uri openssh-9.6p1/ssh-pkcs11.c +--- openssh-9.6p1/ssh-pkcs11.c.pkcs11-uri 2023-12-18 15:59:50.000000000 +0100 ++++ openssh-9.6p1/ssh-pkcs11.c 2024-01-12 14:28:09.170975480 +0100 +@@ -55,8 +55,8 @@ struct pkcs11_slotinfo { int logged_in; }; @@ -1349,7 +1366,7 @@ diff -Naur a/ssh-pkcs11.c b/ssh-pkcs11.c void *handle; CK_FUNCTION_LIST *function_list; CK_INFO info; -@@ -65,6 +65,13 @@ +@@ -65,6 +65,13 @@ struct pkcs11_provider { struct pkcs11_slotinfo *slotinfo; int valid; int refcount; @@ -1363,7 +1380,7 @@ diff -Naur a/ssh-pkcs11.c b/ssh-pkcs11.c TAILQ_ENTRY(pkcs11_provider) next; }; -@@ -75,6 +82,7 @@ +@@ -75,6 +82,7 @@ struct pkcs11_key { CK_ULONG slotidx; char *keyid; int keyid_len; @@ -1371,7 +1388,7 @@ diff -Naur a/ssh-pkcs11.c b/ssh-pkcs11.c }; int pkcs11_interactive = 0; -@@ -106,26 +114,61 @@ +@@ -106,26 +114,61 @@ pkcs11_init(int interactive) * this is called when a provider gets unregistered. */ static void @@ -1400,9 +1417,6 @@ diff -Naur a/ssh-pkcs11.c b/ssh-pkcs11.c - if ((rv = p->function_list->C_Finalize(NULL)) != CKR_OK) + if ((rv = m->function_list->C_Finalize(NULL)) != CKR_OK) error("C_Finalize failed: %lu", rv); -- p->valid = 0; -- p->function_list = NULL; -- dlclose(p->handle); + m->valid = 0; + m->function_list = NULL; + dlclose(m->handle); @@ -1441,11 +1455,13 @@ diff -Naur a/ssh-pkcs11.c b/ssh-pkcs11.c + return; + pkcs11_module_unref(p->module); + p->module = NULL; -+ p->valid = 0; + p->valid = 0; +- p->function_list = NULL; +- dlclose(p->handle); } /* -@@ -137,12 +180,10 @@ +@@ -137,11 +180,9 @@ pkcs11_provider_unref(struct pkcs11_prov { debug_f("provider \"%s\" refcount %d", p->name, p->refcount); if (--p->refcount <= 0) { @@ -1454,13 +1470,12 @@ diff -Naur a/ssh-pkcs11.c b/ssh-pkcs11.c free(p->name); - free(p->slotlist); - free(p->slotinfo); - free(p); + if (p->module) + pkcs11_module_unref(p->module); + free(p); } } - -@@ -159,6 +200,20 @@ +@@ -159,6 +200,20 @@ pkcs11_terminate(void) } } @@ -1481,7 +1496,7 @@ diff -Naur a/ssh-pkcs11.c b/ssh-pkcs11.c /* lookup provider by name */ static struct pkcs11_provider * pkcs11_provider_lookup(char *provider_id) -@@ -173,19 +228,55 @@ +@@ -173,19 +228,55 @@ pkcs11_provider_lookup(char *provider_id return (NULL); } @@ -1491,7 +1506,6 @@ diff -Naur a/ssh-pkcs11.c b/ssh-pkcs11.c int pkcs11_del_provider(char *provider_id) { -- struct pkcs11_provider *p; + int rv; + struct pkcs11_uri *uri; + @@ -1521,7 +1535,7 @@ diff -Naur a/ssh-pkcs11.c b/ssh-pkcs11.c +int +pkcs11_del_provider_by_uri(struct pkcs11_uri *uri) +{ -+ struct pkcs11_provider *p; + struct pkcs11_provider *p; + int rv = -1; + char *provider_uri = pkcs11_uri_get(uri); + @@ -1541,7 +1555,7 @@ diff -Naur a/ssh-pkcs11.c b/ssh-pkcs11.c } static RSA_METHOD *rsa_method; -@@ -195,6 +286,56 @@ +@@ -195,6 +286,56 @@ static EC_KEY_METHOD *ec_key_method; static int ec_key_idx = 0; #endif /* OPENSSL_HAS_ECC && HAVE_EC_KEY_METHOD_NEW */ @@ -1598,7 +1612,7 @@ diff -Naur a/ssh-pkcs11.c b/ssh-pkcs11.c /* release a wrapped object */ static void pkcs11_k11_free(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, -@@ -208,6 +349,7 @@ +@@ -208,6 +349,7 @@ pkcs11_k11_free(void *parent, void *ptr, if (k11->provider) pkcs11_provider_unref(k11->provider); free(k11->keyid); @@ -1606,7 +1620,7 @@ diff -Naur a/ssh-pkcs11.c b/ssh-pkcs11.c free(k11); } -@@ -222,8 +364,8 @@ +@@ -222,8 +364,8 @@ pkcs11_find(struct pkcs11_provider *p, C CK_RV rv; int ret = -1; @@ -1617,7 +1631,7 @@ diff -Naur a/ssh-pkcs11.c b/ssh-pkcs11.c if ((rv = f->C_FindObjectsInit(session, attr, nattr)) != CKR_OK) { error("C_FindObjectsInit failed (nattr %lu): %lu", nattr, rv); return (-1); -@@ -260,14 +402,14 @@ +@@ -260,14 +402,14 @@ pkcs11_login_slot(struct pkcs11_provider if (si->token.flags & CKF_PROTECTED_AUTHENTICATION_PATH) verbose("Deferring PIN entry to reader keypad."); else { @@ -1635,7 +1649,7 @@ diff -Naur a/ssh-pkcs11.c b/ssh-pkcs11.c (pin != NULL) ? strlen(pin) : 0); if (pin != NULL) freezero(pin, strlen(pin)); -@@ -297,13 +439,14 @@ +@@ -297,13 +439,14 @@ pkcs11_login_slot(struct pkcs11_provider static int pkcs11_login(struct pkcs11_key *k11, CK_USER_TYPE type) { @@ -1652,7 +1666,7 @@ diff -Naur a/ssh-pkcs11.c b/ssh-pkcs11.c } -@@ -319,13 +462,14 @@ +@@ -319,13 +462,14 @@ pkcs11_check_obj_bool_attrib(struct pkcs *val = 0; @@ -1670,7 +1684,7 @@ diff -Naur a/ssh-pkcs11.c b/ssh-pkcs11.c attr.type = type; attr.pValue = &flag; -@@ -356,13 +500,14 @@ +@@ -356,13 +500,14 @@ pkcs11_get_key(struct pkcs11_key *k11, C int always_auth = 0; int did_login = 0; @@ -1688,7 +1702,7 @@ diff -Naur a/ssh-pkcs11.c b/ssh-pkcs11.c if ((si->token.flags & CKF_LOGIN_REQUIRED) && !si->logged_in) { if (pkcs11_login(k11, CKU_USER) < 0) { -@@ -439,8 +584,8 @@ +@@ -439,8 +584,8 @@ pkcs11_rsa_private_encrypt(int flen, con return (-1); } @@ -1699,7 +1713,7 @@ diff -Naur a/ssh-pkcs11.c b/ssh-pkcs11.c tlen = RSA_size(rsa); /* XXX handle CKR_BUFFER_TOO_SMALL */ -@@ -484,7 +629,7 @@ +@@ -484,7 +629,7 @@ pkcs11_rsa_start_wrapper(void) /* redirect private key operations for rsa key to pkcs11 token */ static int pkcs11_rsa_wrap(struct pkcs11_provider *provider, CK_ULONG slotidx, @@ -1708,7 +1722,7 @@ diff -Naur a/ssh-pkcs11.c b/ssh-pkcs11.c { struct pkcs11_key *k11; -@@ -502,6 +647,12 @@ +@@ -502,6 +647,12 @@ pkcs11_rsa_wrap(struct pkcs11_provider * memcpy(k11->keyid, keyid_attrib->pValue, k11->keyid_len); } @@ -1721,7 +1735,7 @@ diff -Naur a/ssh-pkcs11.c b/ssh-pkcs11.c RSA_set_method(rsa, rsa_method); RSA_set_ex_data(rsa, rsa_idx, k11); return (0); -@@ -532,8 +683,8 @@ +@@ -532,8 +683,8 @@ ecdsa_do_sign(const unsigned char *dgst, return (NULL); } @@ -1732,7 +1746,7 @@ diff -Naur a/ssh-pkcs11.c b/ssh-pkcs11.c siglen = ECDSA_size(ec); sig = xmalloc(siglen); -@@ -598,7 +749,7 @@ +@@ -598,7 +749,7 @@ pkcs11_ecdsa_start_wrapper(void) static int pkcs11_ecdsa_wrap(struct pkcs11_provider *provider, CK_ULONG slotidx, @@ -1741,7 +1755,7 @@ diff -Naur a/ssh-pkcs11.c b/ssh-pkcs11.c { struct pkcs11_key *k11; -@@ -615,6 +766,11 @@ +@@ -615,6 +766,12 @@ pkcs11_ecdsa_wrap(struct pkcs11_provider k11->keyid = xmalloc(k11->keyid_len); memcpy(k11->keyid, keyid_attrib->pValue, k11->keyid_len); } @@ -1750,31 +1764,21 @@ diff -Naur a/ssh-pkcs11.c b/ssh-pkcs11.c + memcpy(k11->label, label_attrib->pValue, label_attrib->ulValueLen); + k11->label[label_attrib->ulValueLen] = 0; + } ++ EC_KEY_set_method(ec, ec_key_method); EC_KEY_set_ex_data(ec, ec_key_idx, k11); -@@ -622,7 +778,8 @@ +@@ -622,7 +779,8 @@ pkcs11_ecdsa_wrap(struct pkcs11_provider } #endif /* OPENSSL_HAS_ECC && HAVE_EC_KEY_METHOD_NEW */ -/* remove trailing spaces */ +/* remove trailing spaces. Note, that this does NOT guarantee the buffer + * will be null terminated if there are no trailing spaces! */ - static void + static char * rmspace(u_char *buf, size_t len) { -@@ -630,8 +787,8 @@ - - if (!len) - return; -- for (i = len - 1; i > 0; i--) -- if (i == len - 1 || buf[i] == ' ') -+ for (i = len - 1; i > 0; i--) -+ if (buf[i] == ' ') - buf[i] = '\0'; - else - break; -@@ -651,8 +808,8 @@ +@@ -654,8 +812,8 @@ pkcs11_open_session(struct pkcs11_provid CK_SESSION_HANDLE session; int login_required, ret; @@ -1785,7 +1789,7 @@ diff -Naur a/ssh-pkcs11.c b/ssh-pkcs11.c login_required = si->token.flags & CKF_LOGIN_REQUIRED; -@@ -662,9 +819,9 @@ +@@ -665,9 +823,9 @@ pkcs11_open_session(struct pkcs11_provid error("pin required"); return (-SSH_PKCS11_ERR_PIN_REQUIRED); } @@ -1797,7 +1801,7 @@ diff -Naur a/ssh-pkcs11.c b/ssh-pkcs11.c return (-1); } if (login_required && pin != NULL && strlen(pin) != 0) { -@@ -700,7 +857,8 @@ +@@ -703,7 +861,8 @@ static struct sshkey * pkcs11_fetch_ecdsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, CK_OBJECT_HANDLE *obj) { @@ -1807,7 +1811,7 @@ diff -Naur a/ssh-pkcs11.c b/ssh-pkcs11.c CK_SESSION_HANDLE session; CK_FUNCTION_LIST *f = NULL; CK_RV rv; -@@ -714,14 +872,15 @@ +@@ -717,14 +876,15 @@ pkcs11_fetch_ecdsa_pubkey(struct pkcs11_ memset(&key_attr, 0, sizeof(key_attr)); key_attr[0].type = CKA_ID; @@ -1828,7 +1832,7 @@ diff -Naur a/ssh-pkcs11.c b/ssh-pkcs11.c if (rv != CKR_OK) { error("C_GetAttributeValue failed: %lu", rv); return (NULL); -@@ -732,19 +891,19 @@ +@@ -735,19 +895,19 @@ pkcs11_fetch_ecdsa_pubkey(struct pkcs11_ * ensure that none of the others are zero length. * XXX assumes CKA_ID is always first. */ @@ -1852,7 +1856,7 @@ diff -Naur a/ssh-pkcs11.c b/ssh-pkcs11.c if (rv != CKR_OK) { error("C_GetAttributeValue failed: %lu", rv); goto fail; -@@ -756,8 +915,8 @@ +@@ -759,8 +919,8 @@ pkcs11_fetch_ecdsa_pubkey(struct pkcs11_ goto fail; } @@ -1863,7 +1867,7 @@ diff -Naur a/ssh-pkcs11.c b/ssh-pkcs11.c if (group == NULL) { ossl_error("d2i_ECPKParameters failed"); goto fail; -@@ -768,13 +927,13 @@ +@@ -771,13 +931,13 @@ pkcs11_fetch_ecdsa_pubkey(struct pkcs11_ goto fail; } @@ -1880,7 +1884,7 @@ diff -Naur a/ssh-pkcs11.c b/ssh-pkcs11.c if (octet == NULL) { ossl_error("d2i_ASN1_OCTET_STRING failed"); goto fail; -@@ -791,7 +950,7 @@ +@@ -794,7 +954,7 @@ pkcs11_fetch_ecdsa_pubkey(struct pkcs11_ goto fail; } @@ -1889,7 +1893,7 @@ diff -Naur a/ssh-pkcs11.c b/ssh-pkcs11.c goto fail; key = sshkey_new(KEY_UNSPEC); -@@ -807,7 +966,7 @@ +@@ -810,7 +970,7 @@ pkcs11_fetch_ecdsa_pubkey(struct pkcs11_ ec = NULL; /* now owned by key */ fail: @@ -1898,7 +1902,7 @@ diff -Naur a/ssh-pkcs11.c b/ssh-pkcs11.c free(key_attr[i].pValue); if (ec) EC_KEY_free(ec); -@@ -824,7 +983,8 @@ +@@ -827,7 +987,8 @@ static struct sshkey * pkcs11_fetch_rsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, CK_OBJECT_HANDLE *obj) { @@ -1908,7 +1912,7 @@ diff -Naur a/ssh-pkcs11.c b/ssh-pkcs11.c CK_SESSION_HANDLE session; CK_FUNCTION_LIST *f = NULL; CK_RV rv; -@@ -835,14 +995,15 @@ +@@ -838,14 +999,15 @@ pkcs11_fetch_rsa_pubkey(struct pkcs11_pr memset(&key_attr, 0, sizeof(key_attr)); key_attr[0].type = CKA_ID; @@ -1929,7 +1933,7 @@ diff -Naur a/ssh-pkcs11.c b/ssh-pkcs11.c if (rv != CKR_OK) { error("C_GetAttributeValue failed: %lu", rv); return (NULL); -@@ -853,19 +1014,19 @@ +@@ -856,19 +1018,19 @@ pkcs11_fetch_rsa_pubkey(struct pkcs11_pr * ensure that none of the others are zero length. * XXX assumes CKA_ID is always first. */ @@ -1953,7 +1957,7 @@ diff -Naur a/ssh-pkcs11.c b/ssh-pkcs11.c if (rv != CKR_OK) { error("C_GetAttributeValue failed: %lu", rv); goto fail; -@@ -877,8 +1038,8 @@ +@@ -880,8 +1042,8 @@ pkcs11_fetch_rsa_pubkey(struct pkcs11_pr goto fail; } @@ -1964,7 +1968,7 @@ diff -Naur a/ssh-pkcs11.c b/ssh-pkcs11.c if (rsa_n == NULL || rsa_e == NULL) { error("BN_bin2bn failed"); goto fail; -@@ -887,7 +1048,7 @@ +@@ -890,7 +1052,7 @@ pkcs11_fetch_rsa_pubkey(struct pkcs11_pr fatal_f("set key"); rsa_n = rsa_e = NULL; /* transferred */ @@ -1973,7 +1977,7 @@ diff -Naur a/ssh-pkcs11.c b/ssh-pkcs11.c goto fail; key = sshkey_new(KEY_UNSPEC); -@@ -902,7 +1063,7 @@ +@@ -905,7 +1067,7 @@ pkcs11_fetch_rsa_pubkey(struct pkcs11_pr rsa = NULL; /* now owned by key */ fail: @@ -1982,7 +1986,7 @@ diff -Naur a/ssh-pkcs11.c b/ssh-pkcs11.c free(key_attr[i].pValue); RSA_free(rsa); -@@ -913,7 +1074,8 @@ +@@ -916,7 +1078,8 @@ static int pkcs11_fetch_x509_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, CK_OBJECT_HANDLE *obj, struct sshkey **keyp, char **labelp) { @@ -1992,7 +1996,7 @@ diff -Naur a/ssh-pkcs11.c b/ssh-pkcs11.c CK_SESSION_HANDLE session; CK_FUNCTION_LIST *f = NULL; CK_RV rv; -@@ -937,14 +1099,15 @@ +@@ -940,14 +1103,15 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_p memset(&cert_attr, 0, sizeof(cert_attr)); cert_attr[0].type = CKA_ID; @@ -2013,7 +2017,7 @@ diff -Naur a/ssh-pkcs11.c b/ssh-pkcs11.c if (rv != CKR_OK) { error("C_GetAttributeValue failed: %lu", rv); return -1; -@@ -956,18 +1119,19 @@ +@@ -959,18 +1123,19 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_p * XXX assumes CKA_ID is always first. */ if (cert_attr[1].ulValueLen == 0 || @@ -2036,7 +2040,7 @@ diff -Naur a/ssh-pkcs11.c b/ssh-pkcs11.c if (rv != CKR_OK) { error("C_GetAttributeValue failed: %lu", rv); goto out; -@@ -981,8 +1145,8 @@ +@@ -984,8 +1149,8 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_p subject = xstrdup("invalid subject"); X509_NAME_free(x509_name); @@ -2047,7 +2051,7 @@ diff -Naur a/ssh-pkcs11.c b/ssh-pkcs11.c error("d2i_x509 failed"); goto out; } -@@ -1002,7 +1166,7 @@ +@@ -1005,7 +1170,7 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_p goto out; } @@ -2056,7 +2060,7 @@ diff -Naur a/ssh-pkcs11.c b/ssh-pkcs11.c goto out; key = sshkey_new(KEY_UNSPEC); -@@ -1032,7 +1196,7 @@ +@@ -1035,7 +1200,7 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_p goto out; } @@ -2065,7 +2069,7 @@ diff -Naur a/ssh-pkcs11.c b/ssh-pkcs11.c goto out; key = sshkey_new(KEY_UNSPEC); -@@ -1052,7 +1216,7 @@ +@@ -1055,7 +1220,7 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_p goto out; } out: @@ -2074,7 +2078,7 @@ diff -Naur a/ssh-pkcs11.c b/ssh-pkcs11.c free(cert_attr[i].pValue); X509_free(x509); RSA_free(rsa); -@@ -1103,11 +1267,12 @@ +@@ -1106,11 +1271,12 @@ note_key(struct pkcs11_provider *p, CK_U */ static int pkcs11_fetch_certs(struct pkcs11_provider *p, CK_ULONG slotidx, @@ -2089,13 +2093,12 @@ diff -Naur a/ssh-pkcs11.c b/ssh-pkcs11.c CK_SESSION_HANDLE session; CK_FUNCTION_LIST *f = NULL; CK_RV rv; -@@ -1124,10 +1289,24 @@ +@@ -1127,10 +1293,23 @@ pkcs11_fetch_certs(struct pkcs11_provide key_attr[0].pValue = &key_class; key_attr[0].ulValueLen = sizeof(key_class); - session = p->slotinfo[slotidx].session; - f = p->function_list; -+ + if (uri->id != NULL) { + key_attr[nattr].type = CKA_ID; + key_attr[nattr].pValue = uri->id; @@ -2117,7 +2120,7 @@ diff -Naur a/ssh-pkcs11.c b/ssh-pkcs11.c if (rv != CKR_OK) { error("C_FindObjectsInit failed: %lu", rv); goto fail; -@@ -1208,11 +1387,12 @@ +@@ -1211,11 +1390,12 @@ fail: */ static int pkcs11_fetch_keys(struct pkcs11_provider *p, CK_ULONG slotidx, @@ -2132,7 +2135,7 @@ diff -Naur a/ssh-pkcs11.c b/ssh-pkcs11.c CK_SESSION_HANDLE session; CK_FUNCTION_LIST *f = NULL; CK_RV rv; -@@ -1228,10 +1408,23 @@ +@@ -1231,10 +1411,23 @@ pkcs11_fetch_keys(struct pkcs11_provider key_attr[0].pValue = &key_class; key_attr[0].ulValueLen = sizeof(key_class); @@ -2159,7 +2162,7 @@ diff -Naur a/ssh-pkcs11.c b/ssh-pkcs11.c if (rv != CKR_OK) { error("C_FindObjectsInit failed: %lu", rv); goto fail; -@@ -1500,16 +1693,10 @@ +@@ -1503,16 +1696,10 @@ pkcs11_ecdsa_generate_private_key(struct } #endif /* WITH_PKCS11_KEYGEN */ @@ -2178,7 +2181,7 @@ diff -Naur a/ssh-pkcs11.c b/ssh-pkcs11.c int ret = -1; struct pkcs11_provider *p = NULL; void *handle = NULL; -@@ -1518,162 +1705,304 @@ +@@ -1521,162 +1708,309 @@ pkcs11_register_provider(char *provider_ CK_FUNCTION_LIST *f = NULL; CK_TOKEN_INFO *token; CK_ULONG i; @@ -2186,29 +2189,35 @@ diff -Naur a/ssh-pkcs11.c b/ssh-pkcs11.c + struct pkcs11_module *m = NULL; - if (providerp == NULL) +- goto fail; +- *providerp = NULL; +- +- if (keyp != NULL) +- *keyp = NULL; +- if (labelsp != NULL) +- *labelsp = NULL; + /* if no provider specified, fallback to p11-kit */ + if (uri->module_path == NULL) { +#ifdef PKCS11_DEFAULT_PROVIDER + provider_module = strdup(PKCS11_DEFAULT_PROVIDER); +#else + error_f("No module path provided"); - goto fail; -- *providerp = NULL; ++ goto fail; +#endif + } else { + provider_module = strdup(uri->module_path); + } - -- if (keyp != NULL) -- *keyp = NULL; -- if (labelsp != NULL) -- *labelsp = NULL; -+ + p = xcalloc(1, sizeof(*p)); + p->name = pkcs11_uri_get(uri); - if (pkcs11_provider_lookup(provider_id) != NULL) { - debug_f("provider already registered: %s", provider_id); ++ if (lib_contains_symbol(provider_module, "C_GetFunctionList") != 0) { ++ error("provider %s is not a PKCS11 library", provider_module); + goto fail; + } +- if (lib_contains_symbol(provider_id, "C_GetFunctionList") != 0) { +- error("provider %s is not a PKCS11 library", provider_id); - goto fail; + if ((m = pkcs11_provider_lookup_module(provider_module)) != NULL + && m->valid) { @@ -2227,6 +2236,7 @@ diff -Naur a/ssh-pkcs11.c b/ssh-pkcs11.c + p->module = m; + m->refcount++; } ++ /* open shared pkcs11-library */ - if ((handle = dlopen(provider_id, RTLD_NOW)) == NULL) { - error("dlopen %s failed: %s", provider_id, dlerror()); @@ -2239,7 +2249,6 @@ diff -Naur a/ssh-pkcs11.c b/ssh-pkcs11.c - p = xcalloc(1, sizeof(*p)); - p->name = xstrdup(provider_id); - p->handle = handle; -+ + p->module->handle = handle; /* setup the pkcs11 callbacks */ if ((rv = (*getfunctionlist)(&f)) != CKR_OK) { @@ -2264,15 +2273,13 @@ diff -Naur a/ssh-pkcs11.c b/ssh-pkcs11.c + provider_module, rv); goto fail; } -- rmspace(p->info.manufacturerID, sizeof(p->info.manufacturerID)); -- rmspace(p->info.libraryDescription, sizeof(p->info.libraryDescription)); -- debug("provider %s: manufacturerID <%s> cryptokiVersion %d.%d" -- " libraryDescription <%s> libraryVersion %d.%d", +- debug("provider %s: manufacturerID <%.*s> cryptokiVersion %d.%d" +- " libraryDescription <%.*s> libraryVersion %d.%d", - provider_id, -- p->info.manufacturerID, +- RMSPACE(p->info.manufacturerID), - p->info.cryptokiVersion.major, - p->info.cryptokiVersion.minor, -- p->info.libraryDescription, +- RMSPACE(p->info.libraryDescription), - p->info.libraryVersion.major, - p->info.libraryVersion.minor); - if ((rv = f->C_GetSlotList(CK_TRUE, NULL, &p->nslots)) != CKR_OK) { @@ -2316,12 +2323,12 @@ diff -Naur a/ssh-pkcs11.c b/ssh-pkcs11.c goto fail; } - p->slotinfo = xcalloc(p->nslots, sizeof(struct pkcs11_slotinfo)); ++ m->slotinfo = xcalloc(m->nslots, sizeof(struct pkcs11_slotinfo)); p->valid = 1; - nkeys = 0; - for (i = 0; i < p->nslots; i++) { - token = &p->slotinfo[i].token; - if ((rv = f->C_GetTokenInfo(p->slotlist[i], token)) -+ m->slotinfo = xcalloc(m->nslots, sizeof(struct pkcs11_slotinfo)); + m->valid = 1; + for (i = 0; i < m->nslots; i++) { + token = &m->slotinfo[i].token; @@ -2338,23 +2345,25 @@ diff -Naur a/ssh-pkcs11.c b/ssh-pkcs11.c + token->flags = 0; continue; } - rmspace(token->label, sizeof(token->label)); - rmspace(token->manufacturerID, sizeof(token->manufacturerID)); - rmspace(token->model, sizeof(token->model)); - rmspace(token->serialNumber, sizeof(token->serialNumber)); -- debug("provider %s slot %lu: label <%s> manufacturerID <%s> " -- "model <%s> serial <%s> flags 0x%lx", + debug("provider %s slot %lu: label <%.*s> " + "manufacturerID <%.*s> model <%.*s> serial <%.*s> " + "flags 0x%lx", - provider_id, (unsigned long)i, ++ provider_module, (unsigned long)i, + RMSPACE(token->label), RMSPACE(token->manufacturerID), + RMSPACE(token->model), RMSPACE(token->serialNumber), + token->flags); + } + m->module_path = provider_module; + provider_module = NULL; + -+ /* insert unconditionally -- remove if there will be no keys later */ ++ /* now owned by caller */ ++ *providerp = p; ++ + TAILQ_INSERT_TAIL(&pkcs11_providers, p, next); + p->refcount++; /* add to provider list */ -+ *providerp = p; -+ return 0; + ++ return 0; +fail: + if (need_finalize && (rv = f->C_Finalize(NULL)) != CKR_OK) + error("C_Finalize for provider %s failed: %lu", @@ -2370,7 +2379,7 @@ diff -Naur a/ssh-pkcs11.c b/ssh-pkcs11.c + } + if (handle) + dlclose(handle); -+ return ret; ++ return (ret); +} + +/* @@ -2436,12 +2445,12 @@ diff -Naur a/ssh-pkcs11.c b/ssh-pkcs11.c + debug("provider %s slot %lu: label <%.32s> manufacturerID <%.32s> " + "model <%.16s> serial <%.16s> flags 0x%lx", + provider_uri, (unsigned long)i, - token->label, token->manufacturerID, token->model, - token->serialNumber, token->flags); ++ token->label, token->manufacturerID, token->model, ++ token->serialNumber, token->flags); /* - * open session, login with pin and retrieve public - * keys (if keyp is provided) -+ * open session if not yet openend, login with pin and ++ * open session if not yet opened, login with pin and + * retrieve public keys (if keyp is provided) */ - if ((ret = pkcs11_open_session(p, i, pin, user)) != 0 || @@ -2490,8 +2499,8 @@ diff -Naur a/ssh-pkcs11.c b/ssh-pkcs11.c - TAILQ_INSERT_TAIL(&pkcs11_providers, p, next); - p->refcount++; /* add to provider list */ +- + free(provider_uri); - return (nkeys); fail: - if (need_finalize && (rv = f->C_Finalize(NULL)) != CKR_OK) @@ -2502,8 +2511,8 @@ diff -Naur a/ssh-pkcs11.c b/ssh-pkcs11.c - free(p->slotlist); - free(p->slotinfo); - free(p); -+ TAILQ_REMOVE(&pkcs11_providers, p, next); -+ pkcs11_provider_unref(p); ++ TAILQ_REMOVE(&pkcs11_providers, p, next); ++ pkcs11_provider_unref(p); } - if (handle) - dlclose(handle); @@ -2561,7 +2570,7 @@ diff -Naur a/ssh-pkcs11.c b/ssh-pkcs11.c /* no keys found or some other error, de-register provider */ if (nkeys <= 0 && p != NULL) { -@@ -1682,7 +2011,37 @@ +@@ -1685,7 +2019,37 @@ pkcs11_add_provider(char *provider_id, c pkcs11_provider_unref(p); } if (nkeys == 0) @@ -2600,29 +2609,9 @@ diff -Naur a/ssh-pkcs11.c b/ssh-pkcs11.c return (nkeys); } -diff -Naur a/ssh-pkcs11-client.c b/ssh-pkcs11-client.c ---- a/ssh-pkcs11-client.c 2023-07-19 12:31:34.000000000 +0600 -+++ b/ssh-pkcs11-client.c 2023-10-20 19:11:41.817164413 +0600 -@@ -323,6 +323,8 @@ - u_int nkeys, i; - struct sshbuf *msg; - -+ debug_f("called, name = %s", name); -+ - if (fd < 0 && pkcs11_start_helper() < 0) - return (-1); - -@@ -342,6 +344,7 @@ - *keysp = xcalloc(nkeys, sizeof(struct sshkey *)); - if (labelsp) - *labelsp = xcalloc(nkeys, sizeof(char *)); -+ debug_f("nkeys = %u", nkeys); - for (i = 0; i < nkeys; i++) { - /* XXX clean up properly instead of fatal() */ - if ((r = sshbuf_get_string(msg, &blob, &blen)) != 0 || -diff -Naur a/ssh-pkcs11.h b/ssh-pkcs11.h ---- a/ssh-pkcs11.h 2023-07-19 12:31:34.000000000 +0600 -+++ b/ssh-pkcs11.h 2023-10-20 19:11:41.817164413 +0600 +diff -up openssh-9.6p1/ssh-pkcs11.h.pkcs11-uri openssh-9.6p1/ssh-pkcs11.h +--- openssh-9.6p1/ssh-pkcs11.h.pkcs11-uri 2023-12-18 15:59:50.000000000 +0100 ++++ openssh-9.6p1/ssh-pkcs11.h 2024-01-12 14:25:25.235942385 +0100 @@ -22,10 +22,14 @@ #define SSH_PKCS11_ERR_PIN_REQUIRED 4 #define SSH_PKCS11_ERR_PIN_LOCKED 5 @@ -2638,9 +2627,9 @@ diff -Naur a/ssh-pkcs11.h b/ssh-pkcs11.h #ifdef WITH_PKCS11_KEYGEN struct sshkey * pkcs11_gakp(char *, char *, unsigned int, char *, unsigned int, -diff -Naur a/ssh-pkcs11-uri.c b/ssh-pkcs11-uri.c ---- a/ssh-pkcs11-uri.c 1970-01-01 06:00:00.000000000 +0600 -+++ b/ssh-pkcs11-uri.c 2023-10-20 19:11:41.817164413 +0600 +diff -up openssh-9.6p1/ssh-pkcs11-uri.c.pkcs11-uri openssh-9.6p1/ssh-pkcs11-uri.c +--- openssh-9.6p1/ssh-pkcs11-uri.c.pkcs11-uri 2024-01-12 14:25:25.235942385 +0100 ++++ openssh-9.6p1/ssh-pkcs11-uri.c 2024-01-12 14:25:25.235942385 +0100 @@ -0,0 +1,437 @@ +/* + * Copyright (c) 2017 Red Hat @@ -3079,11 +3068,10 @@ diff -Naur a/ssh-pkcs11-uri.c b/ssh-pkcs11-uri.c +} + +#endif /* ENABLE_PKCS11 */ -\ В конце файла нет новой строки -diff -Naur a/ssh-pkcs11-uri.h b/ssh-pkcs11-uri.h ---- a/ssh-pkcs11-uri.h 1970-01-01 06:00:00.000000000 +0600 -+++ b/ssh-pkcs11-uri.h 2023-10-20 19:11:41.818164406 +0600 -@@ -0,0 +1,42 @@ +diff -up openssh-9.6p1/ssh-pkcs11-uri.h.pkcs11-uri openssh-9.6p1/ssh-pkcs11-uri.h +--- openssh-9.6p1/ssh-pkcs11-uri.h.pkcs11-uri 2024-01-12 14:25:25.235942385 +0100 ++++ openssh-9.6p1/ssh-pkcs11-uri.h 2024-01-12 14:25:25.235942385 +0100 +@@ -0,0 +1,43 @@ +/* + * Copyright (c) 2017 Red Hat + * @@ -3126,3 +3114,4 @@ diff -Naur a/ssh-pkcs11-uri.h b/ssh-pkcs11-uri.h +int pkcs11_uri_parse(const char *, struct pkcs11_uri *); +struct pkcs11_uri *pkcs11_uri_init(); +char *pkcs11_uri_get(struct pkcs11_uri *uri); ++ diff --git a/openssh/openssh.spec b/openssh/openssh.spec index 4429041..b87cc08 100644 --- a/openssh/openssh.spec +++ b/openssh/openssh.spec @@ -1,4 +1,8 @@ # Do we want SELinux & Audit +%if 0%{?rhel} < 7 +%global noselinux 1 +%endif + %if 0%{?!noselinux:1} %global WITH_SELINUX 1 %else @@ -32,6 +36,12 @@ %global pam_ssh_agent 0 %endif +%if 0%{?fedora} || 0%{?rhel} >= 8 +%global _emptydir %{_datadir}/empty.sshd +%else +%global _emptydir %{_localstatedir}/empty/sshd +%endif + # Reserve options to override askpass settings with: # rpm -ba|--rebuild --define 'skip_xxx 1' %{?skip_gnome_askpass:%global no_gnome_askpass 1} @@ -46,10 +56,10 @@ %{?static_openssl:%global static_libcrypto 1} # Do not forget to bump pam_ssh_agent_auth release if you rewind the main package release to 1 -%global openssh_ver 9.3p2 +%global openssh_ver 9.7p1 %global openssh_rel 1 %global pam_ssh_agent_ver 0.10.4 -%global pam_ssh_agent_rel 11 +%global pam_ssh_agent_rel 13 Summary: An open source implementation of SSH protocol version 2 Name: openssh @@ -59,7 +69,15 @@ URL: http://www.openssh.com/portable.html #URL1: https://github.com/jbeverly/pam_ssh_agent_auth/ Source0: ftp://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-%{version}.tar.gz Source1: ftp://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-%{version}.tar.gz.asc +%if 0%{?rhel} >= 8 Source2: sshd.pam +%else +%if 0%{?rhel} == 7 +Source2: sshd.pam.el7 +%else +Source2: sshd.pam.el6 +%endif +%endif Source3: gpgkey-736060BA.gpg Source4: https://github.com/jbeverly/pam_ssh_agent_auth/archive/pam_ssh_agent_auth-%{pam_ssh_agent_ver}.tar.gz Source5: pam_ssh_agent-rmheaders @@ -80,6 +98,7 @@ Source21: ssh-host-keys-migration.service Source22: openssh.pam Source23: openssh.ssh_config Source24: openssh.sshd_config +Source25: sshd.init #https://bugzilla.mindrot.org/show_bug.cgi?id=2581 Patch100: openssh-6.7p1-coverity.patch @@ -145,7 +164,7 @@ Patch711: openssh-7.8p1-UsePAM-warning.patch # Reenable MONITOR_REQ_GSSCHECKMIC after gssapi-with-mic failures # upstream MR: # https://github.com/openssh-gsskex/openssh-gsskex/pull/21 -Patch800: openssh-9.3p1-gssapi-keyex.patch +Patch800: openssh-9.7p1-gssapi-keyex.patch #http://www.mail-archive.com/kerberos@mit.edu/msg17591.html Patch801: openssh-6.6p1-force_krb.patch # add new option GSSAPIEnablek5users and disable using ~/.k5users by default (#1169843) @@ -185,7 +204,7 @@ Patch950: openssh-7.5p1-sandbox.patch # PKCS#11 URIs (upstream #2817, 2nd iteration) # https://github.com/Jakuje/openssh-portable/commits/jjelen-pkcs11 # git show > ~/devel/fedora/openssh/openssh-8.0p1-pkcs11-uri.patch -Patch951: openssh-9.3p2-pkcs11-uri.patch +Patch951: openssh-9.7p1-pkcs11-uri.patch # Unbreak scp between two IPv6 hosts (#1620333) Patch953: openssh-7.8p1-scp-ipv6.patch # Mention crypto-policies in manual pages (#1668325) @@ -227,14 +246,11 @@ Patch1002: openssh-8.7p1-ssh-manpage.patch # Don't propose disallowed algorithms during hostkey negotiation # upstream MR: # https://github.com/openssh/openssh-portable/pull/323 -Patch1006: openssh-8.7p1-negotiate-supported-algs.patch +Patch1006: openssh-9.7p1-negotiate-supported-algs.patch Patch1012: openssh-9.0p1-evp-fips-dh.patch Patch1013: openssh-9.0p1-evp-fips-ecdh.patch -Patch1014: openssh-8.7p1-nohostsha1proof.patch - -# upstream b7afd8a4ecaca8afd3179b55e9db79c0ff210237 -Patch1016: openssh-9.3p1-openssl-compat.patch +Patch1014: openssh-9.7p1-nohostsha1proof.patch License: BSD-3-Clause AND BSD-2-Clause AND ISC AND SSH-OpenSSH AND ssh-keyscan AND sprintf AND LicenseRef-Fedora-Public-Domain AND X11-distribute-modifications-variant Requires: /sbin/nologin @@ -253,10 +269,22 @@ BuildRequires: audit-libs-devel >= 2.0.5 BuildRequires: util-linux, groff BuildRequires: pam-devel BuildRequires: openssl3-devel >= 0.9.8j +%if 0%{?fedora} || 0%{?rhel} >= 7 BuildRequires: perl-podlators BuildRequires: systemd-devel BuildRequires: systemd-rpm-macros -BuildRequires: gcc make +%else +BuildRequires: perl +%endif +%if 0%{?fedora} || 0%{?rhel} != 7 +BuildRequires: gcc +%else +BuildRequires: devtoolset-12-gcc devtoolset-12-build +%if 0%{?rhel} < 7 +BuildRequires: autoconf2.69 automake1.16 m4 +%endif +%endif +BuildRequires: make BuildRequires: p11-kit-devel BuildRequires: libfido2-devel Requires: p11-kit @@ -272,10 +300,11 @@ BuildRequires: libedit-devel ncurses-devel %endif %if %{WITH_SELINUX} -Requires: libselinux >= 2.3-5 -BuildRequires: libselinux-devel >= 2.3-5 +Requires: libselinux +BuildRequires: libselinux-devel Requires: audit-libs >= 1.0.8 BuildRequires: audit-libs >= 1.0.8 +BuildRequires: pkgconfig(libseccomp) %endif BuildRequires: xauth @@ -297,7 +326,11 @@ Requires: pam >= 1.0.1-3 %if 0%{?rhel} >= 8 Requires: crypto-policies >= 20220824-1 %endif +%if 0%{?fedora} || 0%{?rhel} >= 7 %{?systemd_requires} +%else +Requires(post): chkconfig >= 0.9, /sbin/service +%endif %package keycat Summary: A mls keycat backend for openssh @@ -368,84 +401,85 @@ gpgv2 --quiet --keyring %{SOURCE3} %{SOURCE1} %{SOURCE0} %if %{pam_ssh_agent} pushd pam_ssh_agent_auth-pam_ssh_agent_auth-%{pam_ssh_agent_ver} -%patch -P 300 -p2 -b .psaa-build -%patch -P 301 -p2 -b .psaa-seteuid -%patch -P 302 -p2 -b .psaa-visibility -%patch -P 306 -p2 -b .psaa-compat -%patch -P 305 -p2 -b .psaa-agent -%patch -P 307 -p2 -b .psaa-deref -%patch -P 308 -p2 -b .rsasha2 -%patch -P 309 -p1 -b .psaa-configure-c99 +%patch300 -p2 -b .psaa-build +%patch301 -p2 -b .psaa-seteuid +%patch302 -p2 -b .psaa-visibility +%patch306 -p2 -b .psaa-compat +%patch305 -p2 -b .psaa-agent +%patch307 -p2 -b .psaa-deref +%patch308 -p2 -b .rsasha2 +%patch309 -p1 -b .psaa-configure-c99 # Remove duplicate headers and library files rm -f $(cat %{SOURCE5}) popd %endif -%patch -P 400 -p1 -b .role-mls -%patch -P 404 -p1 -b .privsep-selinux +%patch400 -p1 -b .role-mls +%patch404 -p1 -b .privsep-selinux -%patch -P 502 -p1 -b .keycat +%patch502 -p1 -b .keycat -%patch -P 601 -p1 -b .ip-opts -%patch -P 606 -p1 -b .ipv6man -%patch -P 607 -p1 -b .sigpipe -%patch -P 609 -p1 -b .x11 -%patch -P 702 -p1 -b .progress -%patch -P 703 -p1 -b .grab-info -%patch -P 707 -p1 -b .redhat -%patch -P 711 -p1 -b .log-usepam-no -# -%patch -P 800 -p1 -b .gsskex -%patch -P 801 -p1 -b .force_krb -%patch -P 804 -p1 -b .ccache_name -%patch -P 805 -p1 -b .k5login -# -%patch -P 901 -p1 -b .kuserok -%patch -P 906 -p1 -b .fromto-remote -%patch -P 916 -p1 -b .contexts -%patch -P 918 -p1 -b .log-in-chroot -%patch -P 919 -p1 -b .scp -%patch -P 802 -p1 -b .GSSAPIEnablek5users -%patch -P 922 -p1 -b .sshdt -%patch -P 926 -p1 -b .sftp-force-mode -%patch -P 939 -p1 -b .s390-dev -%patch -P 944 -p1 -b .x11max -%patch -P 948 -p1 -b .systemd -%patch -P 949 -p1 -b .refactor -%patch -P 950 -p1 -b .sandbox -%patch -P 951 -p1 -b .pkcs11-uri -%patch -P 953 -p1 -b .scp-ipv6 +%patch601 -p1 -b .ip-opts +%patch606 -p1 -b .ipv6man +%patch607 -p1 -b .sigpipe +%patch609 -p1 -b .x11 +%patch702 -p1 -b .progress +%patch703 -p1 -b .grab-info +%patch707 -p1 -b .redhat +%patch711 -p1 -b .log-usepam-no +# +%patch800 -p1 -b .gsskex +%patch801 -p1 -b .force_krb +%patch804 -p1 -b .ccache_name +%patch805 -p1 -b .k5login +# +%patch901 -p1 -b .kuserok +%patch906 -p1 -b .fromto-remote +%patch916 -p1 -b .contexts +%patch918 -p1 -b .log-in-chroot +%patch919 -p1 -b .scp +%patch802 -p1 -b .GSSAPIEnablek5users +%patch922 -p1 -b .sshdt +%patch926 -p1 -b .sftp-force-mode +%patch939 -p1 -b .s390-dev +%patch944 -p1 -b .x11max +%patch948 -p1 -b .systemd +%patch949 -p1 -b .refactor +%patch950 -p1 -b .sandbox +%patch951 -p1 -b .pkcs11-uri +%patch953 -p1 -b .scp-ipv6 %if 0%{?rhel} >= 8 -%patch -P 962 -p1 -b .crypto-policies +%patch962 -p1 -b .crypto-policies %endif -%patch -P 963 -p1 -b .openssl-evp -%patch -P 964 -p1 -b .openssl-kdf -%patch -P 965 -p1 -b .visibility -%patch -P 966 -p1 -b .x11-ipv6 -%patch -P 974 -p1 -b .keygen-strip-doseol -%patch -P 975 -p1 -b .preserve-pam-errors +%patch963 -p1 -b .openssl-evp +%patch964 -p1 -b .openssl-kdf +%patch965 -p1 -b .visibility +%patch966 -p1 -b .x11-ipv6 +%patch974 -p1 -b .keygen-strip-doseol +%patch975 -p1 -b .preserve-pam-errors -%patch -P 977 -p1 -b .kill-scp +%patch977 -p1 -b .kill-scp -%patch -P 981 -p1 -b .scp-sftpdirs -%patch -P 982 -p1 -b .minrsabits -%patch -P 984 -p1 -b .ibmca +%patch981 -p1 -b .scp-sftpdirs +%patch982 -p1 -b .minrsabits +%patch984 -p1 -b .ibmca -%patch -P 200 -p1 -b .audit -%patch -P 201 -p1 -b .audit-race -%patch -P 202 -p1 -b .audit-log -%patch -P 700 -p1 -b .fips +%patch200 -p1 -b .audit +%patch201 -p1 -b .audit-race +%patch202 -p1 -b .audit-log +%patch700 -p1 -b .fips -%patch -P 1002 -p1 -b .ssh-manpage +%patch1002 -p1 -b .ssh-manpage -%patch -P 1006 -p1 -b .negotiate-supported-algs +%patch1006 -p1 -b .negotiate-supported-algs -%patch -P 1012 -p1 -b .evp-fips-dh -%patch -P 1013 -p1 -b .evp-fips-ecdh -%patch -P 1014 -p1 -b .nosha1hostproof -%patch -P 1016 -p1 -b .ossl-version +%patch1012 -p1 -b .evp-fips-dh +%patch1013 -p1 -b .evp-fips-ecdh +%patch1014 -p1 -b .nosha1hostproof + + +%patch100 -p1 -b .coverity -%patch -P 100 -p1 -b .coverity autoreconf pushd pam_ssh_agent_auth-pam_ssh_agent_auth-%{pam_ssh_agent_ver} @@ -453,9 +487,14 @@ autoreconf popd %build +%if 0%{?rhel} == 7 +%enable_devtoolset12 +%endif + %set_build_flags # the -fvisibility=hidden is needed for clean build of the pam_ssh_agent_auth # it is needed for lib(open)ssh build too since it is linked to the pam module too + CFLAGS="$CFLAGS -I%{_includedir}/openssl3 -fvisibility=hidden"; export CFLAGS %if %{pie} %ifarch s390 s390x sparc sparcv9 sparc64 @@ -466,6 +505,10 @@ CFLAGS="$CFLAGS -fpic" SAVE_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS -pie -z relro -z now" +%if 0%{?rhel} < 7 +LDFLAGS="$LDFLAGS -lrt" +%endif + export CFLAGS export LDFLAGS @@ -490,16 +533,24 @@ fi --sysconfdir=%{_sysconfdir}/ssh \ --libexecdir=%{_libexecdir}/openssh \ --datadir=%{_datadir}/openssh \ + --enable-vendor-patchlevel="RHEL10-%{openssh_ver}-%{openssh_rel}" \ +%if 0%{?fedora} || 0%{?rhel} >= 7 --with-default-path=/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin \ --with-superuser-path=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin \ - --with-privsep-path=%{_datadir}/empty.sshd \ +%else + --with-default-path=/usr/local/bin:/bin:/usr/bin \ + --with-superuser-path=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin \ +%endif + --with-privsep-path=%{_emptydir} \ --disable-strip \ --without-zlib-version-check \ --with-ssl-engine \ --with-ipaddr-display \ --with-pie=no \ --without-hardening `# The hardening flags are configured by system` \ +%if 0%{?fedora} || 0%{?rhel} >= 7 --with-systemd \ +%endif --with-default-pkcs11-provider=yes \ --with-security-key-builtin=yes \ --with-pam \ @@ -550,6 +601,11 @@ popd %if %{pam_ssh_agent} pushd pam_ssh_agent_auth-pam_ssh_agent_auth-%{pam_ssh_agent_ver} LDFLAGS="$SAVE_LDFLAGS -ldl" + +%if 0%{?rhel} < 7 +LDFLAGS="$LDFLAGS -lrt" +%endif + %configure --with-selinux \ --libexecdir=/%{_libdir}/security \ --with-mantype=man \ @@ -584,10 +640,12 @@ install -m644 sshd_config_redhat_cp $RPM_BUILD_ROOT%{_sysconfdir}/ssh/sshd_confi install -m644 sshd_config_redhat $RPM_BUILD_ROOT%{_sysconfdir}/ssh/sshd_config.d/50-redhat.conf install -m644 %{SOURCE2} $RPM_BUILD_ROOT/etc/pam.d/sshd %else -install -m 644 %{SOURCE22} $RPM_BUILD_ROOT/etc/pam.d/sshd install -m 644 %{SOURCE23} $RPM_BUILD_ROOT%{_sysconfdir}/ssh/ssh_config install -m 644 %{SOURCE24} $RPM_BUILD_ROOT%{_sysconfdir}/ssh/sshd_config %endif +install -m755 contrib/ssh-copy-id $RPM_BUILD_ROOT%{_bindir}/ +install contrib/ssh-copy-id.1 $RPM_BUILD_ROOT%{_mandir}/man1/ +%if 0%{?rhel} >= 7 install -d -m755 $RPM_BUILD_ROOT/%{_unitdir} install -m644 %{SOURCE9} $RPM_BUILD_ROOT/%{_unitdir}/sshd@.service install -m644 %{SOURCE10} $RPM_BUILD_ROOT/%{_unitdir}/sshd.socket @@ -598,9 +656,7 @@ install -d -m755 $RPM_BUILD_ROOT/%{_userunitdir} install -m644 %{SOURCE16} $RPM_BUILD_ROOT/%{_userunitdir}/ssh-agent.service install -m644 %{SOURCE17} $RPM_BUILD_ROOT/%{_userunitdir}/ssh-agent.socket install -m744 %{SOURCE13} $RPM_BUILD_ROOT/%{_libexecdir}/openssh/sshd-keygen -install -m755 contrib/ssh-copy-id $RPM_BUILD_ROOT%{_bindir}/ -install contrib/ssh-copy-id.1 $RPM_BUILD_ROOT%{_mandir}/man1/ -install -d -m711 ${RPM_BUILD_ROOT}/%{_datadir}/empty.sshd +install -d -m711 ${RPM_BUILD_ROOT}/%{_emptydir} install -p -D -m 0644 %{SOURCE19} %{buildroot}%{_sysusersdir}/openssh-server.conf # Migration service/script for Fedora 38 change to remove group ownership for standard host keys # See https://fedoraproject.org/wiki/Changes/SSHKeySignSuidBit @@ -609,6 +665,10 @@ install -m744 %{SOURCE20} $RPM_BUILD_ROOT/%{_libexecdir}/openssh/ssh-host-keys-m install -m644 %{SOURCE21} $RPM_BUILD_ROOT/%{_unitdir}/ssh-host-keys-migration.service install -d $RPM_BUILD_ROOT/%{_localstatedir}/lib touch $RPM_BUILD_ROOT/%{_localstatedir}/lib/.ssh-host-keys-migration +%else +install -d $RPM_BUILD_ROOT/etc/rc.d/init.d +install -m755 %{SOURCE25} $RPM_BUILD_ROOT/etc/rc.d/init.d/sshd +%endif %if ! %{no_gnome_askpass} install contrib/gnome-ssh-askpass $RPM_BUILD_ROOT%{_libexecdir}/openssh/gnome-ssh-askpass @@ -643,10 +703,16 @@ getent group ssh_keys >/dev/null || groupadd -r ssh_keys || : getent group sshd >/dev/null || groupadd -g %{sshd_uid} -r sshd || : getent passwd sshd >/dev/null || \ useradd -c "Privilege-separated SSH" -u %{sshd_uid} -g sshd \ - -s /sbin/nologin -r -d /usr/share/empty.sshd sshd 2> /dev/null || : + -s /sbin/nologin -r -d %{_emptydir} sshd 2> /dev/null || : %post server +%if 0%{?fedora} || 0%{?rhel} >= 7 %systemd_post sshd.service sshd.socket +%else +/sbin/chkconfig --add sshd +%else + +%endif %if 0%{?fedora} || 0%{?rhel} >= 8 # Migration scriptlet for Fedora 31 and 32 installations to sshd_config # drop-in directory (in F32+). @@ -662,18 +728,34 @@ test -f %{sysconfig_anaconda} && \ %endif %preun server +%if 0%{?fedora} || 0%{?rhel} >= 7 %systemd_preun sshd.service sshd.socket +%else +if [ "$1" = 0 ] +then + /sbin/service sshd stop > /dev/null 2>&1 || : + /sbin/chkconfig --del sshd +fi +%endif %postun server +%if 0%{?fedora} || 0%{?rhel} >= 7 %systemd_postun_with_restart sshd.service +%else +/sbin/service sshd condrestart > /dev/null 2>&1 || : +%endif %post clients +%if 0%{?fedora} || 0%{?rhel} >= 7 %systemd_user_post ssh-agent.service %systemd_user_post ssh-agent.socket +%endif %preun clients +%if 0%{?fedora} || 0%{?rhel} >= 7 %systemd_user_preun ssh-agent.service %systemd_user_preun ssh-agent.socket +%endif %files %doc CREDITS ChangeLog OVERVIEW PROTOCOL* README README.platform README.privsep README.tun README.dns TODO LICENCE @@ -710,14 +792,15 @@ test -f %{sysconfig_anaconda} && \ %attr(0644,root,root) %{_mandir}/man1/ssh-copy-id.1* %attr(0644,root,root) %{_mandir}/man8/ssh-pkcs11-helper.8* %attr(0644,root,root) %{_mandir}/man8/ssh-sk-helper.8* +%if 0%{?fedora} || 0%{?rhel} >= 7 %attr(0644,root,root) %{_userunitdir}/ssh-agent.service %attr(0644,root,root) %{_userunitdir}/ssh-agent.socket +%endif %files server -%dir %attr(0711,root,root) %{_datadir}/empty.sshd +%dir %attr(0711,root,root) %{_emptydir} %attr(0755,root,root) %{_sbindir}/sshd %attr(0755,root,root) %{_libexecdir}/openssh/sftp-server -%attr(0755,root,root) %{_libexecdir}/openssh/sshd-keygen %attr(0644,root,root) %{_mandir}/man5/sshd_config.5* %attr(0644,root,root) %{_mandir}/man5/moduli.5* %attr(0644,root,root) %{_mandir}/man8/sshd.8* @@ -731,6 +814,7 @@ test -f %{sysconfig_anaconda} && \ %attr(0644,root,root) %config(noreplace) /etc/pam.d/sshd %attr(0640,root,root) %config(noreplace) /etc/sysconfig/sshd +%if 0%{?fedora} || 0%{?rhel} >= 7 %attr(0644,root,root) %{_unitdir}/sshd.service %attr(0644,root,root) %{_unitdir}/sshd@.service %attr(0644,root,root) %{_unitdir}/sshd.socket @@ -739,7 +823,11 @@ test -f %{sysconfig_anaconda} && \ %attr(0644,root,root) %{_sysusersdir}/openssh-server.conf %attr(0644,root,root) %{_unitdir}/ssh-host-keys-migration.service %attr(0744,root,root) %{_libexecdir}/openssh/ssh-host-keys-migration.sh +%attr(0755,root,root) %{_libexecdir}/openssh/sshd-keygen %ghost %attr(0644,root,root) %{_localstatedir}/lib/.ssh-host-keys-migration +%else +%attr(0755,root,root) /etc/rc.d/init.d/sshd +%endif %files keycat %doc HOWTO.ssh-keycat @@ -758,12 +846,22 @@ test -f %{sysconfig_anaconda} && \ %if %{pam_ssh_agent} %files -n pam_ssh_agent_auth +%if 0%{?fedora} || 0%{?rhel} >= 8 %license pam_ssh_agent_auth-pam_ssh_agent_auth-%{pam_ssh_agent_ver}/OPENSSH_LICENSE +%else +%doc pam_ssh_agent_auth-pam_ssh_agent_auth-%{pam_ssh_agent_ver}/OPENSSH_LICENSE +%endif %attr(0755,root,root) %{_libdir}/security/pam_ssh_agent_auth.so %attr(0644,root,root) %{_mandir}/man8/pam_ssh_agent_auth.8* %endif %changelog +* Wed Feb 28 2024 Raven - 9.6p2-1 +- New upstream release + +* Fri Oct 20 2023 Raven - 9.3p2-1 +- add pam config ported from proper rhel versions + * Fri Oct 20 2023 Raven - 9.3p2-1 - New upstream release diff --git a/openssh/sshd.init b/openssh/sshd.init new file mode 100755 index 0000000..b1d6f40 --- /dev/null +++ b/openssh/sshd.init @@ -0,0 +1,236 @@ +#!/bin/bash +# +# sshd Start up the OpenSSH server daemon +# +# chkconfig: 2345 55 25 +# description: SSH is a protocol for secure remote shell access. \ +# This service starts up the 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 + +### BEGIN INIT INFO +# Provides: sshd +# Required-Start: $local_fs $network $syslog +# Required-Stop: $local_fs $syslog +# Should-Start: $syslog +# Should-Stop: $network $syslog +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: Start up the OpenSSH server daemon +# Description: SSH is a protocol for secure remote shell access. +# This service starts up the OpenSSH server daemon. +### END INIT INFO + +# source function library +. /etc/rc.d/init.d/functions + +# pull in sysconfig settings +[ -f /etc/sysconfig/sshd ] && . /etc/sysconfig/sshd + +RETVAL=0 +prog="sshd" +lockfile=/var/lock/subsys/$prog + +# Some functions to make the below more readable +KEYGEN=/usr/bin/ssh-keygen +SSHD=/usr/sbin/sshd +RSA1_KEY=/etc/ssh/ssh_host_key +RSA_KEY=/etc/ssh/ssh_host_rsa_key +DSA_KEY=/etc/ssh/ssh_host_dsa_key +PID_FILE=/var/run/sshd.pid + +runlevel=$(set -- $(runlevel); eval "echo \$$#" ) + +fips_enabled() { + if [ -r /proc/sys/crypto/fips_enabled ]; then + cat /proc/sys/crypto/fips_enabled + else + echo 0 + fi +} + +do_rsa1_keygen() { + if [ ! -s $RSA1_KEY -a `fips_enabled` -eq 0 ]; then + echo -n $"Generating SSH1 RSA host key: " + rm -f $RSA1_KEY + if test ! -f $RSA1_KEY && $KEYGEN -q -t rsa1 -f $RSA1_KEY -C '' -N '' >&/dev/null; then + chmod 600 $RSA1_KEY + chmod 644 $RSA1_KEY.pub + if [ -x /sbin/restorecon ]; then + /sbin/restorecon $RSA1_KEY.pub + fi + success $"RSA1 key generation" + echo + else + failure $"RSA1 key generation" + echo + exit 1 + fi + fi +} + +do_rsa_keygen() { + if [ ! -s $RSA_KEY ]; then + echo -n $"Generating SSH2 RSA host key: " + rm -f $RSA_KEY + if test ! -f $RSA_KEY && $KEYGEN -q -t rsa -f $RSA_KEY -C '' -N '' >&/dev/null; then + chmod 600 $RSA_KEY + chmod 644 $RSA_KEY.pub + if [ -x /sbin/restorecon ]; then + /sbin/restorecon $RSA_KEY.pub + fi + success $"RSA key generation" + echo + else + failure $"RSA key generation" + echo + exit 1 + fi + fi +} + +do_dsa_keygen() { + if [ ! -s $DSA_KEY -a `fips_enabled` -eq 0 ]; then + echo -n $"Generating SSH2 DSA host key: " + rm -f $DSA_KEY + if test ! -f $DSA_KEY && $KEYGEN -q -t dsa -f $DSA_KEY -C '' -N '' >&/dev/null; then + chmod 600 $DSA_KEY + chmod 644 $DSA_KEY.pub + if [ -x /sbin/restorecon ]; then + /sbin/restorecon $DSA_KEY.pub + fi + success $"DSA key generation" + echo + else + failure $"DSA key generation" + echo + exit 1 + fi + fi +} + +do_restart_sanity_check() +{ + $SSHD -t + RETVAL=$? + if [ $RETVAL -ne 0 ]; then + failure $"Configuration file or keys are invalid" + echo + fi +} + +start() +{ + [ -x $SSHD ] || exit 5 + [ -f /etc/ssh/sshd_config ] || exit 6 + # Create keys if necessary + if [ "x${AUTOCREATE_SERVER_KEYS}" != xNO ]; then + do_rsa_keygen + if [ "x${AUTOCREATE_SERVER_KEYS}" != xRSAONLY ]; then + do_rsa1_keygen + do_dsa_keygen + fi + fi + + echo -n $"Starting $prog: " + $SSHD $OPTIONS && success || failure + RETVAL=$? + [ $RETVAL -eq 0 ] && touch $lockfile + echo + return $RETVAL +} + +stop() +{ + echo -n $"Stopping $prog: " + killproc -p $PID_FILE $SSHD + RETVAL=$? + # if we are in halt or reboot runlevel kill all running sessions + # so the TCP connections are closed cleanly + if [ "x$runlevel" = x0 -o "x$runlevel" = x6 ] ; then + trap '' TERM + killall $prog 2>/dev/null + trap TERM + fi + [ $RETVAL -eq 0 ] && rm -f $lockfile + echo +} + +reload() +{ + echo -n $"Reloading $prog: " + killproc -p $PID_FILE $SSHD -HUP + RETVAL=$? + echo +} + +restart() { + stop + start +} + +force_reload() { + restart +} + +rh_status() { + status -p $PID_FILE openssh-daemon +} + +rh_status_q() { + rh_status >/dev/null 2>&1 +} + +case "$1" in + start) + rh_status_q && exit 0 + start + ;; + stop) + if ! rh_status_q; then + rm -f $lockfile + exit 0 + fi + stop + ;; + restart) + restart + ;; + reload) + rh_status_q || exit 7 + reload + ;; + force-reload) + force_reload + ;; + condrestart|try-restart) + rh_status_q || exit 0 + if [ -f $lockfile ] ; then + do_restart_sanity_check + if [ $RETVAL -eq 0 ] ; then + stop + # avoid race + sleep 3 + start + else + RETVAL=6 + fi + fi + ;; + status) + rh_status + RETVAL=$? + if [ $RETVAL -eq 3 -a -f $lockfile ] ; then + RETVAL=2 + fi + ;; + *) + echo $"Usage: $0 {start|stop|restart|reload|force-reload|condrestart|try-restart|status}" + RETVAL=2 +esac +exit $RETVAL diff --git a/openssh/sshd.pam.el6 b/openssh/sshd.pam.el6 new file mode 100644 index 0000000..2c10039 --- /dev/null +++ b/openssh/sshd.pam.el6 @@ -0,0 +1,14 @@ +#%PAM-1.0 +auth required pam_sepermit.so +auth include password-auth +account required pam_nologin.so +account include password-auth +password include password-auth +# pam_selinux.so close should be the first session rule +session required pam_selinux.so close +session required pam_loginuid.so +# pam_selinux.so open should only be followed by sessions to be executed in the user context +session required pam_selinux.so open env_params +session required pam_namespace.so +session optional pam_keyinit.so force revoke +session include password-auth diff --git a/openssh/sshd.pam b/openssh/sshd.pam.el7 similarity index 100% rename from openssh/sshd.pam rename to openssh/sshd.pam.el7